Skip to main content
Graphite UI

Number input

Takes a number that moves in steps (guests, quantity, a percentage), typed or nudged with the buttons at the end. For a number with no steps, such as a phone number, use a Text input.

Contract 1.0.0Kit · 6 sets · 54 variantsOpen in Figma

Live preview

Rendered by the component itself from the same generated tokens as the rest of the site.

From 0 to 10

Installation

Install it with the shadcn CLI, along with everything it uses. New project? Set it up first, as Quick start shows.

npx shadcn@latest add https://www.graphite-ui.com/r/number-input.json
import { NumberInput } from '@/components/ui/number-input'

Anatomy

Text input’s label, field and helper, the value 16 in, and the stepper at the end: decrement then increment, each a ghost icon-only Button square at the field’s height, each after a 1 × 20 divider.

From 0 to 10
  1. FieldRequiredThe governed Text input as a native number field, its browser spinner hidden. Every size, layout (fixed, inline, fluid), label, supporting text and state is Text input's.
  2. StepperRequiredThe kit's two action items at the end of the field, decrement then increment. Each is a ghost icon-only Button, square at the field's height (32, 40 or 48; 40 in Fluid), with the kit's 16px minus-small and plus-small, after a 1 × 20 outline divider. They are named "Decrement" and "Increment" and disable at the bounds. In Error and Warning the status glyph comes before them.

Variants

Size sets the field and the stepper together: 48, 40 or 32. Fluid is a 64px box with the label inside and 40px stepper buttons on the value row.

Default: Large
From 0 to 10
Default: Medium
From 0 to 10
Default: Small
From 0 to 10
Fluid
From 0 to 10

States

Text input’s states. Error and warning put the status glyph before the stepper, as the kit draws them. At a bound, the button that would pass it disables. Disabled and Read-only disable both.

Enabled
From 0 to 10
At the minimum
From 0 to 10
At the maximum
From 0 to 10
Error
Enter a number from 0 to 10
Warning
More than 8 may take a while
Disabled
From 0 to 10
Read-only
From 0 to 10

API reference

Generated from the contract, versioned with it, and checked by drift-check. This table cannot describe props the component does not have.

Number input props
PropTypeDefaultNotes
value / onChange——Controlled. A number, or null when the field is empty. What is typed stays as typed until it is a number; checking it against the range is the caller's.
min / max / step——Passed to the native field, so the arrow keys step and clamp as the stepper does. step is 1 by default.
Text input's other props——size, layout, label, helpText, errorText, warningText, disabled, readOnly and the rest. readOnly and disabled both disable the stepper.

Design tokens

Every swatch is live. Change the source color in the header and this table repaints, because it reads the same roles the component does.

  • outlineThe dividers before each stepper button (the kit's Medium binds outline).
  • spacingThe stepper running to the field's right edge, past the shell's 16 inset.

Usage

The contract's prohibitions, written as the choices you will actually face.

Do

  • Set min and max, and say the range in the helper text.
  • Check what is typed on the page, and say what is wrong with errorText.
  • Pick a step that matches how the number moves: 1 for guests, 0.5 for hours.
  • Keep the value short; the field is for numbers, not sentences.

Don’t

  • Use it for numbers that are really identifiers: phone, card or postal numbers.
  • Step past a bound. The buttons stop there.
  • Hide the stepper. It is the reason to use this over a Text input.
  • Restyle the field or the buttons. They are the governed Text input and Button.

Accessibility

What the component does for you, and what it leaves to you.

Roles
A native number field (spinbutton), labelled, with its range and step, and two buttons after it.
Keyboard
Arrow Up and Down step and clamp, as the buttons do. Tab reaches the field, then each button.
Buttons
“Decrement” and “Increment”. Each disables at the bound it would pass, and both with a disabled or read-only field.
Focus
The field takes Text input’s ring; each button its own.

Figma parity

The kit’s Number input page has two public sets, Default and Fluid, built from a private base and action item. The code is one component over Text input and Button.

Kit axes and how they map to code
Kit axisValuesCodeHow it maps
SetDefault · Fluidlayoutfixed and fluid.
SizeLarge · Medium · Smallsize48, 40 and 32, the field and the stepper together.
StateEnabled · Focus · Error · Warning · Disabled · Read-only—Text input’s, with errorText, warningText, disabled and readOnly. Fluid’s Hover is the shell’s.
StateSkeleton—No counterpart by rule.
Action itemEnabled · Hover · Active · Focus · Disabled—The ghost Button’s own states.
Dividerborder-subtle-01 · outline—The Large divider binds a variable that resolves to nothing; the code uses Medium’s outline at every size.
AI slug · RevertAction items—Not built: the AI sets are ungoverned.