SelectKit
A composable select component built on Radix UI primitives and Shadcn/UI components. Supports both static and dynamic data with built-in search, loading states, and accessibility.
Installation
npx shadcn@latest add https://selectkit.arc1.io/r/selectkit.jsonAnatomy
import {
  SelectKit,
  SelectKitTrigger,
  SelectKitValue,
  SelectKitContent,
  SelectKitSearch,
  SelectKitList,
  SelectKitItem,
  SelectKitGroup,
  SelectKitSeparator,
  SelectKitClear,
  SelectKitLoading,
  SelectKitError,
  SelectKitEmpty,
  SelectKitLoadMore,
} from "@/components/ui/selectkit";
export default () => (
  <SelectKit>
    <SelectKitTrigger>
      <SelectKitValue />
      <SelectKitClear />
    </SelectKitTrigger>
    <SelectKitContent>
      <SelectKitSearch />
      <SelectKitList>
        <SelectKitGroup>
          <SelectKitItem />
        </SelectKitGroup>
        <SelectKitSeparator />
        <SelectKitLoading />
        <SelectKitError />
        <SelectKitEmpty />
        <SelectKitLoadMore />
      </SelectKitList>
    </SelectKitContent>
  </SelectKit>
);
API Reference
SelectKit
Contains all the parts of a select. This component manages the open state and selected value.
Props
| Prop | Type | Default | 
|---|---|---|
value | string | undefined | 
onValueChange | (value: string) => void | undefined | 
defaultValue | string | "" | 
open | boolean | undefined | 
onOpenChange | (open: boolean) => void | undefined | 
children | ReactNode | — | 
Data attribute: [data-state] - "open" | "closed"
SelectKitTrigger
The button that toggles the select. Extends all PopoverTrigger props.
Props
| Prop | Type | Default | 
|---|---|---|
asChild | boolean | false | 
disabled | boolean | false | 
Data attribute: [data-state] - "open" | "closed"
SelectKitValue
The part that reflects the selected value. Automatically displays content from the selected item.
Props
| Prop | Type | Default | 
|---|---|---|
placeholder | string | "Select an option..." | 
children | ReactNode | undefined | 
SelectKitContent
The component that pops out when the select is open. Extends all PopoverContent props.
Props
| Prop | Type | Default | 
|---|---|---|
asChild | boolean | false | 
Data attribute: [data-state] - "open" | "closed"
SelectKitSearch
An input field for filtering options.
Props
| Prop | Type | Default | 
|---|---|---|
placeholder | string | "Search..." | 
searchQuery | string | undefined | 
onSearchChange | (query: string) => void | undefined | 
debounceDelay | number | 300 | 
useDefaultFilter | boolean | true | 
SelectKitList
Contains the selectable items.
Props
| Prop | Type | Default | 
|---|---|---|
children | ReactNode | — | 
SelectKitItem
The component that contains the select items.
Props
| Prop | Type | Default | 
|---|---|---|
value | string | — | 
disabled | boolean | false | 
onSelect | (value: string) => void | undefined | 
children | ReactNode | — | 
Data attribute: [data-selected] - Present when selected
SelectKitGroup
Used to group multiple items. Use in conjunction with SelectKitGroup.heading to ensure good accessibility via automatic labelling.
Props
| Prop | Type | Default | 
|---|---|---|
heading | string | undefined | 
children | ReactNode | — | 
SelectKitSeparator
Used to visually separate items in the select.
SelectKitClear
A button to clear the current selection. Only renders when a value is selected.
Props
| Prop | Type | Default | 
|---|---|---|
children | ReactNode | undefined | 
SelectKitLoading
Renders a loading indicator.
Props
| Prop | Type | Default | 
|---|---|---|
children | ReactNode | Default loading UI | 
SelectKitError
Renders an error message with optional retry functionality.
Props
| Prop | Type | Default | 
|---|---|---|
onRetry | () => void | undefined | 
children | ReactNode | — | 
SelectKitEmpty
Renders when no items are available. Automatically detects search context.
Props
| Prop | Type | Default | 
|---|---|---|
searchQuery | string | undefined | 
children | ReactNode | Contextual message | 
SelectKitLoadMore
A button for loading additional items.
Props
| Prop | Type | Default | 
|---|---|---|
onLoadMore | () => void | undefined | 
disabled | boolean | false | 
asChild | boolean | false | 
children | ReactNode | "Load more..." | 
Keyboard Interactions
| Key | Description | 
|---|---|
| Space | When focus is on trigger, opens/closes the select | 
| Enter | When focus is on trigger, opens/closes the select | 
| ArrowDown | When focus is on trigger, opens select and moves focus to first item | 
| ArrowUp | When focus is on trigger, opens select and moves focus to last item | 
| ArrowDown | When focus is in content, moves focus to next item | 
| ArrowUp | When focus is in content, moves focus to previous item | 
| Enter | When focus is on item, selects item and closes | 
| Escape | Closes select and moves focus to trigger |