A common form component for choosing a predefined value in a dropdown menu.
Installation
npx shadcn@latest add @caprice/selectpnpm dlx shadcn@latest add @caprice/selectyarn dlx shadcn@latest add @caprice/selectbunx shadcn@latest add @caprice/selectnpm install @caprice-ui/reactpnpm add @caprice-ui/reactyarn add @caprice-ui/reactbun add @caprice-ui/reactInstall the following dependencies:
npm install @base-ui/react lucide-reactpnpm add @base-ui/react lucide-reactyarn add @base-ui/react lucide-reactbun add @base-ui/react lucide-reactAdd a cn helper
import { defineConfig, getSchema, type VariantProps } from 'cva';
import { twMerge } from 'tailwind-merge';
export const { cva, cx: cn } = defineConfig({
hooks: {
onComplete: (className: string) => twMerge(className),
},
});
export type { VariantProps };
export { getSchema };
Copy and paste the following code into your project.
import { Select as SelectPrimitive } from '@base-ui/react/select';
import { ChevronsUpDownIcon } from 'lucide-react';
import { cn } from '@/lib/utils';
/**
* Groups all parts of the select.
* Doesn't render its own HTML element.
*
* Documentation: [Caprice UI Select](https://caprice-ui.com/docs/components/select)
*
* API Reference: [Base UI Select](https://base-ui.com/react/components/select#root)
*/
export namespace Root {
export type Props = React.ComponentProps<typeof SelectPrimitive.Root>;
export type State = SelectPrimitive.Root.State;
export type Actions = SelectPrimitive.Root.Actions;
export type ChangeEventDetails = SelectPrimitive.Root.ChangeEventDetails;
export type ChangeEventReason = SelectPrimitive.Root.ChangeEventReason;
}
export function Root({ ...props }: Root.Props) {
return <SelectPrimitive.Root data-slot="select" {...props} />;
}
/**
* A button that opens the select popup.
* Renders a `<button>` element.
*
* Documentation: [Caprice UI Select](https://caprice-ui.com/docs/components/select)
*
* API Reference: [Base UI Select](https://base-ui.com/react/components/select#trigger)
*/
export namespace Trigger {
export type State = SelectPrimitive.Trigger.State;
export type Props = React.ComponentProps<typeof SelectPrimitive.Trigger> & {
/**
* The size of the select trigger.
* @default 'md'
*/
size?: 'sm' | 'md' | 'lg';
};
}
export function Trigger({ className, size = 'md', children, ...props }: Trigger.Props) {
return (
<SelectPrimitive.Trigger
className={cn(
"flex h-9 w-fit items-center justify-between gap-2 whitespace-nowrap rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-xs outline-none transition-[color,box-shadow] focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 data-placeholder:text-muted-foreground *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 dark:bg-input/30 dark:aria-invalid:ring-destructive/40 dark:hover:bg-input/50 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0",
size === 'sm' && 'h-8',
size === 'lg' && 'h-10',
className
)}
data-size={size}
data-slot="select-trigger"
{...props}
>
{children}
<SelectPrimitive.Icon data-slot="select-icon">
<ChevronsUpDownIcon className="opacity-50" />
</SelectPrimitive.Icon>
</SelectPrimitive.Trigger>
);
}
/**
* An accessible label that is automatically associated with the select trigger.
* Renders a `<div>` element.
*
* Documentation: [Caprice UI Select](https://caprice-ui.com/docs/components/select)
*
* API Reference: [Base UI Select](https://base-ui.com/react/components/select#label)
*/
export namespace Label {
export type State = SelectPrimitive.Label.State;
export type Props = React.ComponentProps<typeof SelectPrimitive.Label>;
}
export function Label({ ...props }: Label.Props) {
return <SelectPrimitive.Label data-slot="select-label" {...props} />;
}
/**
* A text label of the currently selected item.
* Renders a `<span>` element.
*
* Documentation: [Caprice UI Select](https://caprice-ui.com/docs/components/select)
*
* API Reference: [Base UI Select](https://base-ui.com/react/components/select#value)
*/
export namespace Value {
export type State = SelectPrimitive.Value.State;
export type Props = React.ComponentProps<typeof SelectPrimitive.Value>;
}
export function Value({ ...props }: Value.Props) {
return <SelectPrimitive.Value data-slot="select-value" {...props} />;
}
/**
* An icon that indicates that the trigger button opens a select popup.
* Renders a `<span>` element.
*
* Documentation: [Caprice UI Select](https://caprice-ui.com/docs/components/select)
*
* API Reference: [Base UI Select](https://base-ui.com/react/components/select#icon)
*/
export namespace Icon {
export type State = SelectPrimitive.Icon.State;
export type Props = React.ComponentProps<typeof SelectPrimitive.Icon>;
}
export function Icon({ ...props }: Icon.Props) {
return <SelectPrimitive.Icon data-slot="select-icon" {...props} />;
}
/**
* An overlay displayed beneath the select popup.
* Renders a `<div>` element.
*
* Documentation: [Caprice UI Select](https://caprice-ui.com/docs/components/select)
*
* API Reference: [Base UI Select](https://base-ui.com/react/components/select#backdrop)
*/
export namespace Backdrop {
export type State = SelectPrimitive.Backdrop.State;
export type Props = React.ComponentProps<typeof SelectPrimitive.Backdrop>;
}
export function Backdrop({ className, ...props }: Backdrop.Props) {
return (
<SelectPrimitive.Backdrop
className={cn(
'fixed inset-0 z-50 bg-black/40 backdrop-blur-[10px] transition-all duration-200 ease-in-out [[data-starting-style],[data-ending-style]]:opacity-0',
className
)}
data-slot="select-backdrop"
{...props}
/>
);
}
/**
* A portal element that moves the popup to a different part of the DOM.
* By default, the portal element is appended to `<body>`.
* Renders a `<div>` element.
*
* Documentation: [Caprice UI Select](https://caprice-ui.com/docs/components/select)
*
* API Reference: [Base UI Select](https://base-ui.com/react/components/select#portal)
*/
export namespace Portal {
export interface State extends SelectPrimitive.Portal.State {}
export type Props = React.ComponentProps<typeof SelectPrimitive.Portal>;
}
export function Portal({ ...props }: Portal.Props) {
return <SelectPrimitive.Portal data-slot="select-portal" {...props} />;
}
/**
* Positions the select popup.
* Renders a `<div>` element.
*
* Documentation: [Caprice UI Select](https://caprice-ui.com/docs/components/select)
*
* API Reference: [Base UI Select](https://base-ui.com/react/components/select#positioner)
*/
export namespace Positioner {
export type State = SelectPrimitive.Positioner.State;
export type Props = React.ComponentProps<typeof SelectPrimitive.Positioner> & {
/**
* Whether to render a backdrop behind the positioner.
* @default false
*/
backdrop?: boolean;
};
}
export function Positioner({ backdrop = false, className, ...props }: Positioner.Props) {
return (
<Portal>
{backdrop && <Backdrop />}
<SelectPrimitive.Positioner
className={cn('z-50', className)}
data-slot="select-positioner"
{...props}
/>
</Portal>
);
}
/**
* A container for the select list.
* Renders a `<div>` element.
*
* Documentation: [Caprice UI Select](https://caprice-ui.com/docs/components/select)
*
* API Reference: [Base UI Select](https://base-ui.com/react/components/select#popup)
*/
export namespace Popup {
export type State = SelectPrimitive.Popup.State;
export type Props = React.ComponentProps<typeof SelectPrimitive.Popup>;
}
export function Popup({ children, ...props }: Popup.Props) {
return (
<SelectPrimitive.Popup data-slot="select-popup" {...props}>
<ScrollUpArrow />
<SelectPrimitive.List
className="max-h-(--available-height) min-w-(--anchor-width) bg-popover"
data-slot="select-list"
>
{children}
</SelectPrimitive.List>
<ScrollDownArrow />
</SelectPrimitive.Popup>
);
}
/**
* A container for the select items.
* Renders a `<div>` element.
*
* Documentation: [Caprice UI Select](https://caprice-ui.com/docs/components/select)
*
* API Reference: [Base UI Select](https://base-ui.com/react/components/select#list)
*/
export namespace List {
export type State = SelectPrimitive.List.State;
export type Props = React.ComponentProps<typeof SelectPrimitive.List>;
}
export function List({ ...props }: List.Props) {
return <SelectPrimitive.List data-slot="select-list" {...props} />;
}
/**
* Displays an element positioned against the select popup anchor.
* Renders a `<div>` element.
*
* Documentation: [Caprice UI Select](https://caprice-ui.com/docs/components/select)
*
* API Reference: [Base UI Select](https://base-ui.com/react/components/select#arrow)
*/
export namespace Arrow {
export type State = SelectPrimitive.Arrow.State;
export type Props = React.ComponentProps<typeof SelectPrimitive.Arrow>;
}
export function Arrow({ ...props }: Arrow.Props) {
return <SelectPrimitive.Arrow data-slot="select-arrow" {...props} />;
}
/**
* An individual option in the select popup.
* Renders a `<div>` element.
*
* Documentation: [Caprice UI Select](https://caprice-ui.com/docs/components/select)
*
* API Reference: [Base UI Select](https://base-ui.com/react/components/select#item)
*/
export namespace Item {
export type State = SelectPrimitive.Item.State;
export type Props = React.ComponentProps<typeof SelectPrimitive.Item>;
}
export function Item({ ...props }: Item.Props) {
return <SelectPrimitive.Item data-slot="select-item" {...props} />;
}
/**
* A text label of the select item.
* Renders a `<div>` element.
*
* Documentation: [Caprice UI Select](https://caprice-ui.com/docs/components/select)
*
* API Reference: [Base UI Select](https://base-ui.com/react/components/select#item-text)
*/
export namespace ItemText {
export type State = SelectPrimitive.ItemText.State;
export type Props = React.ComponentProps<typeof SelectPrimitive.ItemText>;
}
export function ItemText({ ...props }: ItemText.Props) {
return <SelectPrimitive.ItemText data-slot="select-item-text" {...props} />;
}
/**
* Indicates whether the select item is selected.
* Renders a `<span>` element.
*
* Documentation: [Caprice UI Select](https://caprice-ui.com/docs/components/select)
*
* API Reference: [Base UI Select](https://base-ui.com/react/components/select#item-indicator)
*/
export namespace ItemIndicator {
export type State = SelectPrimitive.ItemIndicator.State;
export type Props = React.ComponentProps<typeof SelectPrimitive.ItemIndicator>;
}
export function ItemIndicator({ ...props }: ItemIndicator.Props) {
return <SelectPrimitive.ItemIndicator data-slot="select-item-indicator" {...props} />;
}
/**
* Groups related select items with the corresponding label.
* Renders a `<div>` element.
*
* Documentation: [Caprice UI Select](https://caprice-ui.com/docs/components/select)
*
* API Reference: [Base UI Select](https://base-ui.com/react/components/select#group)
*/
export namespace Group {
export type State = SelectPrimitive.Group.State;
export type Props = React.ComponentProps<typeof SelectPrimitive.Group>;
}
export function Group({ ...props }: Group.Props) {
return <SelectPrimitive.Group data-slot="select-group" {...props} />;
}
/**
* An accessible label that is automatically associated with its parent group.
* Renders a `<div>` element.
*
* Documentation: [Caprice UI Select](https://caprice-ui.com/docs/components/select)
*
* API Reference: [Base UI Select](https://base-ui.com/react/components/select#group-label)
*/
export namespace GroupLabel {
export type State = SelectPrimitive.GroupLabel.State;
export type Props = React.ComponentProps<typeof SelectPrimitive.GroupLabel>;
}
export function GroupLabel({ ...props }: GroupLabel.Props) {
return <SelectPrimitive.GroupLabel data-slot="select-group-label" {...props} />;
}
/**
* An element that scrolls the select popup up when hovered. Does not render when using touch input.
* Renders a `<div>` element.
*
* Documentation: [Caprice UI Select](https://caprice-ui.com/docs/components/select)
*
* API Reference: [Base UI Select](https://base-ui.com/react/components/select#scroll-up-arrow)
*/
export namespace ScrollUpArrow {
export type State = SelectPrimitive.ScrollUpArrow.State;
export type Props = React.ComponentProps<typeof SelectPrimitive.ScrollUpArrow>;
}
export function ScrollUpArrow({ ...props }: ScrollUpArrow.Props) {
return <SelectPrimitive.ScrollUpArrow data-slot="select-scroll-up-arrow" {...props} />;
}
/**
* An element that scrolls the select popup down when hovered. Does not render when using touch input.
* Renders a `<div>` element.
*
* Documentation: [Caprice UI Select](https://caprice-ui.com/docs/components/select)
*
* API Reference: [Base UI Select](https://base-ui.com/react/components/select#scroll-down-arrow)
*/
export namespace ScrollDownArrow {
export type State = SelectPrimitive.ScrollDownArrow.State;
export type Props = React.ComponentProps<typeof SelectPrimitive.ScrollDownArrow>;
}
export function ScrollDownArrow({ ...props }: ScrollDownArrow.Props) {
return <SelectPrimitive.ScrollDownArrow data-slot="select-scroll-down-arrow" {...props} />;
}
/**
* A visual separator between items or groups.
* Renders a `<div>` element.
*
* Documentation: [Caprice UI Select](https://caprice-ui.com/docs/components/select)
*
* API Reference: [Base UI Select](https://base-ui.com/react/components/select#separator)
*/
export namespace Separator {
export type State = SelectPrimitive.Separator.State;
export type Props = React.ComponentProps<typeof SelectPrimitive.Separator>;
}
export function Separator({ ...props }: Separator.Props) {
return <SelectPrimitive.Separator data-slot="select-separator" {...props} />;
}
Update the import paths to match your project setup.
Usage
import * as Select from "@/components/caprice-ui/select"import * as Select from "@caprice-ui/react/select"Examples
Last updated on