Default
Show the codeHide the code
Default, code
<NumberField
label="Seats"
defaultValue={2}
minValue={2}
maxValue={50}
hint="Team plans start at 2 seats."
/>A number typed or stepped with 44px buttons and the arrow keys, formatted with its unit or currency.
These are the real React components. Use them with a mouse, touch or keyboard, and switch the theme and density for every example at once.
Default, code
<NumberField
label="Seats"
defaultValue={2}
minValue={2}
maxValue={50}
hint="Team plans start at 2 seats."
/>With a unit, code
<NumberField
label="Parcel weight"
defaultValue={2.5}
minValue={0}
maxValue={30}
step={0.5}
formatOptions={{ style: 'unit', unit: 'kilogram' }}
/>Percentage, code
<NumberField
label="Discount"
defaultValue={0.1}
minValue={0}
maxValue={1}
step={0.05}
formatOptions={{ style: 'percent' }}
/>Invalid, code
<NumberField
label="Seats"
maxValue={50}
isInvalid
errorMessage="Choose at least 2 seats"
defaultValue={1}
minValue={undefined}
/>Disabled, code
<NumberField label="Seats" defaultValue={2} minValue={2} maxValue={50} isDisabled />The 17 design tokens NumberField reads, with the value each has in the theme and density chosen above. Change a token and the component follows, in Figma and in code.
| Token | Value now | CSS variable |
|---|---|---|
| color.bg.muted | … | --sd-color-bg-muted |
| color.bg.subtle | … | --sd-color-bg-subtle |
| color.border.subtle | … | --sd-color-border-subtle |
| color.icon.default | … | --sd-color-icon-default |
| color.text.disabled | … | --sd-color-text-disabled |
| focus-ring.width | … | --sd-focus-ring-width |
| input.bg | … | --sd-input-bg |
| input.bg-disabled | … | --sd-input-bg-disabled |
| input.border | … | --sd-input-border |
| input.border-hover | … | --sd-input-border-hover |
| input.border-invalid | … | --sd-input-border-invalid |
| input.fg | … | --sd-input-fg |
| input.height | … | --sd-input-height |
| input.padding-x | … | --sd-input-padding-x |
| input.placeholder | … | --sd-input-placeholder |
| input.radius | … | --sd-input-radius |
| target.min | … | --sd-target-min |
The npm package isn’t published yet. When it is, this is the install line; until then, this page runs the same build of the package (from commit fa3abf8).
Install
npm i @superduperui/react @superduperui/tokensImport
import { NumberField } from "@superduperui/react"NumberField also takes the props of the React Aria component it’s built on.
| Prop | Type | What it does |
|---|---|---|
labelrequired | string | Visible label (required). |
hint | string | |
errorMessage | string | ((validation: ValidationResult) => string) | |
placeholder | string | |
hideLabel | boolean | |
showSteppers | booleanDefault true | Show the decrease and increase buttons (44px each). Default true. |
Screen readers announce "Seats, 2, stepper"; the steppers "Increase Seats, button".
WCAG 2.2 AAA criteria the component meets in Comfortable density: 1.4.6, 1.4.9, 2.1.3, 2.3.2, 2.4.13, 2.5.5, 2.5.6.
Compact density meets AA (2.5.8, 24px targets), not AAA.
Shared patterns it ships with: 3.3.6 (out-of-range values are clamped, not cleared).
| axe-core (WCAG A, AA, AAA and best practice) | 120 runs across every story, theme, density and width: 0 violations |
|---|---|
| Rendered text contrast | 80 text runs: 0 below 7:1, lowest 8.43:1 |
| Target size | 52 targets: 0 under 44px in Comfortable |
| Focus appearance (2.4.13) | 18 focus stops in 3 browser engines: all pass |
| Keyboard script | Chromium 6 of 6, Firefox 6 of 6, WebKit 6 of 6 |
Manual passes with VoiceOver and NVDA haven’t been done yet.
Each step is scripted and run in Chromium, Firefox and WebKit.
| Key | What happens |
|---|---|
| Tab | Tab reaches the field (steppers are not tab stops) |
| ArrowUp | Up adds one |
| ArrowDown | Down takes one away |
| ArrowDown | It stops at the minimum |
| End | End jumps to the maximum |
| Home | Home jumps to the minimum |
The Figma component is NumberField, with State (Default, Hover, Focus, Disabled, Invalid); Label visibility (Visible, Hidden). The Figma library isn’t published yet.
Figma to code: State (Default, Hover, Focus, Disabled = isDisabled, Invalid = isInvalid); Label visibility → hideLabel (Visible = false, Hidden = true); Value → defaultValue (number; formatted by formatOptions); Show steppers → showSteppers; nested Label → label; nested Hint → hint; nested FieldError → errorMessage.