Select
Styled native select for predictable keyboard behavior and minimal setup.
01 Live Demo
expand_more
02 Code Snippet
src/ui/Select.tsx
import { Select } from "@/ui/Select"; <Select.Root label="Framework" value={framework} onChange={(event) => setFramework(event.target.value)} options={[ { label: "Next.js", value: "next" }, { label: "Vite", value: "vite" }, { label: "Remix", value: "remix" }, ]} />
03 Copy-Paste (Single File)
Select.tsx
import { forwardRef, type SelectHTMLAttributes } from "react"; type SelectProps = SelectHTMLAttributes<HTMLSelectElement> & { label?: string; options?: Array<{ label: string; value: string }>; }; const SelectRoot = forwardRef<HTMLSelectElement, SelectProps>(function SelectRoot( { label, options = [], children, className, ...props }, ref ) { return ( <div className={className}> {label && <label className="mb-1.5 block text-sm font-medium text-slate-700 dark:text-slate-300">{label}</label>} <div className="relative"> <select ref={ref} className="h-10 w-full appearance-none rounded-lg border border-slate-200 bg-white px-3.5 pr-10 text-sm text-slate-900 outline-hidden focus:border-primary focus:ring-2 focus:ring-primary/20 dark:border-[#1f2937] dark:bg-[#0d1117] dark:text-white" {...props} > {options.map((option) => ( <option key={option.value} value={option.value}>{option.label}</option> ))} {children} </select> <span className="material-symbols-outlined pointer-events-none absolute right-3 top-1/2 -translate-y-1/2 text-[18px] text-slate-400">expand_more</span> </div> </div> ); }); type SelectCompound = typeof SelectRoot & { Root: typeof SelectRoot }; export const Select = Object.assign(SelectRoot, { Root: SelectRoot }) as SelectCompound;