HyNumberInput
Usage examples on this page are written for Lit / plain HTML (
<hy-number-input>). The same component ships asHyNumberInputin@whitespaceux/harmony-react(native React 19), with typed wrappers for Angular, Solid, Svelte, and Vue. The API reference below applies to all frameworks.
A form-associated numeric stepper: a text field for typing an exact value, flanked by − / + buttons for click-or-hold increment. Pairs with hy-slider to give users both approximate (slider) and precise (number input) control over the same numeric field.
The primitive is deliberately general-purpose — value is a plain number, units are display-only (suffix), and DTCG / locale / composite values belong in consumer code. That keeps it equally useful for quantity pickers, dashboard bounds, Tuner token editors, and any future form builder.
Form integration
Implements the Form-Associated Custom Elements API — value participates in FormData and validates against min, max, step, and required.
Keyboard
- ArrowUp / ArrowDown: step by
step - Shift + Arrow / PageUp / PageDown: step by
shiftStep(10× by default) - Home / End: jump to
min/maxwhen finite - Enter: commit (blur-equivalent)
Pointer
Single click on ± steps by step (or shiftStep when Shift is held). Press-and-hold auto-repeats with an accelerating cadence. Release fires a single change. pointercancel and pointerleave stop the repeat.
Examples
Basic quantity picker
<hy-number-input label="Quantity" min="1" max="99" value="1"></hy-number-input>Fractional step with suffix
<hy-number-input label="Line height" min="0" max="2" step="0.01" value="1.5" suffix="em">
</hy-number-input>Error state
<hy-number-input label="Bitrate" value="400" max="320" error-message="Exceeds license tier limit">
</hy-number-input>Dense table variant (no visible buttons)
<hy-number-input size="small" hide-buttons value="12"></hy-number-input>Filled emphasis + pill shape
<hy-number-input emphasis="filled" pill value="5"></hy-number-input>API
Properties
| Property | Attribute | Type | Default | Description |
|---|---|---|---|---|
value | value | number | 0 | The current numeric value. |
min | min | number | — | Minimum allowable value. Defaults to -Infinity (no lower bound). |
max | max | number | — | Maximum allowable value. Defaults to +Infinity (no upper bound). |
step | step | number | 1 | Granularity between valid values. |
shiftStep | shift-step | number | undefined | — | Larger increment applied when Shift is held or PageUp/PageDown is pressed. Defaults to 10 × step. |
displayPrecision | display-precision | number | undefined | — | Decimal places to display and round to. When omitted, inferred from step (step=0.01 → 2). Set explicitly to over-ride the display precision without changing the step granularity. |
disabled | disabled | boolean | false | Disables all interaction. |
readonly | readonly | boolean | false | Makes the field non-editable and hides the stepper buttons. |
required | required | boolean | false | Marks the input as required for form validation. |
error | error | boolean | false | Whether the input is in an error state. |
name | name | string | '' | The name attribute for form submission. |
label | label | string | '' | Primary label above the control. |
hint | hint | string | '' | Secondary hint text under the label. |
helperText | helper-text | string | '' | Helper text below the control. |
errorMessage | error-message | string | '' | Error message (auto-raises error state). |
placeholder | placeholder | string | '' | Placeholder shown when the field is empty. |
suffix | suffix | string | '' | Display-only unit ("px", "%", "ms"). Not parsed. Rendered inside the field on the inline-end edge. Use the suffix slot for richer content (icon + text, multi-token labels). |
size | size | 'small' | 'medium' | 'large' | 'medium' | Size variant. Aligns with hy-text-input / hy-select for form mixing. |
variant | variant | 'default' | 'success' | 'warning' | 'danger' | 'default' | Visual variant (affects focus ring color only). |
emphasis | emphasis | 'outlined' | 'filled' | 'outlined' | Visual chrome weight. outlined (default) = border only, filled = surface fill only. Independent from variant (which tints only the focus ring). |
layout | layout | 'block' | 'inline' | 'block' | Row layout: block (default) stacks label above the control; inline puts label on the left and control on the right. Helper/error always sit under the control (col 2–end), never under the label. Set --hy-number-input-label-column-width on a wrapping container so stacked inputs align. |
pill | pill | boolean | false | Pill shape — collapses the border radius to fully rounded ends. |
hideButtons | hide-buttons | boolean | false | Hide the ± stepper buttons. Keyboard stepping (ArrowUp/Down) still works. Useful in dense tables where buttons would add visual noise. |
inputId | input-id | string | '' | Explicit ID for the underlying <input> — auto-generated if empty. |
autofocus | autofocus | boolean | false | Marks this number input as the auto-focus target. Read by hy-dialog (and other overlay containers) on show to choose initial focus. Also focuses on first connect when used outside an overlay, mirroring native HTML autofocus but routed through JS so SSR'd HTML doesn't pull focus during hydration. |
autoselect | autoselect | boolean | false | After auto-focus lands, selects the current value so the user can type-to-replace. Pairs with autofocus for rename-style dialogs where the existing value is shown for context but is meant to be overwritten. |
formatValue | — | (value: number) => string | undefined | — | Custom formatter for the field's display text when the input is not focused. When set, owns the full string — suffix is NOT appended. Does not affect value or FormData; only the visual representation. Must be a function, so assign as a property (el.formatValue = fn). |
form | — | HTMLFormElement | null | — | — |
validity | — | ValidityState | — | — |
validationMessage | — | string | — | — |
Events
| Event | Detail | Description |
|---|---|---|
input | — | Fired on every keystroke or step. Detail: |
change | — | Fired on blur, Enter, or pointer release after stepping. Detail: |
Slots
| Slot | Description |
|---|---|
prefix | Content before the input (e.g. a $ icon). |
suffix | Display-only unit. The suffix attribute is the shorthand. |
CSS Parts
| Part | Description |
|---|---|
base | The component wrapper |
label | The label container (label + hint) |
control | The row containing −, input, + |
input | The native <input> element |
decrement | The − button |
increment | The + button |
helper-text | The helper text element |
error-message | The error message element |
CSS Custom Properties
| Property | Description |
|---|---|
--hy-number-input-width | Host width. Defaults to fit-content so the stepper hugs its value; set to 100% for full-row layouts. |
--hy-number-input-field-min-width | Minimum width of the input field. Defaults to 4ch; raise for ranges with long numbers (e.g. 8ch for 0–999999 or formatted currency). |
--hy-number-input-radius | Border radius |
--hy-number-input-gap | Gap between label, control, helper text |
--hy-number-input-height-sm | Outer height for small size variant. Per-component override in the form-control height contract (see .claude/rules/control-heights.md). Default: var(--hy-control-height-sm) |
--hy-number-input-height-md | Outer height for medium size variant. Default: var(--hy-control-height-md) |
--hy-number-input-height-lg | Outer height for large size variant. Default: var(--hy-control-height-lg) |
--hy-number-input-button-size | Stepper button width (defaults to control height) |
--hy-number-input-field-padding | Inline padding inside the input column |
--hy-number-input-background-rest | Field background |
--hy-number-input-button-background-rest | Stepper button background |
--hy-number-input-button-background-hover | Stepper button hover background |
--hy-number-input-border-rest | Border color |
--hy-number-input-border-hover | Border color on hover |
--hy-number-input-border-focus | Border color on focus |
--hy-number-input-label-column-width | Width of the label column in layout="inline" mode. No default — set on a wrapping container so stacked inputs align. |
--hy-number-input-hover-duration | Transition duration for hover and focus state feedback |
--hy-number-input-hover-easing | Transition easing for hover and focus state feedback |
Methods
select()
Selects all text in the underlying input.
stepUp()
Increment the value by n steps (default 1). Clamps to max, fires input then change, and is a no-op when disabled or readonly.
stepDown()
Decrement the value by n steps (default 1). Clamps to min, fires input then change.