ScrollField
MD3 Expressive scroll field (Compose's ScrollField): a vertical wheel of
numbers that wraps around endlessly and snaps the selected value to its
centre. It is the building block of the TimePicker's
scroll mode, and works on its own
for any small integer range.
Basic usage
min (default 0) and max set the range; max wraps back to min.
Use value + onChange(event, value) for a controlled field or
defaultValue for an uncontrolled one. Values are drawn zero-padded to two
digits; the centred one is DisplayLarge Emphasized in OnSurface, its
neighbours DisplayMedium in Outline.
const [minute, setMinute] = useState(30)
<ScrollField
aria-label="Minute"
max={59}
value={minute}
onChange={(event, value) => setMinute(value)}
getValueText={(value) => `${value} minutes`}
/>
Size and formatting
The field is 100×200px by default (Compose's ScrollFieldHeight); each value
takes a third of 200px whatever height you give it, so a shorter field shows
less of the neighbours. Set width / height with style or className.
formatValue changes how values are drawn.
<ScrollField aria-label="Year" min={2000} max={2030} formatValue={String} style={{ width: 160 }} />
<ScrollField aria-label="Hour" min={1} max={12} style={{ height: 120 }} />
<ScrollField aria-label="Disabled" max={59} disabled />
Accessibility
- The field is an ARIA
spinbuttonwitharia-valuenow,aria-valuemin,aria-valuemaxandaria-valuetext. Give it a name witharia-label(oraria-labelledby), and passgetValueTextwhen the number alone is not enough (for example"7 o'clock"). - Keyboard: ArrowUp / ArrowDown move by one value and wrap around,
PageUp / PageDown by
pageStep(default 5), Home / End jump tomin/max. - The mouse wheel moves one value per notch without scrolling the page. Dragging (touch, mouse or pen) scrolls the wheel and snaps to the nearest value, and tapping a neighbouring value scrolls to it.
- With reduced motion the wheel jumps instead of animating.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
defaultValue | number | min | Uncontrolled initial value. |
disabled | boolean | false | Disabled: dimmed colors, no interaction, out of the Tab order. |
formatValue | ((value: number) => string) | (n: number) => String(n).padStart(2, '0') | Text drawn for a value. |
getValueText | ((value: number) => string) | formatValue's result | aria-valuetext for a value — include the unit (e.g. "7 o'clock"). |
max * | number | — | Largest value (inclusive). The wheel wraps from max back to min. |
min | number | 0 | Smallest value. |
onChange | ((event: Event, value: number) => void) | — | Fires with the new value as the wheel moves (keyboard, wheel, drag, tap). The event is the native event behind the change. |
pageStep | number | 5 | Values moved by PageUp / PageDown. |
value | number | — | Controlled value (an integer from min to max). |