Select

Displays a list of options for the user to pick from—triggered by a button.

Installation

Install the following dependencies:

npm install @radix-ui/react-select

Copy and paste the following code into your project.

'use client';
 
import * as SelectPrimitive from '@radix-ui/react-select';
import clsx from 'clsx';
import { Check, ChevronDown, ChevronUp } from 'lucide-react';
import { ComponentPropsWithoutRef, ElementRef, forwardRef } from 'react';
import styles from './styles.module.scss';
 
const Select = SelectPrimitive.Root;
 
const SelectGroup = SelectPrimitive.Group;
 
const SelectValue = SelectPrimitive.Value;
 
const SelectTrigger = forwardRef<
    ElementRef<typeof SelectPrimitive.Trigger>,
    ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>
>(({ className, children, ...props }, ref) => (
    <SelectPrimitive.Trigger ref={ref} className={clsx(styles.select__trigger, className)} {...props}>
        {children}
        <SelectPrimitive.Icon asChild>
            <ChevronDown className={styles.chevron__down} />
        </SelectPrimitive.Icon>
    </SelectPrimitive.Trigger>
));
SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
 
const SelectScrollUpButton = forwardRef<
    ElementRef<typeof SelectPrimitive.ScrollUpButton>,
    ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>
>(({ className, ...props }, ref) => (
    <SelectPrimitive.ScrollUpButton ref={ref} className={clsx(styles.select__scroll__up, className)} {...props}>
        <ChevronUp className={styles.visible__icon} />
    </SelectPrimitive.ScrollUpButton>
));
SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
 
const SelectScrollDownButton = forwardRef<
    ElementRef<typeof SelectPrimitive.ScrollDownButton>,
    ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>
>(({ className, ...props }, ref) => (
    <SelectPrimitive.ScrollDownButton ref={ref} className={clsx(styles.select__scroll__down, className)} {...props}>
        <ChevronDown className={styles.visible__icon} />
    </SelectPrimitive.ScrollDownButton>
));
SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName;
 
const SelectContent = forwardRef<
    ElementRef<typeof SelectPrimitive.Content>,
    ComponentPropsWithoutRef<typeof SelectPrimitive.Content>
>(({ className, children, position = 'popper', ...props }, ref) => (
    <SelectPrimitive.Portal>
        <SelectPrimitive.Content
            ref={ref}
            className={clsx(styles.select__content, position === 'popper' && styles.select__content__popper, className)}
            position={position}
            {...props}
        >
            <SelectScrollUpButton />
            <SelectPrimitive.Viewport
                className={clsx(
                    styles.select__content__viewport,
                    position === 'popper' && styles.select__content__viewport__popper
                )}
            >
                {children}
            </SelectPrimitive.Viewport>
            <SelectScrollDownButton />
        </SelectPrimitive.Content>
    </SelectPrimitive.Portal>
));
SelectContent.displayName = SelectPrimitive.Content.displayName;
 
const SelectLabel = forwardRef<
    ElementRef<typeof SelectPrimitive.Label>,
    ComponentPropsWithoutRef<typeof SelectPrimitive.Label>
>(({ className, ...props }, ref) => (
    <SelectPrimitive.Label ref={ref} className={clsx(styles.select__label, className)} {...props} />
));
SelectLabel.displayName = SelectPrimitive.Label.displayName;
 
const SelectItem = forwardRef<
    ElementRef<typeof SelectPrimitive.Item>,
    ComponentPropsWithoutRef<typeof SelectPrimitive.Item>
>(({ className, children, ...props }, ref) => (
    <SelectPrimitive.Item ref={ref} className={clsx(styles.select__item, className)} {...props}>
        <span className={styles.item__wrapper}>
            <SelectPrimitive.ItemIndicator>
                <Check className={styles.visible__icon} />
            </SelectPrimitive.ItemIndicator>
        </span>
 
        <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
    </SelectPrimitive.Item>
));
SelectItem.displayName = SelectPrimitive.Item.displayName;
 
const SelectSeparator = forwardRef<
    ElementRef<typeof SelectPrimitive.Separator>,
    ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>
>(({ className, ...props }, ref) => (
    <SelectPrimitive.Separator ref={ref} className={clsx(styles.select__separator, className)} {...props} />
));
SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
 
export {
    Select,
    SelectContent,
    SelectGroup,
    SelectItem,
    SelectLabel,
    SelectScrollDownButton,
    SelectScrollUpButton,
    SelectSeparator,
    SelectTrigger,
    SelectValue,
};

Update the import paths to match your project setup.

Usage

import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
<Select>
    <SelectTrigger>
        <SelectValue placeholder='Theme' />
    </SelectTrigger>
    <SelectContent>
        <SelectItem value='light'>Light</SelectItem>
        <SelectItem value='dark'>Dark</SelectItem>
        <SelectItem value='system'>System</SelectItem>
    </SelectContent>
</Select>

Examples

Scrollable

Form

You can manage email addresses in your email settings.