Select
Select
Customizable dropdown select component with single selection mode
Select
A customizable select dropdown component with support for single and multiple selections, keyboard navigation, search filtering, and custom positioning. Built with floating-ui for intelligent dropdown placement.
Installation
import { Select, SelectOption } from "@geckoui/geckoui";Basic Usage
Select Item
"use client";
import { Select, SelectOption } from "@geckoui/geckoui";
import { useState } from "react";
function Example() {
const [value, setValue] = useState<string | null>(null);
return (
<Select value={value} onChange={setValue}>
<SelectOption value="react" label="React" />
<SelectOption value="vue" label="Vue" />
<SelectOption value="angular" label="Angular" />
</Select>
);
}Important: Use null or undefined for no selection. An empty string "" is considered a valid value and will try to match against options.
Props API
| Prop | Type | Default | Description |
|---|---|---|---|
value | T | null | - | Selected value (required) |
onChange | (value: T | null) => void | - | Callback when selection changes (required) |
placeholder | string | - | Placeholder text when empty |
disabled | boolean | false | Disable the select |
closeMenuOnSelect | boolean | true | Close menu after selection |
placement | Placement | 'bottom-start' | Menu placement position |
floatingStrategy | Strategy | - | Floating positioning strategy |
wrapperClassName | string | - | CSS class for wrapper |
menuClassName | string | - | CSS class for menu |
placeholderClassName | string | - | CSS class for placeholder |
className | string | - | CSS class for select button |
filterable | boolean | 'inline' | 'dropdown' | false | Enable search filtering |
multiple | boolean | false | Enable multiple selection |
hideDefaultEmptyUI | boolean | false | Hide default empty state |
inputRef | RefObject | - | Ref for filter input |
prefix | ReactNode | - | Content before select button |
suffix | ReactNode | - | Content after select button |
Examples
With Placeholder
Choose a framework...
const [value, setValue] = useState<string | null>(null);
<Select value={value} onChange={setValue} placeholder="Choose a framework...">
<SelectOption value="next" label="Next.js" />
<SelectOption value="remix" label="Remix" />
<SelectOption value="gatsby" label="Gatsby" />
</Select>;Disabled Options
Select Item
const [value, setValue] = useState<string | null>(null);
<Select value={value} onChange={setValue}>
<SelectOption value="available" label="Available Option" />
<SelectOption value="disabled" label="Disabled Option" disabled />
<SelectOption value="another" label="Another Available" />
</Select>;Disabled Select
Selected Option
<Select value="selected" onChange={() => {}} disabled>
<SelectOption value="selected" label="Selected Option" />
<SelectOption value="other" label="Other Option" />
</Select>Placement Options
Select Item
Select Item
const [value, setValue] = useState<string | null>(null);
// Opens upward
<Select value={value} onChange={setValue} placement="top-start">
<SelectOption value="a" label="Choice A" />
<SelectOption value="b" label="Choice B" />
</Select>
// Aligns to right
<Select value={value} onChange={setValue} placement="bottom-end">
<SelectOption value="a" label="Choice A" />
<SelectOption value="b" label="Choice B" />
</Select>Grouped Options with Static Elements
You can add any HTML elements inside Select to create headers, dividers, and footers. These static elements won't interfere with filtering or selection.
Basic Grouping
Select a framework...
const [value, setValue] = useState<string | null>(null);
<Select value={value} onChange={setValue}>
<div className="px-3 py-2 text-xs font-semibold text-gray-500 uppercase">Frontend</div>
<SelectOption value="react" label="React" />
<SelectOption value="vue" label="Vue" />
<SelectOption value="angular" label="Angular" />
<hr className="my-1 border-gray-200" />
<div className="px-3 py-2 text-xs font-semibold text-gray-500 uppercase">Backend</div>
<SelectOption value="node" label="Node.js" />
<SelectOption value="django" label="Django" />
<SelectOption value="rails" label="Rails" />
</Select>;Grouped with Filterable
Static elements remain visible during filtering:
Search frameworks...
<Select filterable="inline" value={value} onChange={setValue}>
<div className="px-3 py-2 text-xs font-semibold text-gray-500 uppercase bg-gray-50 dark:bg-neutral-800">
Frontend Frameworks
</div>
<SelectOption value="react" label="React" />
<SelectOption value="vue" label="Vue" />
<hr className="my-1 border-gray-200" />
<div className="px-3 py-2 text-xs font-semibold text-gray-500 uppercase bg-gray-50 dark:bg-neutral-800">
Backend Frameworks
</div>
<SelectOption value="express" label="Express" />
<SelectOption value="nest" label="NestJS" />
</Select>With Header and Footer
Select a color...
<Select value={value} onChange={setValue}>
<div className="px-3 py-2 border-b bg-gray-50 dark:bg-neutral-800">
<p className="text-sm font-medium">Choose your favorite color</p>
<p className="text-xs text-gray-500">This will be used as your theme</p>
</div>
<SelectOption value="blue" label="Blue" />
<SelectOption value="green" label="Green" />
<SelectOption value="purple" label="Purple" />
<div className="px-3 py-2 border-t bg-gray-50 dark:bg-neutral-800">
<a href="#" className="text-xs text-blue-600 hover:underline">
Customize colors →
</a>
</div>
</Select>Complex Grouping
Select a programming language...
<Select value={value} onChange={setValue}>
<div className="px-3 py-2 bg-blue-50">
<p className="text-xs font-semibold text-blue-700">âš¡ Popular</p>
</div>
<SelectOption value="javascript" label="JavaScript" />
<SelectOption value="python" label="Python" />
<div className="px-3 py-2 bg-green-50 mt-1">
<p className="text-xs font-semibold text-green-700">🚀 Trending</p>
</div>
<SelectOption value="rust" label="Rust" />
<SelectOption value="go" label="Go" />
<hr className="my-1 border-gray-200" />
<div className="px-3 py-2">
<p className="text-xs font-semibold text-gray-500">Others</p>
</div>
<SelectOption value="java" label="Java" />
<SelectOption value="csharp" label="C#" />
</Select>Static Notes
Select a plan...
<Select value={value} onChange={setValue}>
<SelectOption value="free" label="Free Plan" />
<SelectOption value="pro" label="Pro Plan - $29/mo" />
<SelectOption value="enterprise" label="Enterprise Plan - $99/mo" />
<div className="px-3 py-2 mt-2 bg-yellow-50 border border-yellow-200 rounded mx-2 mb-2">
<p className="text-xs text-yellow-800">
💡 <strong>Tip:</strong> Annual billing saves 20%
</p>
</div>
</Select>Key Points:
- Static HTML elements (divs, hr, etc.) won't interfere with option selection
- They remain visible during filtering
- Useful for headers, dividers, footers, and informational content
- Style them with any CSS classes
Keyboard Navigation
- Arrow Up/Down: Navigate options
- Enter/Space: Select focused option
- Escape: Close menu
- Tab: Close menu and move to next element
- Type to search: Filter options (when filterable enabled)
Accessibility
- Built with floating-ui for intelligent positioning
- Fully keyboard navigable
- Click-outside to close
- Focus management
- Works with screen readers
- ARIA attributes automatically applied
Styling
The component uses BEM-style class names:
GeckoUISelect- Main containerGeckoUISelectButton- Select buttonGeckoUISelectMenu- Menu containerGeckoUISelectOption- Individual optionGeckoUISelectOption--selected- Applied to selected optionsGeckoUISelectOption--focused- Applied to focused option
Related Pages
- Multiple Selection - Multi-select mode with chips
- Filterable - Search and filtering
- SelectOption - Advanced option patterns
- SelectTrigger - Custom triggers
- SelectEmpty - Empty states
- Advanced - Programmatic control