OptionItem
Selectable row built on Item.
Installation
npx axiom add option-itempnpm dlx axiom add option-itemyarn dlx axiom add option-itembun x axiom add option-itemAlso copies: item.
The row draws no indicator of its own: a check, a chevron, a Switch or a RadioIndicator is something you put in trailing or leading. RadioIndicator and CheckboxIndicator come from Radio and Checkbox, so they match the standalone controls.
Usage
import { OptionItem } from "@/components/ui/option-item";
<OptionItem
label="English"
selected={lang === "en"}
onPress={() => setLang("en")}
trailing={lang === "en" ? <Icon name="check" color="link" /> : null}
/>;Props
OptionItem is an Item with a preset layout, so it also accepts size, divider, disabled and style.
| Prop | Type | Default | Description |
|---|---|---|---|
label | string | — | Main text of the row. |
description | string | — | Secondary text under the label. |
icon | IconName | — | Leading icon on a colored tile, like iOS settings. For an avatar or custom media, compose an Item. |
iconColor | PaletteHue | 'gray' | Tile color from the palette: blue, green, orange… |
selected | boolean | false | Sets accessibilityState.selected. What shows it on screen is yours, in trailing or leading. |
leading | ReactNode | — | Before the icon: a RadioIndicator or a CheckboxIndicator for a list of choices. |
value | ReactNode | — | Current value shown on the right in content.muted, for rows that open a picker. |
trailing | ReactNode | — | After the value: a check, a chevron, a Switch, a Badge. |
destructive | boolean | false | Label in feedback.error, for “Sign out” or “Delete account”. |
onPress | () => void | — | Called when the row is pressed. |
Use cases
Single choice list
The iOS pattern: the checkmark moves to the row the user pressed.
{
sorts.map((s) => (
<OptionItem
key={s.value}
label={s.label}
selected={sort === s.value}
onPress={() => setSort(s.value)}
trailing={sort === s.value ? <Icon name="check" color="link" /> : null}
/>
));
}Settings screen
Icon tiles, values, switches and a destructive row on the same screen, all with one component.
<OptionItem icon="bolt" iconColor="orange" label="Low power mode" trailing={<Switch value={low} onValueChange={setLow} />} />
<OptionItem icon="globe" iconColor="blue" label="Language" value="English" onPress={openLanguage} trailing={<Icon name="chevron-right" size="sm" color="subtle" />} />
<OptionItem label="Sign out" destructive onPress={confirmSignOut} />Multiple selection
A CheckboxIndicator in leading for lists where several rows can be on. The row takes the checkbox role and state, so screen readers read it as one.
<OptionItem
label={c.name}
onPress={() => toggleRecipient(c.id)}
leading={
<>
<CheckboxIndicator checked={recipients.has(c.id)} />
<Avatar size="sm" source={c.photo} fallback={c.initials} />
</>
}
accessibilityRole="checkbox"
accessibilityState={{ checked: recipients.has(c.id) }}
/>