Skip to content

HyNumberInput

Usage examples on this page are written for Lit / plain HTML (<hy-number-input>). The same component ships as HyNumberInput in @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 / max when 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

html
<hy-number-input label="Quantity" min="1" max="99" value="1"></hy-number-input>

Fractional step with suffix

html
<hy-number-input label="Line height" min="0" max="2" step="0.01" value="1.5" suffix="em">
</hy-number-input>

Error state

html
<hy-number-input label="Bitrate" value="400" max="320" error-message="Exceeds license tier limit">
</hy-number-input>

Dense table variant (no visible buttons)

html
<hy-number-input size="small" hide-buttons value="12"></hy-number-input>

Filled emphasis + pill shape

html
<hy-number-input emphasis="filled" pill value="5"></hy-number-input>

API

Properties

PropertyAttributeTypeDefaultDescription
valuevaluenumber0The current numeric value.
minminnumberMinimum allowable value. Defaults to -Infinity (no lower bound).
maxmaxnumberMaximum allowable value. Defaults to +Infinity (no upper bound).
stepstepnumber1Granularity between valid values.
shiftStepshift-stepnumber | undefinedLarger increment applied when Shift is held or PageUp/PageDown is pressed. Defaults to 10 × step.
displayPrecisiondisplay-precisionnumber | undefinedDecimal 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.
disableddisabledbooleanfalseDisables all interaction.
readonlyreadonlybooleanfalseMakes the field non-editable and hides the stepper buttons.
requiredrequiredbooleanfalseMarks the input as required for form validation.
errorerrorbooleanfalseWhether the input is in an error state.
namenamestring''The name attribute for form submission.
labellabelstring''Primary label above the control.
hinthintstring''Secondary hint text under the label.
helperTexthelper-textstring''Helper text below the control.
errorMessageerror-messagestring''Error message (auto-raises error state).
placeholderplaceholderstring''Placeholder shown when the field is empty.
suffixsuffixstring''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).
sizesize'small' | 'medium' | 'large''medium'Size variant. Aligns with hy-text-input / hy-select for form mixing.
variantvariant'default' | 'success' | 'warning' | 'danger''default'Visual variant (affects focus ring color only).
emphasisemphasis'outlined' | 'filled''outlined'Visual chrome weight. outlined (default) = border only, filled = surface fill only. Independent from variant (which tints only the focus ring).
layoutlayout'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.
pillpillbooleanfalsePill shape — collapses the border radius to fully rounded ends.
hideButtonshide-buttonsbooleanfalseHide the ± stepper buttons. Keyboard stepping (ArrowUp/Down) still works. Useful in dense tables where buttons would add visual noise.
inputIdinput-idstring''Explicit ID for the underlying <input> — auto-generated if empty.
autofocusautofocusbooleanfalseMarks 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.
autoselectautoselectbooleanfalseAfter 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 | undefinedCustom 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).
formHTMLFormElement | null
validityValidityState
validationMessagestring

Events

EventDetailDescription
inputFired on every keystroke or step. Detail:
changeFired on blur, Enter, or pointer release after stepping. Detail:

Slots

SlotDescription
prefixContent before the input (e.g. a $ icon).
suffixDisplay-only unit. The suffix attribute is the shorthand.

CSS Parts

PartDescription
baseThe component wrapper
labelThe label container (label + hint)
controlThe row containing −, input, +
inputThe native <input> element
decrementThe − button
incrementThe + button
helper-textThe helper text element
error-messageThe error message element

CSS Custom Properties

PropertyDescription
--hy-number-input-widthHost width. Defaults to fit-content so the stepper hugs its value; set to 100% for full-row layouts.
--hy-number-input-field-min-widthMinimum 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-radiusBorder radius
--hy-number-input-gapGap between label, control, helper text
--hy-number-input-height-smOuter 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-mdOuter height for medium size variant. Default: var(--hy-control-height-md)
--hy-number-input-height-lgOuter height for large size variant. Default: var(--hy-control-height-lg)
--hy-number-input-button-sizeStepper button width (defaults to control height)
--hy-number-input-field-paddingInline padding inside the input column
--hy-number-input-background-restField background
--hy-number-input-button-background-restStepper button background
--hy-number-input-button-background-hoverStepper button hover background
--hy-number-input-border-restBorder color
--hy-number-input-border-hoverBorder color on hover
--hy-number-input-border-focusBorder color on focus
--hy-number-input-label-column-widthWidth of the label column in layout="inline" mode. No default — set on a wrapping container so stacked inputs align.
--hy-number-input-hover-durationTransition duration for hover and focus state feedback
--hy-number-input-hover-easingTransition 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.

Built with Lit. Documented with VitePress.