The control that opens a sheet. It looks like an input because it is one — the same fill, edge, radius and height — with a chevron and a value in place of a cursor.
Light
Empty
Chosen · a string
Chosen · a node (avatar and two lines)
Focus
Error · after submit
Choose who conferred it.
Dark
Empty
Chosen · a string
Chosen · a node (avatar and two lines)
Focus
Error · after submit
Choose who conferred it.
Source:
SelectTrigger.tsx. The sheet it opens: sheet-picker and Bottom sheet.
When to use it
- For a value chosen from a list of seven or more: a student, an instructor, a rank.
- For a date or a time, which opens the native picker.
Not for two to six options — show chips inline so the choice stays visible. Not for text someone types — that is an Input.
Anatomy
| Part | Token |
|---|---|
| Frame | surface.card, 1px border.control, radius.input 8 |
| Padding | spacing.s12, spacing.s12 between content and chevron |
| Height floor | controlHeight.control 44 for every state; a value with an avatar grows past it |
| Placeholder | typography.body, text.tertiary |
| Value | a string renders as typography.body, text.primary; a node renders as given |
| Chevron | caretRight at iconSize.inline 16, text.tertiary |
States
- Empty: the placeholder.
- Chosen: the value — a string, or a node such as an avatar with a name and a rank line.
- Pressed:
opacity.pressed0.85. - Focus: 2px
border.focus, padding adjusted so the control does not resize. - Error:
feedback.errorBorderedge and the field's message below. Focus wins over error. - Validation timing: a trigger has no blur, so it validates on submit, then re-validates
live once it has been in error. That is why
hasErroris a prop. - Disabled: the prop exists; prefer saying why the choice is fixed in the field's helper.
Content
- The placeholder names what is chosen: "Choose a student", "Choose who conferred it".
- A name is the one string nobody may mangle: the trigger grows rather than truncating.
Accessibility
- The whole trigger is one stop with role
button. Avatar, swatch and chevron are decoration. - Its
accessibilityLabelcomes fromfieldControlProps, which includes the value — omit the value and a screen-reader user hears the field's name with nothing in it. - Opening the sheet moves focus into it; closing returns focus here.
Do and don't
Do
It looks like an input, with a chevron that says a sheet is coming.
Don’t
A bare link pretending to be a field: no edge, no target, no error state.
Code
import { Field, SelectTrigger, fieldControlProps } from '../../components/ui';
<Field label="Conferred by" error={submitted && !instructor ? 'Choose who conferred it.' : undefined}>
<SelectTrigger
placeholder="Choose who conferred it"
value={instructor?.name}
onPress={openInstructorSheet}
testID="promotion-conferred-by"
{...fieldControlProps({ label: 'Conferred by', value: instructor?.name })}
/>
</Field>