Skip to content

Select

  • Layer: Component
  • Base: @ark-ui/solid/select (single, multi) + @ark-ui/solid/combobox (searchable)

Select is one component with three call shapes: standard single, multi-select with chips, and searchable (combobox). Trigger height, menu offset, and item geometry are shared across all three so they read as the same primitive.

Backend picker

Selected: ollama

Site picker — right-aligned mono caption ("127 evt")

The selected row gets a left accent bar (2px cyan with glow) — not a checkmark. This is the canonical single-select mark.

Priority — icon left of the label, mirrors into the trigger

Set icon: () => <YourIcon /> on any SelectItemType. The icon renders to the left of the label in every row, left of the selected value in the trigger, and left of the chip label in multi-select chips. Comes through unchanged into the searchable variant’s rows too (the searchable trigger is a text <input>, so icons don’t appear there — that’s a structural property of comboboxes).

Phenomena — chips inside the trigger, +N more overflow

4 selected

The trigger renders selected values as chips (with their icon left of the label, if set); once the count exceeds maxVisibleChips (default 2), the remainder collapses into a dashed +N MORE overflow chip. Menu rows show a 14×14 tick box (not an accent bar) so the multi nature is obvious at a glance.

Combobox-backed single select with type-to-filter

Searchable selects use Ark UI’s Combobox underneath — the trigger becomes an input you can type into, and results filter live.

import { Select, type SelectItemType } from "@risingswamp/design-system";
const items: SelectItemType[] = [
{ value: "swamp-east-2", label: "Swamp bank · east-2", meta: "127 evt" },
{ value: "swamp-west-1", label: "Swamp bank · west-1", meta: "89 evt" },
];
// Single
<Select label="Site" items={items} value={value()} onChange={setValue} />
// Multi
<Select
multiple
label="Phenomena"
items={items}
value={values()}
onChange={setValues}
/>
// Searchable
<Select searchable label="Site" items={items} value={value()} onChange={setValue} />
PropTypeDefaultDescription
itemsSelectItemType[]requiredOptions. See SelectItemType below
labelstringFloating label rendered above the trigger
placeholderstringTrigger placeholder when nothing is selected
disabledbooleanfalseDisables the trigger
namestringForm field name (for <form> integration)
classstringExtra class on the root
variant'outline' | 'ghost''outline'Park UI recipe variant
size'sm' | 'md' | 'lg''md'Park UI recipe size
PropTypeDefaultDescription
valuestringControlled selected value
onChange(value: string) => voidCalled when the selection changes
searchablebooleanfalseUse combobox-backed type-to-filter trigger
PropTypeDefaultDescription
multipletruerequiredSwitches the component into multi mode (discriminant)
valuestring[]Controlled selected values
onChange(value: string[]) => voidCalled when the selection changes
maxVisibleChipsnumber2Chips rendered before collapsing the remainder into a +N MORE overflow
FieldTypeDescription
valuestringStable identifier
labelstringVisible row text
metastringOptional right-aligned mono uppercase caption (e.g. 127 evt, dormant)
icon() => JSX.ElementOptional renderer placed left of the label (and left of the trigger value)
disabledbooleanDisables the row
TokenValueSource / note
Trigger min-height40pxBrief: 04 · Select spec
Menu offset6pxArk UI positioning={{ gutter: 6 }}
Menu max-height240px~6 rows then scroll
Tick box (multi)14×14pxSame geometry as Checkbox
Single markleft accent bar2px rail with cyan glow, no checkmark
Chip textmono 10px UPPERaccent.dim background, accent.text colour
TokenUsage
bg.surface.altTrigger background
bg.surfaceMenu background — opaque, no blur, no shadow
bg.dimHover / highlighted row
accent.defaultSingle accent bar, multi tick fill
accent.dimSelected row background, chip background
accent.textSelected row text, chip text
accent.glowSingle accent bar box-shadow
borderTrigger and menu border, tick-box outline
text.mutedCaret, meta column, placeholder
{shadows.focus-input}Trigger glow on _open and _focusVisible
  • Built on Ark UI Select (single, multi) and Combobox (searchable) — full keyboard support out of the box.
  • Trigger exposes aria-expanded, aria-haspopup="listbox", and aria-controls.
  • Items expose aria-selected (single) / aria-checked (multi); the indicator is decorative.
  • Multi-select chip × buttons stop pointer-down propagation so removing a chip doesn’t reopen the menu.
  • Multi-select never uses an accent bar; single-select never uses a tick box. Reversing them breaks the “what kind of select is this?” read at a glance.
  • meta is opt-in per item — leave it off for short option lists where the caption would be noise.
  • The trigger is Plane-1 by design system rules: no drop shadow, no blur. The cyan glow on focus/open is box-shadow from {shadows.focus-input}, which is permitted as a focus affordance.