Skip to content

Select

A listbox that unfolds in place — the trigger's near corners flatten while the panel pinches away, then items cascade in. Use Select for short known lists (assets, fee tiers); use Combobox when the list is long enough to need filtering.

Trigger states

Placeholder, selected value, and disabled. The trigger flips the panel above itself automatically when there is no room below.

Placeholder
Value selected
Disabled
Hover (forced)

Static replica: border lifts to border-strong.

Focus-visible (forced)

Static replica of the trigger's focus ring.

import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@coldharbor/ui";

<Select defaultValue="btc" onValueChange={setAsset}>
  <SelectTrigger>
    <SelectValue placeholder="Select asset" />
  </SelectTrigger>
  <SelectContent>
    <SelectItem value="btc">Bitcoin (BTC)</SelectItem>
    <SelectItem value="xmr">Monero (XMR)</SelectItem>
  </SelectContent>
</Select>
  • --ch-border
  • --ch-border-strong
  • --ch-bg
  • --ch-bg-raised
  • --ch-fg
  • --ch-fg-muted
  • --ch-focus

Open panel — item states

The Select API has no open prop, so this specimen force-opens the real component by clicking its trigger on mount — the panel renders inline (no portal). It shows the selected item (check mark), default items, and a disabled item. Escape or an outside click dismisses it, as in product.

Open (forced via trigger click)

Selected: Standard. Disabled: Custom rate. Items stagger in with a blur-out cascade.

Fee selector — closed for reference
<SelectContent>
  <SelectItem value="economy">Economy — 2 sat/vB · ~2 hours</SelectItem>
  <SelectItem value="standard">Standard — 6 sat/vB · ~30 minutes</SelectItem>
  <SelectItem value="priority">Priority — 14 sat/vB · ~10 minutes</SelectItem>
  <SelectItem value="custom" disabled>Custom rate — unlock in Settings</SelectItem>
</SelectContent>
  • --ch-border
  • --ch-border-strong
  • --ch-bg
  • --ch-bg-raised
  • --ch-fg
  • --ch-fg-muted
  • --ch-focus

Combobox — filterable lists

Same family, plus a search input in the trigger. The open panel portals to <body> but anchors to the trigger, so it reads inline; the open specimen reserves the space it floats over.

Closed (value selected)

Live — click or focus to open and type to filter.

Open (forced via defaultOpen)

Typing a non-matching query reveals the empty state: “No asset matches that search.”

import { Combobox, ComboboxContent, ComboboxGroup, ComboboxInput, ComboboxItem, ComboboxLabel, ComboboxList, ComboboxTrigger } from "@coldharbor/ui";

<Combobox defaultValue="btc" onValueChange={setAsset}>
  <ComboboxTrigger>
    <ComboboxInput placeholder="Search assets…" />
  </ComboboxTrigger>
  <ComboboxContent>
    <ComboboxList>
      <ComboboxGroup>
        <ComboboxLabel>Assets</ComboboxLabel>
        <ComboboxItem value="btc">Bitcoin (BTC)</ComboboxItem>
      </ComboboxGroup>
    </ComboboxList>
  </ComboboxContent>
</Combobox>
  • --ch-border
  • --ch-border-strong
  • --ch-bg
  • --ch-bg-raised
  • --ch-fg
  • --ch-fg-muted
  • --ch-focus

Themes

The valued trigger under all three layers.

  • --ch-border
  • --ch-border-strong
  • --ch-bg
  • --ch-bg-raised
  • --ch-fg
  • --ch-fg-muted
  • --ch-focus