Select
A native select component with consistent styling across browsers.
Source Code
"use client";
import { VariantProps } from "cva";
import { cn } from "@/lib/utils";
import {
InputGroup,
InputPrefix,
inputStyle,
} from "@/components/input";
interface SelectProps extends React.ComponentPropsWithRef<"select"> {
invalid?: boolean;
variant?: VariantProps<typeof inputStyle>["variant"];
}
const Select = ({ className, invalid, variant, ...props }: SelectProps) => {
return (
<select
data-invalid={invalid}
className={cn(
inputStyle({ variant }),
"appearance-none bg-[length:1em] bg-[position:right_--spacing(2)_center] bg-no-repeat pr-10",
'bg-[url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgdmlld0JveD0iMCAwIDE2IDE2Ij48cGF0aCBmaWxsPSJibGFjayIgZD0iTTMuNyA1LjNsNC4zIDQuMyA0LjMtNC4zLjcuNy01IDUtNS01eiIvPjwvc3ZnPg==")]',
'dark:bg-[url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgdmlld0JveD0iMCAwIDE2IDE2Ij48cGF0aCBmaWxsPSJ3aGl0ZSIgZD0iTTMuNyA1LjNsNC4zIDQuMyA0LjMtNC4zLjcuNy01IDUtNS01eiIvPjwvc3ZnPg==")]',
className
)}
{...props}
/>
);
};
const SelectGroup = InputGroup;
const SelectPrefix = InputPrefix;
export { Select, SelectGroup, SelectPrefix };
Features
- Native Element: Uses the browser's native select element for optimal mobile support
- Consistent Styling: Normalized appearance across different browsers
- Form Integration: Works seamlessly with form libraries and native form validation
- Prefix Support: Optional prefix for additional context
- Variants: Supports default and minimal visual styles
- Validation: Built-in invalid state styling
Anatomy
<SelectGroup>
<SelectPrefix />
<Select>
<option>
</Select>
</SelectGroup>
API Reference
Select
Extends the select
element.
Prop | Default | Type | Description |
---|---|---|---|
|
|
| The visual style variant to use. |
|
|
| Whether the select is in an invalid state. |
SelectGroup
Extends the div
element.
A wrapper component that provides proper spacing and layout for the select and its prefix.
SelectPrefix
Extends the div
element.
Prop | Default | Type | Description |
---|---|---|---|
|
|
| When true, the prefix can be clicked and will receive focus. |
Accessibility
The Select component uses the native <select>
element, which provides excellent accessibility out of the box:
- Full keyboard navigation support
- Screen reader announcements
- Mobile-friendly interaction
- Native form integration
Examples
Simple
Basic usage with a list of options.
Minimal
Using the minimal variant without borders.
Disabled
The select in a disabled state.
Invalid
The select showing an invalid state.
Prefix
Using a prefix to provide additional context.
Best Practices
-
Use Listbox for Complex Cases:
- If you need custom option rendering
- If you need search functionality
- If you need multiple selection
- If you need complex keyboard interactions
-
Mobile Considerations:
- The native select provides the best experience on mobile devices
- It automatically adapts to the platform's native picker
-
Form Integration:
- Use the
required
attribute for required fields - Use the
name
attribute for form submission - Use the
invalid
prop in conjunction with form validation
- Use the
-
Accessibility:
- Always provide a visible label or aria-label
- Group related selects with fieldset and legend
- Use aria-describedby for additional descriptions