<!-- https://getkonjo.com/design/components/select-trigger · source: docs/design/components/select-trigger.md -->

# Select trigger

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.

```kata-specimen
trigger-states
```

> Source: [`SelectTrigger.tsx`](../../../src/components/ui/SelectTrigger.tsx). The sheet it opens:
> [sheet-picker](../patterns/sheet-picker.md) and [Bottom sheet](bottom-sheet.md).

## 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](tag-chip.md) inline so the choice stays visible. Not
for text someone types — that is an [Input](input.md).

## 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.pressed` 0.85.
- **Focus**: 2px `border.focus`, padding adjusted so the control does not resize.
- **Error**: `feedback.errorBorder` edge 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 `hasError` is 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 `accessibilityLabel` comes from `fieldControlProps`, 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

```kata-specimen
trigger-chevron
```

## Code

```tsx
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>
```
