Picker
A scrolling wheel picker for single or multi-column selection — the standard mobile pattern for date, time, and units.
Basic Usage
Single-column picker
Scroll the wheel to settle on a value. Outer rows fade and shrink for the classic iOS feel.
import { Picker } from 'fluxo-ui';
const [value, setValue] = useState(['medium']);
<Picker
columns={[{
key: 'size',
label: 'T-shirt size',
options: [
{ value: 'xs', label: 'XS' },
{ value: 's', label: 'S' },
{ value: 'medium', label: 'M' },
{ value: 'l', label: 'L' },
{ value: 'xl', label: 'XL' },
],
}]}
value={value}
onChange={setValue}
/>Multi-column
Time picker (3 columns)
Use multiple columns for compound values like time, date, or units. Each column scrolls independently.
<Picker
columns={[
{ key: 'hour', label: 'Hour', options: hours },
{ key: 'min', label: 'Min', options: minutes },
{ key: 'ampm', label: '', options: [{ value: 'AM', label: 'AM' }, { value: 'PM', label: 'PM' }] },
]}
value={time}
onChange={setTime}
/>Variants
Wheel (default)
iOS-style with fading and shrinking outer rows.
Flat
Simple highlighted active row, no fade.
Compact
Smaller text — useful when space is tight or when used inline.
<Picker variant="flat" columns={[...]} value={value} onChange={setValue} />Inside a Sheet
Picker inside a bottom sheet
Pair the Picker with a Drawer in sheet mode for a familiar mobile selection pattern.
<Button label="Pick a country" onClick={() => setOpen(true)} />
<Drawer
open={open}
onClose={() => setOpen(false)}
position="bottom"
variant="sheet"
snapPoints={['45%']}
title="Pick a country"
footer={<Button label="Done" onClick={() => setOpen(false)} />}
>
<Picker columns={[{ options: countries }]} value={value} onChange={setValue} />
</Drawer>Import
import { Picker } from 'fluxo-ui';
import type { PickerProps, PickerColumn, PickerOption, PickerVariant } from 'fluxo-ui';Props
columnsreqPickerColumn[]Picker columns. Each column: { key?, label?, options: { value, label, disabled? }[], flex? }.
columnsreqPickerColumn[]Picker columns. Each column: { key?, label?, options: { value, label, disabled? }[], flex? }.
valuereqstring[]Selected value for each column, in order.
valuereqstring[]Selected value for each column, in order.
onChangereq(value: string[]) => voidCalled whenever any column settles on a new option.
onChangereq(value: string[]) => voidCalled whenever any column settles on a new option.
itemHeightnumber"36"Height in pixels for each row.
itemHeightnumber"36"Height in pixels for each row.
visibleItemsnumber"5"Number of rows visible at once. Odd numbers keep the selected row centered.
visibleItemsnumber"5"Number of rows visible at once. Odd numbers keep the selected row centered.
variant'wheel' | 'flat' | 'compact'"'wheel'"Visual style. 'wheel' fades and shrinks outer rows like an iOS picker; 'flat' is a simple highlighted row; 'compact' uses smaller text.
variant'wheel' | 'flat' | 'compact'"'wheel'"Visual style. 'wheel' fades and shrinks outer rows like an iOS picker; 'flat' is a simple highlighted row; 'compact' uses smaller text.
disabledboolean"false"Disable interaction across all columns.
disabledboolean"false"Disable interaction across all columns.
classNamestringAdditional CSS class for the picker root.
classNamestringAdditional CSS class for the picker root.
ariaLabelstringAccessible name for the picker group.
ariaLabelstringAccessible name for the picker group.
Features
Single or multi-column
Stack any number of columns for compound values (time, date, units).
Wheel, flat, compact
Three visual variants — iOS wheel by default, plus alternatives.
Touch & scroll-snap
CSS scroll-snap powers native-feeling momentum scrolling.
Keyboard arrows
Up/Down keys move the selection, respecting disabled rows.
Disabled rows
Mark individual options disabled — the picker skips them on settle.
ARIA listbox
Each column is a listbox with aria-activedescendant + selected options.