Inputs

Select

List of user-selectable options, triggered by a button.

Installation

  1. 1

    Install dependencies:

    npm install @radix-ui/react-select
  2. 2

    Add component:

    Copy and paste the code into your project’s component directory. Do not forget to update the import paths.
    // Tremor Select [v0.0.3]
    import React from "react"import * as SelectPrimitives from "@radix-ui/react-select"import {  RiArrowDownSLine,  RiArrowUpSLine,  RiCheckLine,  RiExpandUpDownLine,} from "@remixicon/react"
    import { cx, focusInput, hasErrorInput } from "@/lib/utils"
    const Select = SelectPrimitives.RootSelect.displayName = "Select"
    const SelectGroup = SelectPrimitives.GroupSelectGroup.displayName = "SelectGroup"
    const SelectValue = SelectPrimitives.ValueSelectValue.displayName = "SelectValue"
    const selectTriggerStyles = [  cx(    // base    "group/trigger flex w-full select-none items-center justify-between gap-2 truncate rounded-md border px-3 py-2 shadow-sm outline-none transition sm:text-sm",    // border color    "border-gray-300 dark:border-gray-800",    // text color    "text-gray-900 dark:text-gray-50",    // placeholder    "data-[placeholder]:text-gray-500 data-[placeholder]:dark:text-gray-500",    // background color    "bg-white dark:bg-gray-950",    // hover    "hover:bg-gray-50 hover:dark:bg-gray-950/50",    // disabled    "data-[disabled]:bg-gray-100 data-[disabled]:text-gray-400",    "data-[disabled]:dark:border-gray-700 data-[disabled]:dark:bg-gray-800 data-[disabled]:dark:text-gray-500",    focusInput,    // invalid (optional)    // "aria-[invalid=true]:dark:ring-red-400/20 aria-[invalid=true]:ring-2 aria-[invalid=true]:ring-red-200 aria-[invalid=true]:border-red-500 invalid:ring-2 invalid:ring-red-200 invalid:border-red-500"  ),]
    const SelectTrigger = React.forwardRef<  React.ElementRef<typeof SelectPrimitives.Trigger>,  React.ComponentPropsWithoutRef<typeof SelectPrimitives.Trigger> & {    hasError?: boolean  }>(({ className, hasError, children, ...props }, forwardedRef) => {  return (    <SelectPrimitives.Trigger      ref={forwardedRef}      className={cx(        selectTriggerStyles,        hasError ? hasErrorInput : "",        className,      )}      tremor-id="tremor-raw"      {...props}    >      <span className="truncate">{children}</span>      <SelectPrimitives.Icon asChild>        <RiExpandUpDownLine          className={cx(            // base            "size-4 shrink-0",            // text color            "text-gray-400 dark:text-gray-600",            // disabled            "group-data-[disabled]/trigger:text-gray-300 group-data-[disabled]/trigger:dark:text-gray-600",          )}        />      </SelectPrimitives.Icon>    </SelectPrimitives.Trigger>  )})
    SelectTrigger.displayName = "SelectTrigger"
    const SelectScrollUpButton = React.forwardRef<  React.ElementRef<typeof SelectPrimitives.ScrollUpButton>,  React.ComponentPropsWithoutRef<typeof SelectPrimitives.ScrollUpButton>>(({ className, ...props }, forwardedRef) => (  <SelectPrimitives.ScrollUpButton    ref={forwardedRef}    className={cx(      "flex cursor-default items-center justify-center py-1",      className,    )}    {...props}  >    <RiArrowUpSLine className="size-3 shrink-0" aria-hidden="true" />  </SelectPrimitives.ScrollUpButton>))SelectScrollUpButton.displayName = SelectPrimitives.ScrollUpButton.displayName
    const SelectScrollDownButton = React.forwardRef<  React.ElementRef<typeof SelectPrimitives.ScrollDownButton>,  React.ComponentPropsWithoutRef<typeof SelectPrimitives.ScrollDownButton>>(({ className, ...props }, forwardedRef) => (  <SelectPrimitives.ScrollDownButton    ref={forwardedRef}    className={cx(      "flex cursor-default items-center justify-center py-1",      className,    )}    {...props}  >    <RiArrowDownSLine className="size-3 shrink-0" aria-hidden="true" />  </SelectPrimitives.ScrollDownButton>))SelectScrollDownButton.displayName =  SelectPrimitives.ScrollDownButton.displayName
    const SelectContent = React.forwardRef<  React.ElementRef<typeof SelectPrimitives.Content>,  React.ComponentPropsWithoutRef<typeof SelectPrimitives.Content>>(  (    {      className,      position = "popper",      children,      sideOffset = 8,      collisionPadding = 10,      ...props    },    forwardedRef,  ) => (    <SelectPrimitives.Portal>      <SelectPrimitives.Content        ref={forwardedRef}        className={cx(          // base          "relative z-50 overflow-hidden rounded-md border shadow-xl shadow-black/[2.5%]",          // widths          "min-w-[calc(var(--radix-select-trigger-width)-2px)] max-w-[95vw]",          // heights          "max-h-[--radix-select-content-available-height]",          // background color          "bg-white dark:bg-gray-950",          // text color          "text-gray-900 dark:text-gray-50",          // border color          "border-gray-200 dark:border-gray-800",          // transition          "will-change-[transform,opacity]",          // "data-[state=open]:animate-slideDownAndFade",          "data-[state=closed]:animate-hide",          "data-[side=bottom]:animate-slideDownAndFade data-[side=left]:animate-slideLeftAndFade data-[side=right]:animate-slideRightAndFade data-[side=top]:animate-slideUpAndFade",          className,        )}        sideOffset={sideOffset}        position={position}        collisionPadding={collisionPadding}        {...props}      >        <SelectScrollUpButton />        <SelectPrimitives.Viewport          className={cx(            "p-1",            position === "popper" &&              "h-[var(--radix-select-trigger-height)] w-full min-w-[calc(var(--radix-select-trigger-width))]",          )}        >          {children}        </SelectPrimitives.Viewport>        <SelectScrollDownButton />      </SelectPrimitives.Content>    </SelectPrimitives.Portal>  ),)
    SelectContent.displayName = "SelectContent"
    const SelectGroupLabel = React.forwardRef<  React.ElementRef<typeof SelectPrimitives.Label>,  React.ComponentPropsWithoutRef<typeof SelectPrimitives.Label>>(({ className, ...props }, forwardedRef) => (  <SelectPrimitives.Label    ref={forwardedRef}    className={cx(      // base      "px-3 py-2 text-xs font-medium tracking-wide",      // text color      "text-gray-500 dark:text-gray-500",      className,    )}    {...props}  />))
    SelectGroupLabel.displayName = "SelectGroupLabel"
    const SelectItem = React.forwardRef<  React.ElementRef<typeof SelectPrimitives.Item>,  React.ComponentPropsWithoutRef<typeof SelectPrimitives.Item>>(({ className, children, ...props }, forwardedRef) => {  return (    <SelectPrimitives.Item      ref={forwardedRef}      className={cx(        // base        "grid cursor-pointer grid-cols-[1fr_20px] gap-x-2 rounded px-3 py-2 outline-none transition-colors data-[state=checked]:font-semibold sm:text-sm",        // text color        "text-gray-900 dark:text-gray-50",        // disabled        "data-[disabled]:pointer-events-none data-[disabled]:text-gray-400 data-[disabled]:hover:bg-none dark:data-[disabled]:text-gray-600",        // focus        "focus-visible:bg-gray-100 focus-visible:dark:bg-gray-900",        // hover        "hover:bg-gray-100 hover:dark:bg-gray-900",        className,      )}      {...props}    >      <SelectPrimitives.ItemText className="flex-1 truncate">        {children}      </SelectPrimitives.ItemText>      <SelectPrimitives.ItemIndicator>        <RiCheckLine          className="size-5 shrink-0 text-gray-800 dark:text-gray-200"          aria-hidden="true"        />      </SelectPrimitives.ItemIndicator>    </SelectPrimitives.Item>  )})
    SelectItem.displayName = "SelectItem"
    const SelectSeparator = React.forwardRef<  React.ElementRef<typeof SelectPrimitives.Separator>,  React.ComponentPropsWithoutRef<typeof SelectPrimitives.Separator>>(({ className, ...props }, forwardedRef) => (  <SelectPrimitives.Separator    ref={forwardedRef}    className={cx(      // base      "-mx-1 my-1 h-px",      // background color      "bg-gray-300 dark:bg-gray-700",      className,    )}    {...props}  />))
    SelectSeparator.displayName = "SelectSeparator"
    export {  Select,  SelectContent,  SelectGroup,  SelectGroupLabel,  SelectItem,  SelectSeparator,  SelectTrigger,  SelectValue,}
    
  3. 3

    Update tailwind.config.ts

    import type { Config } from 'tailwindcss';export default {  // ...  theme: {    extend: {      keyframes: {        hide: {          from: { opacity: "1" },          to: { opacity: "0" },        },        slideDownAndFade: {          from: { opacity: "0", transform: "translateY(-6px)" },          to: { opacity: "1", transform: "translateY(0)" },        },        slideLeftAndFade: {          from: { opacity: "0", transform: "translateX(6px)" },          to: { opacity: "1", transform: "translateX(0)" },        },        slideUpAndFade: {          from: { opacity: "0", transform: "translateY(6px)" },          to: { opacity: "1", transform: "translateY(0)" },        },        slideRightAndFade: {          from: { opacity: "0", transform: "translateX(-6px)" },          to: { opacity: "1", transform: "translateX(0)" },        },      },      animation: {        hide: "hide 150ms cubic-bezier(0.16, 1, 0.3, 1)",        slideDownAndFade:          "slideDownAndFade 150ms cubic-bezier(0.16, 1, 0.3, 1)",        slideLeftAndFade:          "slideLeftAndFade 150ms cubic-bezier(0.16, 1, 0.3, 1)",        slideUpAndFade: "slideUpAndFade 150ms cubic-bezier(0.16, 1, 0.3, 1)",        slideRightAndFade:          "slideRightAndFade 150ms cubic-bezier(0.16, 1, 0.3, 1)",      },    },  },  // ...} satisfies Config;

Example: Select with label

Example: Select with defaultValue

Example: Select with disabled state

Example: Select with disabled select item

Example: Select with groups

Example: Select with scroll and custom height

Example: Select with Dialog

Example: Select with error state

To style the Select for an error state, use the hasError prop.

Example: Select with icons

Example: Controlled select

Selected key:

API Reference: Select

This component uses the Radix UI API.

API Reference: SelectTrigger

This component uses the Radix UI API.

hasError
boolean
Style for erroneous input.

Default: false

API Reference: SelectValue

This component uses the Radix UI API.

API Reference: SelectContent

This component uses the Radix UI API.

API Reference: SelectItem

This component uses the Radix UI API.

API Reference: SelectGroupLabel

This component uses the Radix UI API.

API Reference: SelectLabel

This component uses the Radix UI API.

API Reference: SelectSeparator

This component uses the Radix UI API.