Accessibility
Accessibility is built in. Here's what each component exposes to VoiceOver (iOS), TalkBack (Android), screen readers on the web and the keyboard.
Wheels
WheelPicker (and each column of MultiWheelPicker, TimePicker and DateWheelPicker) is a single element with:
| Property | Value |
|---|---|
accessibilityRole | adjustable |
accessibilityValue | the current label, e.g. "45" |
accessibilityActions | increment, decrement: swipe up / down moves one row |
accessibilityLabel | the accessibilityLabel prop |
Name your wheels, especially multi-column ones:
<WheelPicker accessibilityLabel="Shirt size" items={sizes} value={size} onChange={setSize} />
<MultiWheelPicker
columns={[
{ key: 'h', accessibilityLabel: 'Hours', items: hours, value: h, onChange: setH },
{ key: 'm', accessibilityLabel: 'Minutes', items: minutes, value: m, onChange: setM },
]}
/>
Calendar
- Each day is a
buttonlabelled with the full date in the calendar's locale ("Wednesday, 14 October 2026"), withselectedanddisabledstates. - The arrows are buttons labelled Previous and Next, with a
disabledstate at min / max. - The month title is a button (quick jump) or a
header. - Quick-jump grid cells expose
selected/disabled.
Select
- The field is a
buttonlabelled withlabel(or the placeholder). Its hint lists the selected options, and it has anexpandedstate. - Options are
buttons in single mode andcheckboxes in multiple mode, withselected,checkedanddisabled. - Chips are buttons labelled
Remove {label}, and × is labelled Clear. - The search input is labelled with
searchPlaceholder. - While
loading, the loader is aprogressbar.
Every field, SelectPicker, PhoneField, AmountField and OtpField reads "required" after its label when required is set, and reads the error message as its hint.
Slider and rating
- Each slider thumb is
adjustable: swipe up or down to step it. It's named byaccessibilityLabel, orthumbLabelson a range (default Minimum and Maximum), and its value is the formatted number. - An interactive
Ratingisadjustabletoo, named Rating by default, with a value such as "3 of 5" (formatValue). AreadOnlyrating is read as text.
Codes, phone numbers and amounts
OtpFieldis one text input named Verification code by default; the boxes are hidden from screen readers. It asks for SMS autofill (oneTimeCodeon iOS,sms-otpon Android).- In
PhoneField, the country button reads "Country code: " with the country and its dialing code, with anexpandedstate. The number input asks for phone autofill (tel). AmountField's input is named by its label and the currency, such as "Price, US Dollar" (Amount without a label), on a number pad. Its currency button reads "Currency: " with the currency's name, with anexpandedstate.
Menu and action sheet
The Menu trigger is a button with an expanded state. Each action is a button labelled with its label and description, with selected and disabled states. A title has the header role.
Horizontal list
The list is a radiogroup named by accessibilityLabel; each item is a radio labelled with its label, with checked and disabled states.
Emoji
Every emoji cell is a button labelled with its name ("thumbs up"). Category tabs are tabs with a selected state, and the skin-tone button is labelled Skin tone. A long press on an emoji opens its tones, each labelled with the name and tone ("thumbs up, skin tone 3"); the button sets a tone for every emoji without one.
Sheets
The sheet is marked accessibilityViewIsModal, so focus stays inside it. The backdrop is a button labelled Close, string titles have the header role, and Android back closes the sheet.
Keyboard
On the web, every picker works without a mouse:
| Key | What it does |
|---|---|
| Tab | Moves between fields, buttons, wheels and sliders |
| Enter / Space | Opens a field, picks the focused day, option or emoji |
| ↑ ↓ | On a wheel, steps one row. In a calendar, list or grid, moves to the cell above or below. From a search field, goes into the results, and back |
| ← → | Moves to the next cell, wrapping to the next row, or to the next wheel of a date or time |
| Home / End | Jumps to the first or last cell, or to the ends of a wheel or slider |
| Page Up / Page Down | Moves a slider by a bigger step |
| Esc | Closes a sheet or dropdown |
Arrows follow what's drawn, so they go the right way in RTL and in any custom layout. Colour sliders and the colour square move with the arrows, and the clock dial steps its hand. When a sheet or dropdown closes, focus goes back to the field that opened it.
Your checklist
- Give every wheel an
accessibilityLabel. - Translate the English accessibility strings by passing translated
label/placeholder/searchPlaceholderprops. - Keep custom
renderDay/renderOptioncontent as plain views and text. The library already provides the pressable and its accessibility props. - Keep colour contrast when theming:
textSecondaryonbackgroundshould meet WCAG AA (4.5:1) for body text.