Skip to content
UI

Search docs

Search components and documentation

New
Menu

Combobox

An autocomplete input and command palette built from Popover + Command.

The Combobox isn’t a standalone registry item — it’s a composition of the popover and command components, same as upstream shadcn. Install both, then wire the selection state yourself.

Installation

npx logic2b@latest add popover command

Usage

import * as React from "react"
import { Check, ChevronsUpDown } from "lucide-react"

import { cn } from "@/lib/utils"
import { Button } from "@/components/ui/button"
import {
  Command,
  CommandEmpty,
  CommandGroup,
  CommandInput,
  CommandItem,
  CommandList,
} from "@/components/ui/command"
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"

const frameworks = [
  { value: "next", label: "Next.js" },
  { value: "vite", label: "Vite" },
]

export function Combobox() {
  const [open, setOpen] = React.useState(false)
  const [value, setValue] = React.useState("")

  return (
    <Popover open={open} onOpenChange={setOpen}>
      <PopoverTrigger asChild>
        <Button variant="outline" role="combobox" aria-expanded={open}>
          {value ? frameworks.find((f) => f.value === value)?.label : "Select..."}
          <ChevronsUpDown className="ml-2 size-4 opacity-50" />
        </Button>
      </PopoverTrigger>
      <PopoverContent className="w-[220px] p-0">
        <Command>
          <CommandInput placeholder="Search..." />
          <CommandList>
            <CommandEmpty>No results.</CommandEmpty>
            <CommandGroup>
              {frameworks.map((f) => (
                <CommandItem
                  key={f.value}
                  value={f.value}
                  onSelect={(v) => {
                    setValue(v === value ? "" : v)
                    setOpen(false)
                  }}
                >
                  <Check className={cn("mr-2 size-4", value === f.value ? "opacity-100" : "opacity-0")} />
                  {f.label}
                </CommandItem>
              ))}
            </CommandGroup>
          </CommandList>
        </Command>
      </PopoverContent>
    </Popover>
  )
}

Accessibility

  • The trigger sets role="combobox" and aria-expanded, so assistive tech announces the collapsed/expanded state.
  • Command handles list navigation: / move between items, Enter selects, and typing filters.
  • Esc closes the popover and returns focus to the trigger.