- Docs
- Components
- Select
Select
A select displays a collapsible list of options and allows a user to select one of them.
Preview
Code
Installation
CLI
Manual
Copy and paste the following code into your project.
export * from "./select";
export * as Select from "./namespace";
export * from "./styles";
export {
SelectRoot as Root,
SelectTrigger as Trigger,
SelectPopover as Popover,
SelectContent as Content,
SelectItem as Item,
} from "./select";
"use client";
import {
Button,
Select as SelectPrimitive,
SelectValue,
} from "react-aria-components";
import { ListBoxItem, ListBoxPicker } from "../list-box";
import { PopoverContent } from "../popover";
import { TextFieldStyles } from "../textfield/styles";
import { SelectStyles } from "./styles";
const Icons = {
ChevronDown: (props) => (
<svg
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
width={32}
height={32}
viewBox="0 0 24 24"
{...props}
>
<path
fill="none"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M6 9l6 6 6-6"
/>
</svg>
),
} as const satisfies Record<
string,
(props: React.ComponentProps<"svg">) => React.JSX.Element
>;
export interface SelectRootProps<T extends object>
extends React.ComponentProps<typeof SelectPrimitive<T>> {}
export function SelectRoot<T extends object>({
className,
...props
}: SelectRootProps<T>) {
return (
<SelectPrimitive
{...props}
className={TextFieldStyles.Provider({ className })}
/>
);
}
export interface SelectTriggerProps
extends Omit<React.ComponentProps<typeof Button>, "children"> {}
export function SelectTrigger({ className, ...props }: SelectTriggerProps) {
return (
<Button {...props} className={SelectStyles.Trigger({ className })}>
<SelectValue className="select-none text-base placeholder-shown:text-muted-fg lg:text-sm [&_[slot=description]]:hidden" />
<Icons.ChevronDown
aria-hidden="true"
className="size-4 shrink-0 text-muted-fg duration-200 group-open:rotate-180 group-disabled:opacity-50"
/>
</Button>
);
}
export interface SelectPopoverProps
extends React.ComponentProps<typeof PopoverContent> {}
export const SelectPopover = PopoverContent;
export interface SelectContentProps
extends React.ComponentProps<typeof ListBoxPicker> {}
export const SelectContent = ListBoxPicker;
export interface SelectItemProps
extends React.ComponentProps<typeof ListBoxItem> {}
export const SelectItem = ListBoxItem;
import { cva } from "~/lib/cva";
export const SelectStyles = {
Trigger: cva({
base: [
"flex h-9 w-full items-center justify-between whitespace-nowrap rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-xs outline-hidden ring-offset-bg transition",
"placeholder:text-muted-fg focus-visible:ring-1 focus-visible:ring-ring [&>span]:line-clamp-1",
"disabled:cursor-not-allowed disabled:opacity-50",
"group-invalid:border-danger group-invalid:focus:border-danger group-invalid:focus:ring-4 group-invalid:focus:ring-danger/20",
],
}),
};
Update the import paths to match your project setup.
Usage
Single import
import { Select } from "~/components/ui/select";
<Select.Root>
<Select.Trigger />
<Select.Popover>
<Select.Content items={fruits}>
{(item) => (
<Select.Item id={item.id} textValue={item.name}>
{item.name}
<Icons.Check className="size-0 opacity-0 group-selected:size-4 group-selected:opacity-100" />
</Select.Item>
)}
</Select.Content>
</Select.Popover>
</Select.Root>
Multiple imports
import {
SelectContent,
SelectItem,
SelectPopover,
SelectRoot,
SelectTrigger,
} from "~/components/ui/select";
<SelectRoot>
<SelectTrigger />
<SelectPopover>
<SelectContent items={fruits}>
{(item) => (
<SelectItem id={item.id} textValue={item.name}>
{item.name}
<Icons.Check className="size-0 opacity-0 group-selected:size-4 group-selected:opacity-100" />
</SelectItem>
)}
</SelectContent>
</SelectPopover>
</SelectRoot>
Examples
Unselectable
Preview
Code
With Label
Preview
Code
Choose a fruit
Form
Preview
Code