---
title: Number Field
description: Number fields collect numeric input with increment/decrement steppers, locale formatting, and min/max constraints.
category: Forms
---
import { meta as NumberFieldMeta, Default } from '@/content/stories/number-field';
import Canvas from '@/components/component-docs/canvas';
import Demo from '@/components/component-docs/demo';
export const config = {
dependencies: {
components: [Canvas, Demo],
scripts: [
'../../components/component-docs/demo.script.tsx',
'../../components/component-docs/canvas.script.tsx',
'../../components/component-docs/controls.script.tsx',
],
},
};
# Number Field
Number fields collect numeric input with increment/decrement steppers, locale formatting, and min/max constraints.
## Try it
## Usage
Set `minValue`, `maxValue`, and `step` to constrain input. Compose with `RuiNumberFieldGroup` and stepper buttons for the full pattern.
```tsx
import {
RuiNumberField,
RuiNumberFieldGroup,
RuiNumberFieldInput,
RuiNumberFieldDecrementButton,
RuiNumberFieldIncrementButton,
RuiNumberFieldSteppers,
} from '@ecopages/radiant-ui/number-field';
```
## Custom markup
`` coordinates any light-DOM tree that matches its query contract. The `RuiNumberField` helpers stamp these targets; they are not required.
```tsx
import '@ecopages/radiant-ui/number-field';
```
BEM classes are presentation-only. The host owns formatted input `value` and spinbutton `aria-*`. Set `name` on the host to submit the raw number with a native form (not the formatted display string).
## Step and commit behavior
`commitBehavior` controls whether out-of-range typed values snap to bounds or reject on blur.
## Disable scroll wheel
Set `wheelDisabled` to prevent accidental value changes when users scroll over a focused number field.
## Theming
Number field surfaces map to **semantic surface roles**, never Tailwind palette steps:
| Part | CSS roles |
| --- | --- |
| Group (`.rui-number-field__group`) | `border`, `background`, `rounded-control` |
| Input (`.rui-number-field__input`) | `on-background` text |
| Steppers (`.rui-number-field__steppers`) | `border` divider |
| Stepper (`.rui-number-field__stepper`) | `on-surface`, `surface` hover, `surface-container-low` active |
| Focus / invalid | `focus-ring` / `error` |
Geometry shares control tokens (`--size-control-sm`, `--space-control-*`, `--radius-control`, `--text-control`) with `RuiInput` and `RuiButton` so form rows align. Override at the theme layer, not in component CSS.
## API
`RuiNumberField` is a custom element (``). Standalone it renders the default input + stepper row; compose the view helpers for full control.
### Attributes
| Attribute | Type | Default | Description |
| --- | --- | --- | --- |
| `value` | `number` | | Current value. |
| `default-value` | `number` | | Initial value when uncontrolled. |
| `min-value` | `number` | `-Infinity` | Lower bound; steppers and arrow keys snap to it. |
| `max-value` | `number` | `Infinity` | Upper bound; steppers and arrow keys snap to it. |
| `step` | `number` | `1` | Increment/decrement and snap interval. |
| `disabled` | `boolean` | `false` | Disables input and steppers. |
| `read-only` | `boolean` | `false` | Blocks editing; the value still displays formatted. |
| `label` | `string` | `''` | Accessible name when there is no visible `RuiLabel`. |
| `name` | `string` | `''` | Form field name on this host. Submits the raw number, not the formatted display. |
| `locale` | `string` | `''` | BCP 47 locale tag, or comma-separated fallback list. |
| `format-options` | `string` | `''` | JSON-serialized `Intl.NumberFormatOptions`. |
| `commit-behavior` | `snap` ยท `validate` | `snap` | Blur behavior after editing. |
| `increment-aria-label` | `string` | `Increment` | Accessible name for the increment stepper. |
| `decrement-aria-label` | `string` | `Decrement` | Accessible name for the decrement stepper. |
| `wheel-disabled` | `boolean` | `false` | Disables scroll-wheel value changes. |
### Light-DOM contract
| Target | Required | Host writes | Author owns |
| --- | --- | --- | --- |
| `[data-number-field-input]` | yes | `id`, `role`, `inputmode`, `data-disabled`, `data-readonly`, `aria-valuemin`, `aria-valuemax`, `aria-valuenow`, formatted `value` | text input; stamp `data-rui-control` for field wiring |
| `[data-number-field-action="decrement"]` | no | `disabled`, `aria-label` | decrement button |
| `[data-number-field-action="increment"]` | no | `disabled`, `aria-label` | increment button |
| `[data-number-field-group]` | no | โ | presentation wrapper only |
Nested hosts: none.
### Events
| Event | Detail | Description |
| --- | --- | --- |
| `rui-change` | `{ value: number }` | Emitted when a value is committed (blur, stepper, or keyboard). |
### View helpers
| Component | Target stamped | Notes |
| --- | --- | --- |
| `RuiNumberField` | default group when `children` omitted | Includes input and steppers. |
| `RuiNumberFieldGroup` | `[data-number-field-group]` | Presentation only; not queried. |
| `RuiNumberFieldInput` | `[data-number-field-input]` | Always stamps `data-rui-control`. |
| `RuiNumberFieldIncrementButton` | `[data-number-field-action="increment"]` | Default label "Increment". |
| `RuiNumberFieldDecrementButton` | `[data-number-field-action="decrement"]` | Default label "Decrement". |
| `RuiNumberFieldSteppers` | stepper column wrapper | Presentation only. |
### CSS classes
Public BEM classes (documented via `@cssclass`):
| Class | Description |
| --- | --- |
| `.rui-number-field` | Root field wrapper. |
| `.rui-number-field__group` | Control-height bordered row. |
| `.rui-number-field__input` | Borderless text input. |
| `.rui-number-field__steppers` | Trailing stepper column. |
| `.rui-number-field__stepper` | Icon button cell (`+` / `โ`). |
### Theme roles
| Part | CSS variables consumed |
| --- | --- |
| Group | `--border`, `--background`, `--radius-control`, `--duration-normal` |
| Input | `--on-background`, `--space-control-x`, `--space-control-y`, `--text-control` |
| Steppers | `--size-control-sm` |
| Stepper states | `--on-surface`, `--surface`, `--surface-container-low` |
| Focus / invalid | `--focus-ring` / `--error` |
## Accessibility
- Stepper buttons need accessible names; "Increment" and "Decrement" are provided by default.
- Announce min and max constraints in helper text when the valid range is not obvious.
- Disabled fields should explain why editing is unavailable.