Rime

Combobox

A text field that filters a list of options as you type and picks one, with optional create.

Combobox is the editable combobox: typing opens a frosted list and narrows it by label, description and keywords. It suits long lists people know the name of (a project, a country, a customer). For a short fixed list a person compares, use Select; Select's searchable mode is the same idea with a button trigger.

Leaving the field restores the chosen option's label, so the text never disagrees with the value. creatable offers "Create …" when the text matches nothing, and hands the text to onCreate.

inline renders the list open in normal flow under the field instead of a portalled popover: for docs, previews and pickers that live inside a panel.

Installation

npx shadcn@latest add KezLahd/rime/combobox

Also installs: base, field, icon, text-input.

Usage

import { Combobox } from "@/components/ui";

<Field label="Project">
  <Combobox options={PROJECTS} value={project} onChange={setProject} placeholder="Type to search projects" />
</Field>

Examples

Open list

Shown inline so the list is visible; in a form it is a popover.
  • Atlas redesignDesign · 12 tasks
  • Beacon launchMarketing · 8 tasks
  • Cobalt APIEngineering · 21 tasks
  • Delta onboardingCustomer success · 5 tasks
  • Ember billingFinance · 9 tasks

In a Field

Creatable

Type a new tag to create it.

API

Generated from the component's TypeScript types and JSDoc (scripts/gen-ui-registry.mjs), so it always matches the source.

Combobox

Combobox props
PropTypeDefaultDescription
optionsRequiredReadonlyArray<ComboboxOption>
valueRequiredstring | null
onChangeRequired(value: string | null) => voidThe chosen option's value, or null when the text is cleared.
placeholderstring
creatablebooleanOffer "Create …" when the typed text matches no option. onCreate receives the text; add the option and select it there.
onCreate(label: string) => void
emptyTextstring"No matches"Shown when nothing matches and creatable is off.
size"sm" | "md""md"
disabledboolean
invalidboolean
idstring
namestring
aria-labelstring
defaultOpenbooleanfalseOpen on mount.
inlinebooleanfalseRender the list in normal flow under the field instead of portalling a popover, and keep it open. For docs, previews and pickers inside a panel.
classNamestring

Theme tokens

Per-component tokens are undeclared by default, so the default shown is the fallback the CSS uses. Set one at :root (or in theme.css) to restyle every instance. Live values are read from this page, so they follow the Rime Studio.

Combobox per-component tokens
TokenDefaultLive value
--field-focus-borderrgba(var(--rgb-brand), 0.7) / var(--focus-color)…
--field-focus-ringvar(--focus-halo)…
--field-focus-ring-invalid0 0 0 4px rgba(var(--rgb-danger), 0.14)…
--field-hover-borderrgba(var(--rgb-brand-deep), 0.3)…
--input-bgvar(--surface-solid)…
--input-bordervar(--line-input)…
--input-border-widthvar(--border-w-field)…
--input-font-sizevar(--text-input)…
--input-height-mdvar(--field-h-md)…
--input-height-smvar(--field-h-sm)…
--input-pad-xcalc(14px * var(--density))…
--input-radiusvar(--r-md) / var(--r-sm)…
--input-shadowvar(--shadow-input)…
--popover-item-active-bglinear-gradient(to right, rgba(var(--rgb-brand), 0.14), rgba(var(--rgb-brand-deep), 0.07))…
--popover-item-radiusvar(--r-xs)…
--popover-padcalc(6px * var(--density))…
--popover-radiusvar(--r-lg)…

System tokens it reads

Combobox system tokens
TokenDefaultLive value
--border-wtokens.css…
--border-w-fieldtokens.css…
--brandtokens.css…
--danger-basetokens.css…
--danger-field-filltokens.css…
--densitytokens.css…
--durtokens.css…
--dur-fasttokens.css…
--easetokens.css…
--ease-outtokens.css…
--field-h-mdtokens.css…
--field-h-smtokens.css…
--focus-colortokens.css…
--focus-halotokens.css…
--font-bodytokens.css…
--font-monotokens.css…
--ink-bodytokens.css…
--ink-brandtokens.css…
--ink-disabledtokens.css…
--ink-mutedtokens.css…
--ink-placeholdertokens.css…
--ink-secondarytokens.css…
--line-inputtokens.css…
--line-softtokens.css…
--popover-blurtokens.css…
--popover-bordertokens.css…
--popover-shadowtokens.css…
--popover-surfacetokens.css…
--r-lgtokens.css…
--r-mdtokens.css…
--r-smtokens.css…
--r-xstokens.css…
--rgb-brandtokens.css…
--rgb-brand-deeptokens.css…
--rgb-dangertokens.css…
--scrollbar-thumbtokens.css…
--scrollbar-tracktokens.css…
--scrollbar-widthtokens.css…
--shadow-inputtokens.css…
--surface-solidtokens.css…
--surface-sunkentokens.css…
--text-bodytokens.css…
--text-captiontokens.css…
--text-inputtokens.css…
--text-smalltokens.css…
--wash-subtletokens.css…
--z-popovertokens.css…

Accessibility

  • The input is role="combobox" with aria-expanded, aria-controls, aria-autocomplete="list" and aria-activedescendant, so focus stays in the field while Up and Down move the highlight.
  • Keyboard: typing filters, Up and Down move (and open), Home and End jump, Enter picks, Esc closes and then clears, Tab closes and moves on.
  • The number of results is announced through a polite status region as you type.
  • Give it a Field label, or aria-label when it stands alone.

Do and don't

Do

  • Search descriptions and keywords, not only labels.
  • Use creatable only where adding a value is safe and expected (tags).

Don't

  • Don't use Combobox for fewer than about eight options; use Select or RadioGroup.
  • Don't allow free text that is not saved as an option; that is a TextInput.

For AI agents

This page as markdown, rendered from the same registry entry. Point an agent at it (or add .md to this page's URL), or at /llms.txt for the index.

Open combobox.md

Related: select, command, field