Skip to main content

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

options
SelectOption[]
required
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.
defaultSelectedKey
string
The initially selected option value (uncontrolled).
selectedKey
string
The currently selected option value (controlled).
onSelectionChange
(key: string) => void
Handler called when the selection changes.
isDisabled
boolean
default:"false"
Whether the select is disabled.
isRequired
boolean
default:"false"
Whether a selection is required.
className
string
Additional CSS classes to apply to the wrapper.
name
string
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

  1. Provide clear, descriptive option labels:
    const options = [
      { value: 'us', label: 'United States' },
      { value: 'ca', label: 'Canada' },
    ];
    
  2. Use descriptive placeholders:
    <Select placeholder="Choose your country..." options={options} />
    
  3. 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..."
/>

Long List with Scrolling

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>
  );
}

Form Integration

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>
  );
}

React Hook Form Integration

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>
  );
}

Build docs developers (and LLMs) love