Stepper
Number stepper whose digits roll in the direction you press. Hold a button to repeat.
- Category: Inputs
- Licence: Free, MIT
- Built with: React 19, Tailwind CSS 4, Motion
- Dependencies: motion, clsx, tailwind-merge
Examples
Stepper
API reference
| Prop | Type | Default | Description |
|---|---|---|---|
value | number | — | Controlled value. |
defaultValue | number | — | Initial value when uncontrolled. |
onValueChange | (value: number) => void | — | |
min | number | 0 | |
max | number | 99 | |
step | number | 1 | |
aria-label | string | — |
About Stepper
Stepper is a number input with minus and plus buttons whose digits roll up or down in the direction you pressed. Hold a button and it repeats, speeding up, which is exactly what you want for quantities and counts.
Stepper is an input component for React 19, styled with Tailwind CSS 4 and animated with Motion. It drops into Next.js, Vite, Remix or Astro through the shadcn CLI as a single file you own.
When to use Stepper
- Quantity selectors in carts and booking flows.
- Guest, seat or ticket counts.
- Numeric settings with sensible bounds.
- Inventory and admin tools where values change in small steps.
How it works
Each digit is its own rolling column, so 9 to 10 rolls only the digits that change. Press and hold starts a repeat timer that accelerates; min, max and step clamp the value, and the buttons disable at the bounds.
It is a real form control: it has an accessible name, works with the keyboard alone, shows a visible focus ring and announces its state to screen readers. With prefers-reduced-motion on, it holds still or settles instantly instead of animating.
Customizing Stepper
Every prop is documented in the API reference above with its type and default. The ones you will reach for first are listed here.
The Customize panel next to the preview lets you change min, max, step live, and the Code tab updates to match, so the snippet you copy already carries your values.
- value (number): Controlled value.
- defaultValue (number): Initial value when uncontrolled.
- min (number, default 0).
- max (number, default 99).
- step (number, default 1).
- aria-label (string).
Goes well with Stepper
Stepper is already composed into 2 ready-made sections, so you can see it in context or install the whole block.
- Product Detail: Commerce section
- Event Tickets: Events section
- Range Slider: Six animated React range sliders on one accessible core: inline, tick, fluid, wave, bubble and ruler
- Button: An animated React button with six variants, spring press feedback and a width-stable loading state
- Switch: An animated React toggle switch whose thumb stretches when pressed, like a real switch
- Checkbox: An animated React checkbox: the check draws itself in, the box pops, indeterminate morphs to a dash
- Radio Group: An animated React radio group with roving focus and a highlight that glides between card options
Install Stepper
npx shadcn@latest add https://charcoalui.com/r/stepper.jsonStepper is free and MIT licensed. The command copies stepper.tsx into components/ui and installs clsx, tailwind-merge; you can also copy the source from the Code tab by hand.
It pairs well with Split Flap, a Pro piece: Airport departure board: every cell flips through the drum until it lands on its letter.
Frequently asked questions
- How do I install Stepper?
- Run npx shadcn@latest add https://charcoalui.com/r/stepper.json. The shadcn CLI copies stepper.tsx into components/ui and installs motion, clsx, tailwind-merge. You can also copy the source from this page by hand.
- Is Stepper free for commercial use?
- Yes. Stepper is MIT licensed: use it in any personal or commercial project and change it however you like.
- Does Stepper work with Next.js?
- Yes. It is a client component for React 19 styled with Tailwind CSS 4, so it works in the Next.js App Router and Pages Router, Vite, Remix and Astro.
- Can an AI coding agent install Stepper?
- Yes. Connect the Charcoal UI MCP server (https://charcoalui.com/mcp) to Claude Code, Cursor or any MCP client; get_component returns Stepper's props and source and get_install_command returns the exact command.