A value between a "−" and a "+" button — the fare the passenger offers, or a count.
Overview
NumericStepper changes a value a step at a time with the "−" and "+" buttons; the Counter in the middle shows the value and opens direct entry. It holds the fare the passenger offers, or a count.
-
1
Standard
-
2
Empty
-
3
Green
-
4
Orange
-
5
Red
-
6
Skeleton
States
The six Fare State values, one block each. Press, focus and a disabled side button are interaction on each button, listed in the spec's States table — see Animation and Accessibility.
Standard
-
1
Decrease --surface-on-white — the fill, the Squircle's own.--text-and-icon-primary — the icon.Standard by default; the host sets each side button on its own.
-
2
Counter --surface-on-white — the fill; no tone.--text-and-icon-secondary — the chevron.
-
3
Title --text-and-icon-primary — the currency and the value.The default — an instance may set another TextAndIcon token.
-
4
Increase --text-and-icon-primary — the icon.Standard by default; the host sets each side button on its own.
Empty
-
1
Decrease --text-and-icon-disabled — the icon.Disabled by default; the host sets each side button on its own.
-
2
Placeholder --text-and-icon-secondary — "Tap to enter", in place of the title.No value yet; the Counter opens direct entry.
-
3
Increase --text-and-icon-disabled — the icon.Disabled by default; the host sets each side button on its own.
Green
-
1
Decrease --text-and-icon-primary — the icon.Standard by default; the host sets each side button on its own.
-
2
Glow --pastel-green1 — at 60 %, a radial gradient from the bottom centre to transparent.The Positive tone; the screen's own text says why.
-
3
Edge --border-success — a 1dp inside edge, radial from the bottom centre, gone by 32 % of the radius.
-
4
Increase --text-and-icon-disabled — the icon.Disabled by default; the host sets each side button on its own.
Orange
-
1
Decrease --text-and-icon-disabled — the icon.Disabled by default; the host sets each side button on its own.
-
2
Glow --pastel-orange1 — at 60 %, a radial gradient from the bottom centre to transparent.The Warning tone; the screen's own text says why.
-
3
Edge --border-warning — a 1dp inside edge, radial from the bottom centre, gone by 32 % of the radius.
-
4
Increase --text-and-icon-primary — the icon.Standard by default; the host sets each side button on its own.
Red
-
1
Decrease --text-and-icon-disabled — the icon.Disabled by default; the host sets each side button on its own.
-
2
Glow --pastel-red2 — at 60 %, a radial gradient from the bottom centre to transparent.The Error tone; the screen's own text says why.
-
3
Title --text-and-icon-error — the currency and the value.
-
4
Edge --border-error — a 1dp inside edge, radial from the bottom centre, gone by 32 % of the radius.
-
5
Increase --text-and-icon-disabled — the icon.Disabled by default; the host sets each side button on its own.
Skeleton
-
1
Side Buttons --skeleton-on-white — the Squircle Skeleton; no icons.--pattern-shimmer — the DS sweep.
-
2
Counter --skeleton-on-white — the fill; no text, no chevron.--pattern-shimmer — the same sweep; it runs in reverse in RTL.
Anatomy
Three buttons in a row: "−", the Counter, "+". The Counter carries the value and, optionally, a subtitle and a chevron.
-
1
Container A horizontal row that fills its host; no fill of its own. Required.
-
2
Decrease Squircle L, Type Icon — the "minus" icon.Required.
-
3
Counter --surface-on-white — the fill; a customButton that opens direct entry.Its row: the spacer, the text, the chevron. In Empty, "Tap to enter" replaces the title — see States. Required.
-
4
Currency Heading/Heading 3 — the text style, the same as the value.Before the value or after it; none for a count. Optional.
-
5
Value Heading/Heading 3 — the text style.--text-and-icon-primary — the colour, shared with the currency.Formatted by the product; one line. Required.
-
6
Increase Squircle L, Type Icon — the "add" icon.Required.
-
7
Spacer var(--sp-s24) — an empty box at the Counter's start, the chevron's width.It balances the chevron, so the text stays centred. Comes and goes with the chevron.
-
8
Subtitle TextRow in Expanded mode — one line, centred under the title.Body/Compact Body — the text style.--text-and-icon-secondary — the colour.Off by default. Optional.
-
9
Subtitle Icons var(--sp-s16) — an IconContainer in the TextRow's start or end slot, var(--sp-s4) from the text.Up to two on each side. A mono icon takes the subtitle colour; a colour icon — here wallet-color — keeps its own. Optional.
-
10
Chevron --text-and-icon-secondary — chevron-right-small in an IconContainer.On by default. Optional.
Layout
One size: a row of three s56 buttons that fills its host. The Counter takes the width the side buttons leave.
General
-
Container var(--sp-100-s8) — padding on all four sides; fixed.var(--sp-100-s4) — the gap between each side button and the Counter; fixed.Fills its host's width; hugs its height — 72 at 100 %.
-
SP Modes Figma binds the Counter's height and vertical padding to SP/130 % and everything else to SP/100 %, and the web takes the same families: the Counter grows to 72.8 at 130 % and holds there, the side buttons stay 56 — above 100 % the Counter stands taller than them.
Buttons
-
Counter var(--sp-130-s56) — the height, capped at 130%: it holds at 72.8 in the 150% mode; a two-line text centres in it.var(--sp-s24) — the spacer at the start and the chevron at the end; the spacer balances the chevron, so the text stays centred.var(--sp-s0) — the side padding and the gaps; the spacer and the chevron sit flush at the ends.var(--sp-130-s8) — top and bottom padding, capped at 130%.Fills the width the side buttons leave.
-
Side Buttons var(--sp-100-s56) — Squircle L, held at 100%: Figma binds the side buttons to SP/100%, over the Squircle L cap. It brings its states.var(--sp-100-s24) — the icon, fixed with the box.
-
Corner Radius var(--sp-100-s20) — all three buttons; fixed.
-
Without The Chevron The spacer goes with it — one Figma property toggles both; the text centres across the whole Counter.
Text
-
Title Heading/Heading 3 — one line, centred in the Counter.var(--sp-s2) — the hair space between the currency and the value.The currency is a prefix or a suffix; a count has none. The value is formatted by the product.
-
Subtitle var(--sp-s0) — the gap to the title.var(--sp-s16) — the icons in the TextRow's start and end slots, up to two on each side.var(--sp-s4) — the TextRow's gap between the text and an icon.One line, centred under the title. Off by default — see Anatomy.
-
Overflow One line, never wrapped: an over-long value ends in an ellipsis on the web (iOS shrinks it). Figma stages no overflow.
RTL
-
1
LTR "−" on the left, "+" on the right; the chevron at the Counter's right end.
-
2
RTL The row mirrors: "+" on the left, "−" on the right; the chevron points left at the Counter's left end, the var(--sp-s24) spacer at its right end.The title keeps its order — the currency side is the Currency setting, not the direction.The DOM, Tab and reading order stay Decrease, Counter, Increase. The web takes the direction from
dir="rtl".
Animation
Motion follows the motion system § 6.1 — pushHighlight, the press without scale. Two motions: the press, and the skeleton's shimmer.
Press
-
General --component-push-highlight — press and release, 150 ms linear.var(--shadow-pressed) — the pressed overlay over the button's fill; it fades in and out, no scale.The same on all three buttons. A disabled side button does not react.
-
Value Change No motion: the new value replaces the old in the same frame — no count-up, no width tween. A change of Fare State swaps the tone, the placeholder and the side buttons' states in the same frame too.
-
Reduced Motion Handled at the token:
motion.csszeroes every --component-* insideprefers-reduced-motion: reduce, so the overlay appears without a fade; no override of its own.
Skeleton
-
Shimmer var(--pattern-shimmer) — the DS sweep on every shape: the Squircle Skeleton on the side buttons, the same sweep on the Counter.It runs in reverse in RTL.
-
Skeleton → Content The host swaps the skeleton for the content; the stepper declares no transition of its own.
-
Reduced Motion var(--pattern-shimmer) — zeroed at the token, so the skeleton holds still.
Usage
NumericStepper sits where a person sets a value near a known one, a step at a time or by typing it in.
-
1
The Fare On The Ride Request The recommended fare to start from, the step buttons to move it, the Counter to type it.The tone comes with the screen's own words — "Recommended fare" — and those words are the Counter's description (
aria-describedby), so a screen reader hears them too. -
2
A Count The same stepper holds a count — passengers, seats: no currency, the step is one; the Counter still opens direct entry.
-
3
✕ A Tone With No Words Red alone does not say what is wrong or what to do. Give the screen's reason in text next to the stepper — never the colour as the only signal.
-
4
✕ A Value That Cannot Change Both side buttons dead and nothing to enter is not a stepper. Show the value as plain text.
Your fare
Recommended fare
Passengers
Including you
Your fare
Ride price
Accessibility
Three buttons, each its own focus with its own announcement. The screen supplies the words: what the value is, and the value as it is spoken.
-
1
Decrease "Decrease [Item], [value]" — a Button. "−" is read by its meaning, never as a symbol.Hint: TalkBack says "Double-tap to decrease" (from the
onClicklabel); VoiceOver has none — the label says it.Web:aria-label+aria-describedbyto ahiddenspan with the spoken value — never read on its own. -
2
Counter "[Item], [value]" — a Button that opens direct entry, not read-only text. Hint: TalkBack "Double-tap to edit"; VoiceOver "Opens fare entry".A fare is read with its currency in words — "Fare, 120,000 Colombian pesos", never "C O L dollar 120 000"; a count — "Passengers, 3". The product's formatter supplies the spoken form.Direct entry is titled "[Item]"; on dismiss the focus returns to the Counter, whose name reads the committed value once.Web: the spoken text is a
.visually-hiddenspan; the visible title, subtitle, spacer, chevron and icons arearia-hidden. -
3
Increase "Increase [Item], [value]" — a Button; the hint as on Decrease.
-
4
At A Limit The step that lands on it says so — "130,000 Colombian pesos, maximum" (the product's word); a tap on the disabled button repeats it, so a press is never silent.TalkBack:
enabled = false— "Disabled" after the role.VoiceOver:.notEnabled— "Dimmed"; the button stays in navigation.The Counter stays enabled — it still opens direct entry.Web — the trap:aria-disabled="true"+.squircle--disabled, the click only re-announces. Neverdisabled: "+" pressed up to the maximum would drop the focus to the page and the person loses their place. -
5
Empty "[Item], Not set" — "Tap to enter" is a touch instruction and is not read. Both side buttons are disabled by default.
-
6
Skeleton Not announced, not focusable — TalkBack
clearAndSetSemantics {}, VoiceOveraccessibilityHidden(true)(.isLoading(true)alone does not hide it), webaria-hidden+inert, the buttonstabindex="-1"whereinertis missing."Loading" is announced once by a separaterole="status"node withoutaria-busy;aria-busygoes on the region being loaded. -
After A Step The new value is announced right away; the focus stays on "−" or "+".TalkBack: the focused button's
stateDescriptionfollows the value and its change is read; the Counter is not a live region, so the value is read once. To verify on device.VoiceOver: an announcement notification; every element'saccessibilityValuefollows the value.Web: a polite live region inside the root — not the Counter; it holds only the latest value, so a held key does not queue steps. Try it on the live stepper in Animation. -
Tones The colour is never announced and never the only signal. The screen's own message about the value is appended to the value — TalkBack in the Counter's
stateDescription, VoiceOver in itsaccessibilityValue, web througharia-describedby(Usage, example 1).A step that changes the tone announces the new message with the new value. -
Subtitle Its text joins the Counter's value, in words — "…, was 200,000 Colombian pesos". Its slot icons are decorative, unless the screen gives an icon that carries meaning a word.
-
Voice Control The name carries the visible number, so "Tap 120,000" works; iOS adds
accessibilityInputLabels— "[Item]" and the visible value — to the Counter. -
Keyboard And Focus Tab moves "−" → Counter → "+"; Enter and Space activate. No arrow keys — three buttons, not a
spinbutton: the value is not edited in place.var(--sp-s2) — the focus ring in --text-and-icon-primary inside the button's edge, radius var(--sp-s20);:focus-visibleonly. -
RTL The row mirrors; the order stays Decrease, Counter, Increase — in the DOM, in Tab and in reading. TalkBack follows the reading direction, so the button on the right — Decrease — comes first. The labels are semantic, not positional.
-
Text Scaling And Targets Heading/Heading 3 — the title, caps at 130 %.Heading/Heading 4 and Body/Compact Body — the placeholder and the subtitle, scale to 150 %, the DS maximum.var(--sp-100-s56) — the side buttons, s56 × s56 in every mode; the Counter, s56 high, grows to 72.8 at 130% — both above the 48 minimum on every platform.An over-long visible value ends in an ellipsis; the spoken value stays whole.
-
Reduced Motion The press overlay appears without a fade and the shimmer holds still — both zeroed at the token.
-
Contrast --text-and-icon-primary on --surface-on-white — ≈ 15.7:1 Day / ≈ 13.2:1 Night; above 11:1 over the Green and Orange glow; the focus ring the same.--text-and-icon-error — the Red value, ≈ 3.5:1 / ≈ 3.8:1, ≈ 3.1:1 / ≈ 3.5:1 over the strongest glow: large text, above the 3:1 floor.--text-and-icon-secondary — placeholder, subtitle, chevron, ≈ 4.6:1 / ≈ 6.1:1; the subtitle over the Red glow ≈ 4.1–4.4:1 Day, below 4.5:1 — the Figma colours stay, accepted (owner, 2026-11-12).--text-and-icon-disabled — ≈ 1.9:1, below the floor on purpose: a disabled control is exempt, and its state is announced, never shown by colour alone.