Glin UI
Primitive / Moleculebeta

Combobox

A searchable select built from Popover and Command.

Edit on GitHub

New project

Pick the framework we should scaffold. Type to filter the list.

Next.js starter selected

Installation

Install from
pnpm dlx @glinui/cli@latest add combobox

Prefer the package?

Usage

Combobox is single select only. For multiple selection, compose Popover with Command, or use a checkbox group.

Variants

import { Combobox } from "@glinui/ui"
const frameworks = [
{ value: "next", label: "Next.js" },
{ value: "remix", label: "Remix" },
{ value: "astro", label: "Astro", keywords: ["islands"] },
{ value: "nuxt", label: "Nuxt" },
{ value: "sveltekit", label: "SvelteKit" }
]
export function Demo() {
return (
<div className="grid gap-3 sm:grid-cols-2">
<Combobox variant="glinr" options={frameworks} aria-label="glinr" placeholder="glinr" />
<Combobox variant="solid" options={frameworks} aria-label="solid" placeholder="solid" />
<Combobox variant="plain" options={frameworks} aria-label="plain" placeholder="plain" />
<Combobox variant="soft" options={frameworks} aria-label="soft" placeholder="soft" />
<Combobox variant="outline" options={frameworks} aria-label="outline" placeholder="outline" />
<Combobox variant="ghost" options={frameworks} aria-label="ghost" placeholder="ghost" />
</div>
)
}

Glass (opt-in)

Glass is opt-in and needs a backdrop behind it: pick Photo or Vivid in the stage backdrop switcher.

import { Combobox } from "@glinui/ui"
const frameworks = [
{ value: "next", label: "Next.js" },
{ value: "remix", label: "Remix" },
{ value: "astro", label: "Astro", keywords: ["islands"] },
{ value: "nuxt", label: "Nuxt" },
{ value: "sveltekit", label: "SvelteKit" }
]
export function Demo() {
return <Combobox variant="glass" options={frameworks} aria-label="Framework" />
}

Accessibility

  • Trigger is `role="combobox"` with `aria-expanded`, `aria-haspopup="listbox"` and `aria-controls`.
  • The panel is a filterable listbox (Command) with a labelled search field.
  • Focus returns to the trigger when the panel closes.
  • Pass `aria-label` or label it through Field.

Keyboard Interactions

KeyAction
Enter / Space / Arrow DownOpen the list from the trigger.
TypeFilter options.
Arrow Up / DownMove the highlighted option.
EnterSelect the highlighted option.
EscapeClose without changing the value.

ARIA Attributes

  • `role="combobox"` and `aria-expanded` on trigger
  • `aria-invalid` and `aria-describedby` pass through
  • `role="listbox"` and `role="option"` from cmdk

Reduced Motion

Panel open and close animations are disabled under prefers-reduced-motion.

Affected properties

opacitytransform

API Reference

PropTypeRequiredDefaultDescription
optionsComboboxOption[]Yes-Required. Selectable items.
value | defaultValuestring--Controlled or initial selection.
onValueChange(value: string) => voidNo-Fires on selection. Empty string means cleared.
open | onOpenChangeboolean | (open: boolean) => void--Controlled popover state.
placeholderstringNoSelect an optionTrigger text with no selection.
searchPlaceholderstringNoSearch...Placeholder of the filter input.
emptyTextstringNoNo results found.Shown when nothing matches.
clearablebooleanNofalseSelecting the active option again clears it.
namestringNo-Adds a hidden input for native form submission.
variantControlVariantPropNoambient (glinr)Trigger look. Omit to follow the ambient design style. Glass is opt-in and also frosts the panel.
size"sm" | "md" | "lg"NomdTrigger height.
aria-describedbystringNo-Auto-generated from TypeScript source.
aria-invalidboolean | "true" | "false"No-Auto-generated from TypeScript source.
aria-labelstringNo-Auto-generated from TypeScript source.
aria-labelledbystringNo-Auto-generated from TypeScript source.
classNamestringNo-Auto-generated from TypeScript source.
contentClassNamestringNo-Extra class for the popover panel.
defaultValuestringNo""Initial value for uncontrolled usage.
disabledbooleanNo-Auto-generated from TypeScript source.
idstringNo-Auto-generated from TypeScript source.
onOpenChange(open: boolean) => voidNo-Auto-generated from TypeScript source.
openbooleanNo-Controlled open state.
valuestringNo-Controlled selected value.

Source

Import directly from the package or browse the source on GitHub. Click any file to view it.

Import

import { Combobox } from "@glinui/ui"

Source Files

Dependencies

@glinui/ui@phosphor-icons/reactclass-variance-authority

Generated API Snapshot

Beta

Auto-extracted from TypeScript source in packages/ui/src/components/combobox.tsx. This section is in beta and may lag behind hand-curated docs. Regenerate with pnpm --filter @glinui/docs api:generate.

Generated: 2026-10-08T01:41:21.546Z · Full index: /docs/api-metadata

Primary Props Type

ComboboxProps

ComboboxProps

PropTypeRequiredDefaultDescription
aria-describedbystringNo--
aria-invalidboolean | "true" | "false"No--
aria-labelstringNo--
aria-labelledbystringNo--
classNamestringNo--
clearablebooleanNofalseAllow selecting the active option again to clear it.
contentClassNamestringNo-Extra class for the popover panel.
defaultValuestringNo""Initial value for uncontrolled usage.
disabledbooleanNo--
emptyTextstringNo"No results found."Message shown when no option matches.
idstringNo--
namestringNo-Form field name; renders a hidden input with the value.
onOpenChange(open: boolean) => voidNo--
onValueChange(value: string) => voidNo-Fires when the selection changes. Empty string means cleared.
openbooleanNo-Controlled open state.
optionsComboboxOption[]Yes--
placeholderstringNo"Select an option"Trigger text when nothing is selected.
searchPlaceholderstringNo"Search..."Placeholder inside the search input.
size"sm" | "md" | "lg"No"md"Variant option from comboboxSizeVariants.
valuestringNo-Controlled selected value.
variantControlVariantPropNo-Trigger look. Omit to follow the ambient design style (glinr = inset well). Same vocabulary as Input.