Select
A component that allows users to select a value from a list of options.

Installation
npx shadcn@latest add @tetra-ui/selectUsage
First ensure that you have the PortalHost component in your root layout.
import { PortalHost } from "@/components/ui/portal";
export default function RootLayout() {
return (
<>
<Stack />
<PortalHost />
</>
);
}import { Button } from "@/components/ui/button";
import {
Select,
SelectContentSheet,
SelectContentSheetBody,
SelectContentSheetConfirm,
SelectContentSheetFooter,
SelectContentSheetHeader,
SelectContentSheetTitle,
SelectInput,
SelectItem,
SelectItemIndicator,
SelectItemLabel,
SelectTrigger,
} from "@/components/ui/select";
const OPTIONS = [
{ label: "Option 1", value: "1" },
{ label: "Option 2", value: "2" },
{ label: "Option 3", value: "3" },
];
<Select options={OPTIONS} placeholder="Select...">
<SelectTrigger asChild>
<SelectInput />
</SelectTrigger>
<SelectContentSheet>
<SelectContentSheetHeader>
<SelectContentSheetTitle>Select a value</SelectContentSheetTitle>
</SelectContentSheetHeader>
<SelectContentSheetBody>
{OPTIONS.map((option) => (
<SelectItem
key={option.value}
label={option.label}
value={option.value}
/>
))}
</SelectContentSheetBody>
<SelectContentSheetFooter>
<SelectContentSheetConfirm asChild>
<Button>Confirm</Button>
</SelectContentSheetConfirm>
</SelectContentSheetFooter>
</SelectContentSheet>
</Select>Controlled
Pass value and onValueChange for controlled selection:
const [value, setValue] = useState<string>();
<Select
options={OPTIONS}
value={value}
onValueChange={setValue}
placeholder="Select..."
>
{/* ... */}
</Select>Invalid
Pass invalid to show a destructive border on the trigger input:
<Select options={OPTIONS} invalid placeholder="Select...">
{/* ... */}
</Select>Popover content
For shorter option lists, use SelectContentPopover instead of a sheet:
<Select options={OPTIONS} placeholder="Select...">
<SelectTrigger asChild>
<SelectInput />
</SelectTrigger>
<SelectContentPopover>
{OPTIONS.map((option) => (
<SelectItem
key={option.value}
label={option.label}
value={option.value}
/>
))}
</SelectContentPopover>
</Select>When using popover content, PortalHost must be present in your root layout.
Changelog
30-05-2026 - Migrate to BottomSheet
Use the new BottomSheet component for the sheet content instead of the NativeSheet component.