Combobox
rivelle/comboboxFreeComponent
A searchable controlled option picker built from Command and Popover.
Live preview
live · rendered by the registry
Rendered by rivelle on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://rivelle.dev/r/combobox.jsonSource
1"use client";23import * as React from "react";4import { Check, ChevronsUpDown } from "lucide-react";56import { cn } from "@/lib/utils";7import { Button } from "@/components/ui/button";8import {9 Command,10 CommandEmpty,11 CommandGroup,12 CommandInput,13 CommandItem,14 CommandList,15} from "@/components/ui/command";16import {17 Popover,18 PopoverContent,19 PopoverTrigger,20} from "@/components/ui/popover";2122export type ComboboxOption = {23 value: string;24 label: string;25 disabled?: boolean;26};2728function Combobox({29 options,30 value,31 defaultValue,32 onValueChange,33 placeholder = "Select an option",34 searchPlaceholder = "Search...",35 emptyText = "No results found.",36 disabled,37 className,38}: {39 options: ComboboxOption[];40 value?: string;41 defaultValue?: string;42 onValueChange?: (value: string) => void;43 placeholder?: string;44 searchPlaceholder?: string;45 emptyText?: string;46 disabled?: boolean;47 className?: string;48}) {49 const [open, setOpen] = React.useState(false);50 const [internalValue, setInternalValue] = React.useState(defaultValue ?? "");51 const selectedValue = value ?? internalValue;52 const selected = options.find((option) => option.value === selectedValue);5354 function select(nextValue: string) {55 if (value === undefined) setInternalValue(nextValue);56 onValueChange?.(nextValue);57 setOpen(false);58 }5960 return (61 <Popover open={open} onOpenChange={setOpen}>62 <PopoverTrigger asChild>63 <Button64 role="combobox"65 aria-expanded={open}66 disabled={disabled}67 variant="outline"68 className={cn(69 "h-11.5 w-full justify-between px-4 font-medium hover:-translate-y-0",70 !selected && "text-muted-foreground",71 className,72 )}73 >74 <span className="truncate">{selected?.label ?? placeholder}</span>75 <ChevronsUpDown className="ml-2 size-4 shrink-0 text-muted-foreground" />76 </Button>77 </PopoverTrigger>78 <PopoverContent79 align="start"80 className="w-[var(--radix-popover-trigger-width)] p-0"81 >82 <Command>83 <CommandInput placeholder={searchPlaceholder} />84 <CommandList>85 <CommandEmpty>{emptyText}</CommandEmpty>86 <CommandGroup>87 {options.map((option) => (88 <CommandItem89 disabled={option.disabled}90 key={option.value}91 value={option.label}92// … truncated
What it pulls in
npm packages
Other registry items
Files it writes
More from rivelle
All 83 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Accordionaccordion | rivelle | Components | Free | 2 deps | |
| Alertalert | rivelle | Components | Free | 1 dep | |
| Alert Dialogalert-dialog | rivelle | Components | Free | 1 dep | |
| Aspect Ratioaspect-ratio | rivelle | Components | Free | 1 dep | |
| Avataravatar | rivelle | Components | Free | 1 dep | |
| Badgebadge | rivelle | Components | Free | 2 deps | |
| Breadcrumbbreadcrumb | rivelle | Components | Free | 2 deps | |
| Buttonbutton | rivelle | Components | Free | 2 deps |
