Select

A standalone select dropdown with chevron icon, invalid state, and dark mode — built with Tailwind CSS.

Preview

Basic select

import { Select } from '@/registry/ui-kit/tailwind-select/react'

function Example() {
  return (
    <Select>
      <option value="">Choose a framework</option>
      <option value="react">React</option>
      <option value="vue">Vue</option>
      <option value="svelte">Svelte</option>
    </Select>
  )
}

Invalid state

import { Select } from '@/registry/ui-kit/tailwind-select/react'

function Example() {
  return (
    <Select invalid defaultValue="">
      <option value="">Select a country</option>
      <option value="us">United States</option>
    </Select>
  )
}

Component API

PropDefaultDescription
invalidfalseShow the select in an invalid/error state with red border.
className""Additional CSS classes to apply.
childrenNative option elements.

Source Code

"use client";

import { forwardRef } from "react";

interface SelectProps extends React.SelectHTMLAttributes<HTMLSelectElement> {
  invalid?: boolean;
  className?: string;
  children: React.ReactNode;
}

const Select = forwardRef<HTMLSelectElement, SelectProps>(
  ({ invalid = false, className = "", children, ...props }, ref) => {
    return (
      <div className="relative">
        <select
          ref={ref}
          aria-invalid={invalid || undefined}
          className={[
            "block w-full appearance-none rounded-lg border bg-white py-2 pl-3.5 pr-10 text-sm text-zinc-900 shadow-sm outline-none transition-colors dark:border-zinc-700 dark:bg-zinc-900 dark:text-zinc-100 disabled:cursor-not-allowed disabled:opacity-50",
            invalid
              ? "border-red-500 focus:border-red-500 focus:ring-2 focus:ring-red-500/20"
              : "border-zinc-300 focus:border-indigo-500 focus:ring-2 focus:ring-indigo-500/20 dark:focus:border-indigo-400 dark:focus:ring-indigo-400/20",
            className,
          ].join(" ")}
          {...props}
        >
          {children}
        </select>
        <svg
          className="pointer-events-none absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 text-zinc-400"
          xmlns="http://www.w3.org/2000/svg"
          viewBox="0 0 24 24"
          fill="none"
          stroke="currentColor"
          strokeWidth="2"
          strokeLinecap="round"
          strokeLinejoin="round"
        >
          <path d="m6 9 6 6 6-6" />
        </svg>
      </div>
    );
  }
);
Select.displayName = "Select";

export { Select };
export default Select;