Components

Base Components

Native Select

A styled native HTML select element with option and optgroup support.

Example

Installation

Create a native-select.tsx file and paste the following code into it.

import * as React from "react"import { ChevronDownIcon, ChevronsUpDown } from "lucide-react"import { cn } from "@/lib/utils"const NativeSelect = React.forwardRef<  HTMLSelectElement,  Omit<React.ComponentProps<"select">, "size"> & { size?: "sm" | "default" }>(({ className, size = "default", ...props }, ref) => {  return (    <div      className="group/native-select relative w-full h-fit has-[select:disabled]:opacity-50"      data-slot="native-select-wrapper"    >      <select        ref={ref}        data-slot="native-select"        data-size={size}        className={cn(          "border-input placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 dark:hover:bg-input/50 h-9 w-full min-w-0 appearance-none rounded-md border bg-transparent px-3 py-2 pr-9 text-sm shadow-xs transition-[color,box-shadow] outline-none disabled:pointer-events-none disabled:cursor-not-allowed data-[size=sm]:h-8 data-[size=sm]:py-1",          "focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",          "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",          className        )}        {...props}      />      <ChevronsUpDown        className="text-muted-foreground pointer-events-none absolute top-1/2 right-3.5 size-4 -translate-y-1/2 opacity-50 select-none"        aria-hidden="true"        data-slot="native-select-icon"      />    </div>  )})NativeSelect.displayName = "NativeSelect"function NativeSelectOption({ ...props }: React.ComponentProps<"option">) {  return <option data-slot="native-select-option" {...props} />}function NativeSelectOptGroup({  className,  ...props}: React.ComponentProps<"optgroup">) {  return (    <optgroup      data-slot="native-select-optgroup"      className={cn(className)}      {...props}    />  )}export { NativeSelect, NativeSelectOptGroup, NativeSelectOption }

Check the import paths to ensure they match your project setup.

Usage

import {
  NativeSelect,
  NativeSelectOption,
  NativeSelectOptGroup,
} from "@/components/ui/native-select";
<NativeSelect value={value} onChange={(e) => setValue(e.target.value)}>
  <NativeSelectOption value="">Choose...</NativeSelectOption>
  <NativeSelectOption value="a">Option A</NativeSelectOption>
  <NativeSelectOption value="b">Option B</NativeSelectOption>
</NativeSelect>
NativeSelect forwards all native <select> props. Use NativeSelectOption for <option> and NativeSelectOptGroup for <optgroup>. The component supports a size prop for "default" or "sm".

Examples

Default

With label

With optgroup

Use NativeSelectOptGroup to group options under a label.

Sizes

Use the size prop to switch between default and small.

Disabled

API Reference

NativeSelect

A styled native <select> with consistent focus and invalid styles. Accepts all native select props plus size ("default" | "sm").
disabledboolean
Default: -
size"default" | "sm"
Default: default
PropTypeDefaultDescription
disabledboolean--
size"default" | "sm"default-

NativeSelectOption

Renders a native <option>. Use value and optional disabled.
No prop metadata found for component "NativeSelectOption".

NativeSelectOptGroup

Renders a native <optgroup> to group options. Use the label prop for the group heading.
No prop metadata found for component "NativeSelectOptGroup".

On this page