Overview
The Select component provides an accessible dropdown selection interface built on React Aria’s ComboBox. It supports multiple sizes, disabled options, and keyboard navigation.
Import
import { Select } from 'stride-ds';
import type { SelectOption } from 'stride-ds';
Basic Usage
import { Select } from 'stride-ds';
const options = [
{ value: 'apple', label: 'Apple' },
{ value: 'banana', label: 'Banana' },
{ value: 'orange', label: 'Orange' },
];
function Example() {
return (
<Select
options={options}
placeholder="Choose a fruit..."
/>
);
}
Sizes
Three size options are available:
<Select size="sm" options={options} placeholder="Small select..." />
<Select size="md" options={options} placeholder="Medium select..." />
<Select size="lg" options={options} placeholder="Large select..." />
With Disabled Options
Individual options can be disabled:
const options = [
{ value: 'option1', label: 'Option 1' },
{ value: 'option2', label: 'Option 2 (Disabled)', disabled: true },
{ value: 'option3', label: 'Option 3' },
];
<Select options={options} placeholder="Select an option..." />
States
Default Value
<Select
options={options}
placeholder="Choose a fruit..."
defaultSelectedKey="banana"
/>
Disabled
<Select
options={options}
placeholder="Disabled select..."
isDisabled
/>
Required
<Select
options={options}
placeholder="Required selection..."
isRequired
/>
Props
Array of options to display in the dropdown. Each option has value, label, and optional disabled properties.
placeholder
string
default:"'Select an option...'"
Placeholder text shown when no option is selected.
size
'sm' | 'md' | 'lg'
default:"'md'"
Size of the select component.
The initially selected option value (uncontrolled).
The currently selected option value (controlled).
Handler called when the selection changes.
Whether the select is disabled.
Whether a selection is required.
Additional CSS classes to apply to the wrapper.
The name of the select in a form.
SelectOption Type
interface SelectOption {
value: string; // Unique identifier for the option
label: string; // Display text
disabled?: boolean; // Whether this option is disabled
}
Accessibility
The Select component is built with React Aria ComboBox and provides:
- Keyboard Navigation:
- Arrow keys to navigate options
- Enter to select
- Escape to close
- Type to search options
- Focus Management: Proper focus handling and restoration
- Screen Reader Support: Full ARIA combobox implementation
- Disabled State: Properly communicated to assistive technologies
Best Practices
-
Provide clear, descriptive option labels:
const options = [
{ value: 'us', label: 'United States' },
{ value: 'ca', label: 'Canada' },
];
-
Use descriptive placeholders:
<Select placeholder="Choose your country..." options={options} />
-
Group related options logically:
// Good: Alphabetical or by popularity
const countries = [
{ value: 'us', label: 'United States' },
{ value: 'uk', label: 'United Kingdom' },
// ...
];
Examples
All Sizes
const options = [
{ value: 'apple', label: 'Apple' },
{ value: 'banana', label: 'Banana' },
{ value: 'orange', label: 'Orange' },
];
<div className="space-y-4 w-64">
<div>
<label className="block text-sm font-medium mb-2">Small</label>
<Select size="sm" options={options} placeholder="Small select..." />
</div>
<div>
<label className="block text-sm font-medium mb-2">Medium</label>
<Select options={options} placeholder="Medium select..." />
</div>
<div>
<label className="block text-sm font-medium mb-2">Large</label>
<Select size="lg" options={options} placeholder="Large select..." />
</div>
</div>
Country Selector
const countryOptions = [
{ value: 'us', label: 'United States' },
{ value: 'ca', label: 'Canada' },
{ value: 'uk', label: 'United Kingdom' },
{ value: 'fr', label: 'France' },
{ value: 'de', label: 'Germany' },
{ value: 'jp', label: 'Japan' },
{ value: 'au', label: 'Australia' },
];
<Select
options={countryOptions}
placeholder="Select a country..."
/>
With Disabled Options
const options = [
{ value: 'free', label: 'Free Plan' },
{ value: 'pro', label: 'Pro Plan' },
{ value: 'enterprise', label: 'Enterprise (Contact Sales)', disabled: true },
];
<Select
options={options}
placeholder="Choose a plan..."
/>
const longOptions = Array.from({ length: 50 }, (_, i) => ({
value: `item-${i + 1}`,
label: `Item ${i + 1}`,
}));
<Select
options={longOptions}
placeholder="Select from many options..."
/>
Controlled Component
import { useState } from 'react';
import { Select } from 'stride-ds';
function ControlledExample() {
const [selected, setSelected] = useState('');
const options = [
{ value: 'apple', label: 'Apple' },
{ value: 'banana', label: 'Banana' },
{ value: 'orange', label: 'Orange' },
];
return (
<div>
<Select
options={options}
placeholder="Choose a fruit..."
selectedKey={selected}
onSelectionChange={setSelected}
/>
{selected && (
<p className="mt-4">Selected: {selected}</p>
)}
</div>
);
}
import { Select } from 'stride-ds';
function FormExample() {
const handleSubmit = (e) => {
e.preventDefault();
const formData = new FormData(e.target);
console.log('Country:', formData.get('country'));
};
return (
<form onSubmit={handleSubmit}>
<label className="block text-sm font-medium mb-2">
Country
</label>
<Select
name="country"
options={countryOptions}
placeholder="Select your country..."
isRequired
/>
<button type="submit" className="mt-4">
Submit
</button>
</form>
);
}
The Select component works with React Hook Form:
import { useForm, Controller } from 'react-hook-form';
import { Select } from 'stride-ds';
function FormExample() {
const { control, handleSubmit, formState: { errors } } = useForm();
const options = [
{ value: 'option1', label: 'Option 1' },
{ value: 'option2', label: 'Option 2' },
{ value: 'option3', label: 'Option 3' },
];
return (
<form onSubmit={handleSubmit(onSubmit)}>
<Controller
name="selection"
control={control}
rules={{ required: 'Please make a selection' }}
render={({ field }) => (
<div>
<Select
options={options}
placeholder="Choose an option..."
selectedKey={field.value}
onSelectionChange={field.onChange}
/>
{errors.selection && (
<p className="text-red-500 text-sm mt-1">
{errors.selection.message}
</p>
)}
</div>
)}
/>
</form>
);
}