Design System

Dropdowns & selects

One unified dropdown family. Every trigger shares the V2 field chrome, a single right-side chevron, the standard focus treatment and the FormField label / helper / error hierarchy.

Family rules

Applies to Select, Combobox, MultiSelect and UserSelect alike.

What is this?

One dropdown family — Select, Combobox, MultiSelect and UserSelect — sharing the V2 field chrome, a single right-side chevron, the standard focus ring and the FormField label / helper / error hierarchy.

When to use it

  • Choosing from a known set of values inside a form or filter bar
  • Long directories where search is needed (Combobox)
  • Several values at once (MultiSelect)

How to use it

  • Exactly one chevron, always right-aligned and vertically centred
  • Leading icons only when meaningful — status, record type, avatar
  • Clear action sits left of the chevron so clearing and opening stay distinct
  • Selection uses a check icon plus subtle highlight and medium weight, never colour alone
  • Sizes small (32px), default (40px) and large (48px) come from the shared control tokens

What to avoid

  • Chevrons on the left, or a second dropdown arrow
  • Decorative leading icons
  • New focus, shadow or colour treatments specific to Select

Select

The default single-selection control.

Select

Choose one value from a short, known list. Built on Radix Select for native keyboard, typeahead and ARIA behaviour.

import { Select } from "@/design-system";

When to use

  • Between roughly 3 and 15 known options
  • Where the value is a single, required choice such as a property or plan
  • Inside forms that already use FormField label and helper conventions

When not to use

  • Two mutually exclusive options — use Radio or a segmented control
  • Long directories of people or records — use the searchable Combobox
  • Several values at once — use MultiSelect

Default, placeholder and filled

Only properties you manage are listed.

Filled state — the value reads at full text contrast.

Sizes

Required, optional and helper text

Choose the resident associated with this request.

Error, disabled and read-only

Set by the care plan and cannot be changed here.

Options with supporting descriptions

Do

  • Keep the chevron as the only trigger icon
  • Distinguish placeholder from a chosen value using the tertiary text token

Don't

  • Add a second chevron or a left-side dropdown arrow
  • Use disabled styling for placeholder text

Accessibility

  • The trigger exposes role=combobox with expanded / collapsed state and the selected value as its accessible name.
  • Tab, Enter, Space, arrow keys, Home / End, Escape and typeahead are all supported.
  • Required, disabled, read-only and invalid states are announced via aria-required, aria-disabled, aria-readonly and aria-invalid.
  • Helper text and error messages are wired through aria-describedby; errors also carry role=alert.

Select with icon and status values

Leading icons only where they carry information.

Select with icon

Surface meaningful leading icons — most often semantic status — on both the trigger and the option list.

<Select options={[{ value: "active", label: "Active", icon: <CheckCircle2 /> }]} />

When to use

  • Status values
  • Record types that users scan by shape
  • Property or location kinds

When not to use

  • Decoration
  • Where the icon repeats the label with no added meaning

Select status

Accessibility

  • Icons are aria-hidden; the option label carries the meaning so status is never colour-only.
  • Status colours come from the existing semantic tokens — no new colours are introduced.

Grouped select

Subtle, non-selectable group headings.

Grouped Select

Split one list into labelled sections — residents versus staff, for example — without changing the selection model.

<Select groups={[{ label: "Residents", options: [...] }]} />

When to use

  • Options fall into two or three obvious categories
  • Users think in categories before values

When not to use

  • More than about five groups — filter or search instead
  • Groups with a single option each

Select employee or resident

Grouped by record type.

Accessibility

  • Group headings use Radix SelectGroup / SelectLabel so they are announced as group names, not options.
  • Headings are not focusable and are visually subordinate to option labels.

Searchable & clearable select

For long lists and optional values.

Searchable Select (Combobox)

Filter long lists by typing. The search field sits inside the menu, visually distinct from the trigger.

import { Combobox } from "@/design-system";

When to use

  • More than about 15 options
  • Directories of residents, staff or records
  • Where users know the name they want

When not to use

  • Short lists — the extra search step slows people down
  • Multiple values — use MultiSelect

Choose a resident

Search by name; disabled residents are discharged.

Clearable — the clear action sits left of the chevron.

Read-only and error

Locked while the request is in review.

Accessibility

  • Typing filters options while focus stays in the search field; arrow keys move the active option and Enter selects it.
  • Escape closes the menu and returns focus to the trigger.
  • An explicit no-results message is shown inside the menu rather than the generic empty state.

Select with avatar

People pickers use the V2 Avatar at small size.

Select with avatar

Identify people by face, name and a supporting role line so similarly named records can be told apart.

<Combobox options={[{ value, label, description, media: <Avatar size="small" name={label} /> }]} />

When to use

  • Assigning a resident, key worker or employee
  • Where names alone are ambiguous

When not to use

  • Non-person records
  • Where the supporting line would be empty

Choose a resident

Assign one or more employees to this visit.

Accessibility

  • Avatars are decorative; the name and role text carry the information.
  • UserSelect covers multi-assignee flows with removable pills and search.

Multi select

Several values, with select all and clear all.

MultiSelect

Choose several values from one list. Selected values appear as removable chips that wrap instead of clipping the chevron.

import { MultiSelect } from "@/design-system";

When to use

  • Notification types, locations, tags or filters
  • Where select all or clear all is genuinely useful

When not to use

  • Single-value fields — use Select
  • Two or three options — use a checkbox group

Select notification type

Incident reportsMedication alerts

Chips wrap below the control on narrow screens.

Willow House

Error and disabled

Visit reminders

Do

  • Let selected chips wrap
  • Offer clear all when more than a couple of values are typical

Don't

  • Let chips overlap or clip the chevron
  • Hide the number of selected values

Accessibility

  • Each option reports its checked state; the check icon and weight change convey selection without colour.
  • Every chip has its own labelled remove control, reachable by keyboard.
  • Select all reflects a partial selection and flips to clear all when everything is chosen.

Responsive & positioning

Verified at desktop, tablet and mobile widths.

  • Width: Menus match the trigger width and are capped to the viewport minus the standard gutter.
  • Collision: Menus flip and shift with 12px viewport padding, so they never render off-screen.
  • Touch targets: Triggers and clear actions meet the 24px / 44px target rules via ds-target.
  • Overflow: Long labels truncate on the trigger and wrap in the option list; chips wrap below the control.