Component
Select

Select

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

Installation

Install the following dependencies

npm i @radix-ui/react-select

Copy and paste the following code into your project

components/ui/select/index.tsx
'use client'
 
import * as React from 'react'
import * as SelectPrimitive from '@radix-ui/react-select'
import { Check, ChevronDown } from 'lucide-react'
import { createStyleContext } from '@shadow-panda/style-context'
import { styled } from '@shadow-panda/styled-system/jsx'
import { select, icon } from '@shadow-panda/styled-system/recipes'
 
const { withProvider, withContext } = createStyleContext(select)
 
const Trigger = React.forwardRef<
  React.ElementRef<typeof SelectPrimitive.Trigger>,
  React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>
>(({ children, ...props }, ref) => (
  <SelectPrimitive.Trigger ref={ref} {...props}>
    {children}
    <SelectPrimitive.Icon asChild>
      <ChevronDown className={icon({ dimmed: true })} />
    </SelectPrimitive.Icon>
  </SelectPrimitive.Trigger>
))
Trigger.displayName = SelectPrimitive.Trigger.displayName
 
const Viewport = withContext(SelectPrimitive.Viewport, 'viewport')
 
const Content = React.forwardRef<
  React.ElementRef<typeof SelectPrimitive.Content>,
  React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>
>(({ children, position = 'popper', ...props }, ref) => (
  <SelectPrimitive.Portal>
    <SelectPrimitive.Content ref={ref} position={position} data-position={position} {...props}>
      <Viewport data-position={position}>{children}</Viewport>
    </SelectPrimitive.Content>
  </SelectPrimitive.Portal>
))
Content.displayName = SelectPrimitive.Content.displayName
 
const ItemIndicator = withContext(styled(SelectPrimitive.ItemIndicator), 'itemIndicator')
 
const Item = React.forwardRef<
  React.ElementRef<typeof SelectPrimitive.Item>,
  React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>
>(({ children, ...props }, ref) => (
  <SelectPrimitive.Item ref={ref} {...props}>
    <ItemIndicator>
      <Check className={icon()} />
    </ItemIndicator>
 
    <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
  </SelectPrimitive.Item>
))
Item.displayName = SelectPrimitive.Item.displayName
 
export const Select = withProvider(styled(SelectPrimitive.Root), 'root')
export const SelectGroup = withContext(styled(SelectPrimitive.Group), 'group')
export const SelectValue = withContext(styled(SelectPrimitive.Value), 'value')
export const SelectTrigger = withContext(styled(Trigger), 'trigger')
export const SelectContent = withContext(styled(Content), 'content')
export const SelectLabel = withContext(styled(SelectPrimitive.Label), 'label')
export const SelectItem = withContext(styled(Item), 'item')
export const SelectSeparator = withContext(styled(SelectPrimitive.Separator), 'separator')

Update the import paths to match your project setup

Usage

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

Examples

Form

You can manage email addresses in your email settings.