SelectOption
Advanced option patterns including custom content, click handlers, and visibility control
You are reading the v1 docs. v2 renamed several props and replaced GeckoUIPortal with GeckoUIProvider. Read this page in v2.
Live examples are only rendered in the v2 docs.
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">[email protected]</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 base class names with data-* attributes for states:
GeckoUISelectOption- Base option elementdata-state="selected"/data-state="unselected"- Selection statedata-focused- Applied when focuseddata-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