NumberField
NumberFields allow users to enter and adjust numeric values with increment and decrement controls. They support range constraints, step values, and locale-aware formatting.
Import
import { NumberField } from '@proyecto-viviana/solid-spectrum';Basic Usage
A simple number input with a label and stepper buttons.
<NumberField label="Quantity" defaultValue={1} />Controlled Value
Control the number field value with state. The stepper buttons and keyboard input both update the controlled value.
Current quantity: 1
const [quantity, setQuantity] = createSignal(1);
<NumberField
label="Items"
value={quantity()}
onChange={setQuantity}
/>
<p>Current quantity: {quantity()}</p>With Min and Max
Constrain the value within a minimum and maximum range. The stepper buttons disable at boundaries.
<NumberField
label="Age"
minValue={0}
maxValue={120}
defaultValue={25}
/>
<NumberField
label="Rating (1-5)"
minValue={1}
maxValue={5}
defaultValue={3}
/>Step Values
Configure the increment/decrement step size for fine or coarse adjustments.
<NumberField
label="Opacity"
minValue={0}
maxValue={1}
step={0.1}
defaultValue={0.5}
/>
<NumberField
label="Quantity (step 5)"
step={5}
defaultValue={10}
/>Currency Formatting
Use formatOptions to display values with locale-aware currency formatting.
Raw value: 29.99
const [price, setPrice] = createSignal(29.99);
<NumberField
label="Price"
value={price()}
onChange={setPrice}
formatOptions={{
style: 'currency',
currency: 'USD',
}}
/>Percentage Formatting
Display values as percentages. The underlying value is stored as a decimal (0-1).
<NumberField
label="Discount"
defaultValue={0.15}
minValue={0}
maxValue={1}
step={0.01}
formatOptions={{
style: 'percent',
}}
/>Sizes
NumberField supports S, M, L, and XL sizes.
<NumberField label="Small" size="S" defaultValue={5} />
<NumberField label="Medium" size="M" defaultValue={10} />
<NumberField label="Large" size="L" defaultValue={15} />
<NumberField label="Extra large" size="XL" defaultValue={20} />Hidden Stepper
Hide the increment/decrement buttons for a cleaner appearance. Users can still type values directly and use arrow keys.
<NumberField
label="Score"
hideStepper
defaultValue={85}
/>Disabled and Invalid
NumberField supports disabled and invalid states for form integration.
<NumberField label="Disabled" isDisabled defaultValue={42} />
<NumberField
label="Invalid"
isInvalid
errorMessage="Value must be between 1 and 100"
defaultValue={150}
maxValue={100}
/>Props
| Prop | Type | Default | Description |
|---|---|---|---|
label | string | — | Label text for the number field (required for accessibility) |
value | number | — | The current value (controlled) |
defaultValue | number | — | The default value (uncontrolled) |
onChange | (value: number) => void | — | Handler called when the value changes |
minValue | number | — | The minimum allowed value |
maxValue | number | — | The maximum allowed value |
step | number | 1 | The increment/decrement step size |
formatOptions | Intl.NumberFormatOptions | — | Options for locale-aware number formatting (e.g., currency, percent) |
size | 'sm' | 'md' | 'lg' | 'md' | The size of the number field |
variant | 'outline' | 'filled' | 'outline' | Visual style variant |
isDisabled | boolean | false | Whether the number field is disabled |
isRequired | boolean | false | Whether the number field is required |
isInvalid | boolean | false | Whether the number field is in an invalid state |
errorMessage | string | — | Error message displayed when the field is invalid |
description | string | — | Help text displayed below the input |
hideStepper | boolean | false | Whether to hide the increment/decrement stepper buttons |
Accessibility
- Uses
role="spinbutton"witharia-valuenow,aria-valuemin, andaria-valuemaxfor screen readers - Label is associated with the input via
aria-labelledby - Increment and decrement buttons have
aria-labelfor screen readers - Supports keyboard interaction: Arrow Up/Down to increment/decrement, Home/End for min/max
- Stepper buttons are automatically disabled at min/max boundaries
- Invalid state is communicated via
aria-invalidand linked error message - Description text is linked via
aria-describedby