Components

Select

A dropdown select, measured from Attio's choice fields.

Available since@crisp-ui-kit/crisp@0.11.0

Measured from Attio's choice fields (the create-record dialog's Deal stage and Categories). A role="combobox" trigger (value + chevron) — a 32px field, 9px radius, 6/8px padding, a faint fill and a 1px inset edge — opens a portaled role="listbox": 12px radius, the shared popover shadow, 32px option rows (5px padding, 8px radius, a raised hover fill, 1px between rows) that show a brand check on the selected one. Pass searchable for a Linear/cmdk-style filter row (36px, a hairline under it) at the top of the list (the Timezone select below). An option can carry an optional second-line description.

Installation

npm install @crisp-ui-kit/crisp

Compact

Props

Prop

Type

SelectOption is { value, label, keywords?, color?, disabled?, group?, description? } — set keywords to control the searchable text when the label isn't a plain string, and description for a second line under the label.

Notes

  • Keyboard. Closed: ↓ / Enter / Space open (highlighting the selected option). Open: ↑/↓ move, Home/End jump, Enter/Space pick, Esc closes and returns focus to the trigger, Tab closes.
  • Semantics. A role="combobox" button with aria-expanded / aria-haspopup="listbox"; each option is a role="option" with aria-selected; the check marks the current value.
  • Placement. The listbox opens below, or flips above when there isn't room; it closes on outside pointer-down.
  • readOnly vs disabled. Both refuse to open; readOnly keeps the trigger focusable and full-strength, disabled removes it from the tab order and dims it.
  • Attio-measured (crisp/#1071). This is Attio's own field again; the seed-design rebuild (#867 and its follow-ups) is gone. size (small/medium/large) is still accepted so existing code compiles, but is ignored: Attio has one 32px trigger. For Linear's settings select pass compact (crisp#1302): a 30px trigger with an 8px radius instead of 32px / 9px. It is opt-in, and nothing changes unless you pass it. invalid is a 1px red ring, not a thicker border. triggerLabel, searchable, description and readOnly are crisp's own and stay.

Used across the settings surface.

On this page