Components

A single-select dropdown — a token-styled wrapper over Base UI's Select. Options are flat { value, label } data, so a CMS/query result drops straight in; the trigger matches Input's height and focus ring, and picks up the invalid treatment inside a Field. For a free-text-filterable list, reach for Base UI's Autocomplete/Combobox directly.

Install

npx shadcn@latest add @alix/select

Preview

Usage

<Field label="Owner">
  <Select
    placeholder="Unassigned"
    items={[
      { value: "jp", label: "J. Patel" },
      { value: "rs", label: "R. Silva" },
    ]}
  />
</Field>

Examples

01

Placeholder and selected states

The trigger shows placeholder copy until a default or controlled value resolves to an option.

<Select
  placeholder="Select capability"
  items={[
    { value: "turnaround", label: "Turnaround" },
    { value: "transactions", label: "Transactions" },
  ]}
/>
<Select
  defaultValue="performance"
  items={[
    { value: "performance", label: "Performance improvement" },
    { value: "investigations", label: "Investigations" },
  ]}
/>
02

Disabled select

Disable the root when the value is locked by workflow or permissions.

<Select
  disabled
  defaultValue="approved"
  items={[
    { value: "draft", label: "Draft" },
    { value: "approved", label: "Approved" },
  ]}
/>
03

Form row with search text

Select pairs with Input and Field when a row combines free text with one constrained choice.

<div className="grid gap-4 md:grid-cols-[1fr_14rem_auto] md:items-end">
  <Field label="Search term">
    <Input placeholder="Engagement or client" />
  </Field>
  <Field label="Capability">
    <Select
      placeholder="Any"
      items={[
        { value: "turnaround", label: "Turnaround" },
        { value: "performance", label: "Performance" },
        { value: "transactions", label: "Transactions" },
      ]}
    />
  </Field>
  <Button variant="outline">Apply</Button>
</div>

When to use it

Use it for

  • Short, flat option lists where exactly one value should be selected.
  • CMS or query-driven options shaped as { value, label } data.
  • Field-wrapped form controls that need the same height and focus treatment as Input.

Reach for something else

  • Free-text entry or searchable filtering — use Input or InputGroup instead.
  • Command lists with actions, links, or separators — use Menu instead.
  • Multiple independent choices — use Checkbox instead.

Props

PropTypeDefaultDescription
itemsSelectOption[]Options as flat data — { value: string, label: ReactNode }[]. Drives both the popup list and the selected label in the trigger.
placeholderReactNode"Select…"Shown when nothing is selected.
value / defaultValuestringControlled / uncontrolled selected value.
onValueChange(value: string) => voidFires with the new value. Never null — this is a single-select with no clear option.
disabled / requiredbooleanStandard control flags; required is forwarded by Field.

See also