SelectOption
Advanced option patterns including custom content, click handlers, and visibility control
SelectOption
The SelectOption component represents an individual selectable item within a Select dropdown. It supports custom content rendering, click handlers with preventDefault, visibility control, and automatic keyboard/focus management.
Basic Usage
'use client';
import { useState } from 'react';
import { Select, SelectOption } from '@geckoui/geckoui';
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>
);
}Custom Content with Render Props
Use a render function to customize the option display based on its state:
const [value, setValue] = useState<string | null>(null);
<Select value={value} onChange={setValue}>
<SelectOption value="user1" label="John Doe">
{({ selected, focused }) => (
<div className="flex items-center gap-3">
<div className="w-10 h-10 rounded-full bg-blue-500 flex items-center justify-center text-white font-semibold">
JD
</div>
<div className={focused ? 'font-semibold' : ''}>
<div className="font-medium">John Doe</div>
<div className="text-sm text-gray-500">john@example.com</div>
</div>
{selected && <span className="ml-auto text-blue-500">✓</span>}
</div>
)}
</SelectOption>
{/* ... more options */}
</Select>Note: The label prop is still required for filtering and accessibility, even when using custom content.
Hide Check Icon
Remove the default check icon for selected items:
<Select value={value} onChange={setValue}>
<SelectOption value="opt1" label="Option 1" hideCheckIcon />
<SelectOption value="opt2" label="Option 2" hideCheckIcon />
<SelectOption value="opt3" label="Option 3" hideCheckIcon />
</Select>Disabled Options
<Select value={value} onChange={setValue}>
<SelectOption value="free" label="Free Plan" />
<SelectOption value="pro" label="Pro Plan" disabled />
<SelectOption value="enterprise" label="Enterprise Plan" disabled />
</Select>Custom Click Handler
Add custom logic that runs when an option is clicked. The default selection behavior still occurs:
const [clickCount, setClickCount] = useState(0);
<SelectOption
value="custom"
label="Custom Action"
onClick={({ selectCurrentOption, closeMenu }) => {
setClickCount((prev) => prev + 1);
console.log('Custom action triggered!');
selectCurrentOption(); // Still selects the option
closeMenu(); // Closes the menu
}}
/>onClick Parameters
The onClick handler receives an object with:
selectCurrentOption()- Function to manually trigger selectioncloseMenu()- Function to close the dropdownvalue- The option's valuepreventDefault()- Function to prevent default selection behavior
Using preventDefault
Completely override the default selection behavior:
<SelectOption
value="delete"
label="Delete Item"
onClick={({ preventDefault, selectCurrentOption, closeMenu }) => {
preventDefault(); // Prevents automatic selection
if (window.confirm('Are you sure?')) {
// Custom logic here
selectCurrentOption(); // Manually select only if confirmed
closeMenu();
}
// If canceled, nothing happens - option is NOT selected
}}
/>Common preventDefault Use Cases
// Conditional selection based on user permissions
<SelectOption
value="premium"
label="Premium Feature"
onClick={({ preventDefault, selectCurrentOption }) => {
preventDefault();
if (userHasPremium) {
selectCurrentOption();
} else {
openUpgradeModal();
}
}}
/>
// Trigger external action without selection
<SelectOption
value="export"
label="Export Data"
onClick={({ preventDefault, closeMenu }) => {
preventDefault();
handleExport();
closeMenu();
}}
/>
// Navigate instead of selecting
<SelectOption
value="settings"
label="Go to Settings"
onClick={({ preventDefault, closeMenu }) => {
preventDefault();
router.push('/settings');
closeMenu();
}}
/>Visibility Control
Control when options appear using the show prop:
<Select value={value} onChange={setValue}>
<SelectOption value="draft" label="Draft" visibility="default" />
<SelectOption value="published" label="Published" visibility="default" />
<SelectOption value="archived" label="Archived" visibility="default" />
{/* Always visible, even when filtering */}
<SelectOption value="admin-only" label="Admin Only Status" visibility="always" />
</Select>Visibility Modes
"default"- Normal visibility, hidden when filtered out"always"- Always visible, even during search/filter"empty"- Only visible when no other options match filter"filtered-and-empty"- Visible when filtered or empty
Complex Content Example
const frameworks = [
{
id: 'react',
name: 'React',
description: 'A JavaScript library for building user interfaces',
popularity: 'Very High',
color: 'bg-blue-500'
},
// ... more frameworks
];
<Select value={value} onChange={setValue}>
{frameworks.map((framework) => (
<SelectOption key={framework.id} value={framework.id} label={framework.name}>
{({ selected, focused }) => (
<div className="py-1">
<div className="flex items-center gap-2">
<div className={`w-3 h-3 rounded-full ${framework.color}`} />
<span className={focused ? 'font-semibold' : 'font-medium'}>
{framework.name}
</span>
<span className="ml-auto text-xs bg-gray-100 px-2 py-0.5 rounded">
{framework.popularity}
</span>
</div>
<p className="text-sm text-gray-500 mt-1 ml-5">
{framework.description}
</p>
</div>
)}
</SelectOption>
))}
</Select>Props API
| Prop | Type | Default | Description |
|---|---|---|---|
value | T | - | Option value (required) |
label | string | - | Display label and search text (required) |
children | ReactNode | (args) => ReactNode | - | Custom content or render function |
disabled | boolean | false | Disable the option |
hideCheckIcon | boolean | false | Hide check icon for selected state |
visibility | 'default' | 'always' | 'empty' | 'filtered-and-empty' | 'default' | Visibility control |
onClick | (args) => void | - | Custom click handler |
className | string | - | CSS class for option |
Render Function Arguments
When using a render function as children:
{({ selected, focused }) => ReactNode}selected- Boolean indicating if this option is selectedfocused- Boolean indicating if this option has keyboard/mouse focus
onClick Handler Arguments
onClick={({ selectCurrentOption, closeMenu, value, preventDefault }) => void}selectCurrentOption()- Manually trigger selectioncloseMenu()- Close the dropdownvalue- The option's valuepreventDefault()- Prevent default selection behavior
Styling
The component uses BEM-style class names:
GeckoUISelectOption- Base option elementGeckoUISelectOption--selected- Applied when selectedGeckoUISelectOption--focused- Applied when focusedGeckoUISelectOption--disabled- Applied when disabled
Best Practices
- Always provide label: Even with custom content, the
labelprop is required for filtering and accessibility - Use preventDefault wisely: Only use when you need complete control over selection behavior
- Keep custom content accessible: Ensure custom content works with keyboard navigation
- Consider performance: For large lists with complex custom content, consider virtualization
Related Pages
- Basic Usage - Introduction to Select
- Filterable - How filtering works with custom content
- SelectTrigger - Custom trigger components
- Multiple Selection - Multi-select with custom options