Components / Text & numbers
NumberInput
A numeric field with steppers, min/max clamping and arrow-key stepping.
@ruckc/truss-ui Text & numbers
Import
import { NumberInput } from '@ruckc/truss-ui'; Playground
Recipe: reacting to committed changes
onchange receives the new value (number | null) each time a change is committed: on blur, on Enter, with the arrow keys and
with the step buttons. It does not fire on every keystroke, and not when the committed value equals the current one.
Last change: none
<NumberInput label="Quantity" bind:value={qty} onchange={(v) => save(v)} /> Recipe: function bindings for immutable state
When state is updated immutably, bind with a getter and a setter instead of bind:value={x}. The setter is the place to
copy, validate or clamp.
<script lang="ts">
let state = $state({ qty: 3 });
const update = (v: number | null) => (state = { ...state, qty: v ?? 0 });
</script>
<!-- Svelte function bindings: a getter and a setter -->
<NumberInput label="Quantity" bind:value={() => state.qty, (v) => update(v)} /> Recipe: clearing the field
Clearing the input commits null, so a consumer that needs a number must handle it (value ?? 0). Set allowEmpty={false} to commit min ?? 0 instead and never see null from user input.
Value: 2
<NumberInput label="Seats" min={1} allowEmpty={false} bind:value={seats} />
<!-- clearing the field commits 1 (min ?? 0), never null --> Recipe: an optional number
Some settings are a number or "off". With nullable, NumberInput and Slider add a switch named
"Enable label" to the same labelled control. While the value is null the field is inert and shows offLabel (default
"Off"). Switching on restores the last number the control had, else defaultValue, else min (or 0). A range slider ignores nullable. An enabled NumberInput that is cleared keeps its number: turn the switch off to get null.
Value:
Value: 40
<NumberInput label="Max iterations" nullable defaultValue={100} bind:value={limit} />
<Slider label="Speed" nullable numberInput offLabel="Auto" bind:value={speed} />
<!-- null means off; the built-in switch is named "Enable Max iterations" --> API
| Prop | Type | Default | Description |
|---|---|---|---|
value bindable | number | null | null | The current value. Bind it with `bind:value`. |
min | number | — | Minimum allowed value. |
max | number | — | Maximum number to show before collapsing the rest. |
step | number | 1 | Increment between values. |
label | string | — | Visible label shown above the control. |
ariaLabel | string | — | Accessible name when no visible `label` is shown. |
hint | string | — | Helper text shown below the control. |
error | string | — | Error message. Marks the control invalid, replaces the hint, and is announced to assistive technology. |
placeholder | string | — | Hint shown while the field is empty. |
disabled | boolean | false | Disables the control: it cannot be focused, changed or activated. |
allowEmpty | boolean | true | When false, clearing the field commits `min ?? 0` instead of `null`. Defaults to true. |
nullable | boolean | false | Treat `null` as "off": a built-in switch (named "Enable <label>") sits beside the field, the field is disabled and shows `offLabel` while off. Clearing the text of an enabled field keeps the current number instead of committing `null`; turn the switch off for that. |
offLabel | string | 'Off' | Text shown while a `nullable` field is off. Defaults to "Off". |
defaultValue | number | — | What turning a `nullable` field on restores when there is no earlier number to return to. Falls back to `min ?? 0`. |
onchange event | (value: number | null) => void | — | Fires when a change is committed (blur, Enter, arrow keys, the step buttons), not on every keystroke. |