NumberField
A number you can type or step, with arrow keys and two buttons.
SourcePackage @weft-js/warp
Preview
tsx
import { NumberField } from '@weft-js/warp'export function Basic() { return ( <NumberField label="Retries" defaultValue={3} min={0} max={10} /> )}const min = 60_000Installation
npm install @weft-js/warpUsage
tsx
import { NumberField } from '@weft-js/warp'<NumberField label="Retries" defaultValue={3} min={0} max={10} />Sizes
size matches the other fields in a form.
tsx
import { NumberField, Stack } from '@weft-js/warp'export function Sizes() { return ( <Stack gap="group"> <NumberField label="Small" size="sm" defaultValue={3} min={0} max={10} /> <NumberField label="Medium" defaultValue={3} min={0} max={10} /> <NumberField label="Large" size="lg" defaultValue={3} min={0} max={10} /> </Stack> )}const min = 60_000Fractions and a unit
A fractional step moves by that much. suffix names the unit.
tsx
import { NumberField } from '@weft-js/warp'export function Decimal() { return ( <NumberField label="CPU per copy" defaultValue={0.5} min={0.25} max={8} step={0.25} suffix="vCPU" /> )}const min = 60_000Money
prefix shows the currency. Page Up and Page Down move ten steps at a time.
tsx
import { NumberField } from '@weft-js/warp'export function Money() { return ( <NumberField label="Monthly budget" defaultValue={1500} min={0} step={50} prefix="$" hint="We email you at 80%." /> )}const min = 60_000Hint, error, read-only, disabled
Read-only and disabled turn the steppers off too.
tsx
import { Grid, NumberField, Stack, Text } from '@weft-js/warp'export function States() { return ( <Grid cols={2} gap="group"> <Cell name="Empty"><NumberField label="Retries" min={0} max={10} /></Cell> <Cell name="Hint"><NumberField label="Retries" defaultValue={3} min={0} max={10} hint="0 turns retries off." /></Cell> <Cell name="Invalid"><NumberField label="Retries" defaultValue={10} min={0} max={10} error="Ten retries can hide a real failure." /></Cell> <Cell name="Read-only"><NumberField label="Retries" defaultValue={3} readonly /></Cell> <Cell name="Disabled"><NumberField label="Retries" defaultValue={3} disabled /></Cell> </Grid> )}const min = 60_000const Cell = (p: { name: string; children?: unknown }) => ( <Stack gap="tight"> <Text role="caption" subtle>{p.name}</Text> {p.children} </Stack>)Buying seats
Use min and max to limit the count, and read value to work out a total.
tsx
import { state } from '@weft-js/core'import { NumberField, Stack, Text } from '@weft-js/warp'export function Seats() { const seats = state<number | null>(8) return ( <Stack gap="related"> <NumberField label="Seats" value={seats} min={1} max={50} hint="$12 a seat, each month." /> <Text subtle>Total: ${(seats.value ?? 0) * 12} a month</Text> </Stack> )}const min = 60_000When to use
Use it for
- An exact number, like seats or a retry count
Reach for something else
- Slider, when a rough value is enough
Accessibility
- ↑↓
- Steps up or down
- PageUpPageDown
- Steps by ten
- HomeEnd
- Jumps to the bound, when there is one
API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
label | string | — | The accessible name, drawn as the floating border label (or above, classic). Required. |
hint | unknown | — | One line of help under the control. |
error | unknown | — | Shown instead of the hint; marks the field invalid. |
icon | IconRef | — | Leading icon: it sweeps with the border. |
prefix | unknown | — | Text or an element inside the field before the value, such as $. |
suffix | unknown | — | Text or an element inside the field after the value, such as kg. |
variant | "floating" | "classic" | — | floating (default, or the app's warp({ fields })) · classic: the label above. |
appearance | "line" | — | line: only a bottom line under the value, no box or fill. The boxed field otherwise. |
size | "sm" | "md" | "lg" | 'md' | Control size. md by default. |
clearable | boolean | false | A clear button (shown once there is a value). |
counter | number | — | Maximum length, shown as a counter. |
id | string | — | The element id. One is made for you if you leave it out. |
disabled | boolean | false | Turns it off, and takes it out of the tab order. |
readonly | boolean | false | Shows the value and lets it be selected and copied, but not changed. |
value | number | State<number | null> | null | — | The current value, when you own the state. |
defaultValue | number | null | — | The starting value, when the component owns the state. |
min | number | — | The lowest it can step to. |
max | number | — | The highest it can step to. |
step | number | 1 | How far one press moves it. |
name | string | — | The name it posts under in a form. |
required | boolean | false | The form will not submit without it. |
| Event | Type | Default | Description |
|---|---|---|---|
onInput | ((e: InputEvent & { currentTarget: HTMLInputElement & HTMLTextAreaElemen… | — | Called on each keystroke. |
onValueChange | ((v: number | null, reason: ChangeReason) => void) | — | Called with each new value, and whether a pointer, a key or code made the change. |
Parts
Every element carries a stable name, so you can style it from your own CSS: [data-scope="number-field"] [data-part="step"]
stepstepsinput