# Select

A select allows users to choose a single option from a list of predefined choices. It provides a compact interface for selection with a dropdown menu that displays available options when activated.

## When to Use

- Allow users to select one option from a predefined list
- Provide selection in forms where space is limited
- Offer choices where only one selection is allowed
- Create dropdown menus for navigation or filtering
- Present structured options in a compact interface

## Component

---

### Properties

- **`selectedKey`** `string` — The selected value in controlled mode
- **`defaultSelectedKey`** `string` — The default selected value in uncontrolled mode
- **`placeholder`** `string` — Placeholder text when no option is selected
- **`icon`** `ReactElement` — Icon element rendered before the select value
- **`rightIcon`** `ReactNode` — Icon element rendered after the select value (caret by default)
- **`prefix`** `ReactNode` — Content rendered before the select value
- **`suffix`** `ReactNode` — Content rendered after the select value
- **`shape`** `'card' | 'button' | 'sharp' | 'pill'` (default: `button`) — Shape of the trigger border radius
- **`suffixPosition`** `string` (default: `before`) — Position of suffix relative to validation icons
- **`type`** `string` (default: `outline`) — Visual style variant of the select
- **`theme`** `string` (default: `default`) — Theme variant affecting overall styling
- **`size`** `string` (default: `medium`) — Size of the select component
- **`direction`** `string` (default: `bottom`) — Preferred direction for the dropdown menu
- **`isClearable`** `boolean` (default: `false`) — Whether the select is clearable using a clear button in the rightIcon slot
- **`shouldFlip`** `boolean` (default: `true`) — Whether dropdown should flip to fit in viewport
- **`overlayOffset`** `number` (default: `8`) — Distance between select and dropdown in pixels
- **`items`** `Iterable<T>` — Item objects used when rendering dynamic collections
- **`disabledKeys`** `Iterable<Key>` — Keys of items that are disabled
- **`children`** `ReactNode | (item: T) => ReactElement` — Static child items or render function for dynamic items
- **`triggerRef`** `RefObject<HTMLButtonElement>` — Ref for the trigger button element
- **`popoverRef`** `RefObject<HTMLInputElement>` — Ref for the popover overlay element
- **`listBoxRef`** `RefObject<HTMLElement>` — Ref for the list box element
- **`loadingIndicator`** `ReactNode` — Custom loading indicator element
- **`hideTrigger`** `boolean` (default: `false`) — Whether to hide the trigger button
- **`styles`** `Styles` — Styles for the root wrapper element
- **`inputStyles`** `Styles` — Styles for the input trigger element
- **`listBoxStyles`** `Styles` — Styles for the dropdown list container
- **`optionStyles`** `Styles` — Styles for individual option items
- **`overlayStyles`** `Styles` — Styles for the dropdown overlay wrapper
- **`triggerStyles`** `Styles` — Styles for the trigger button element
- **`inputProps`** `Props` — Additional props for the input element
- **`triggerDescription`** `ReactNode` — Description text displayed within the trigger button (different from field-level description)
- **`descriptionPlacement`** `'inline' | 'block'` — Controls how the trigger description is positioned
- **`hotkeys`** `string` — Keyboard shortcut that triggers the select when pressed
- **`containerPadding`** `number` (default: `8`) — Minimum padding in pixels between the popover and viewport edges
- **`isOpen`** `boolean` — Whether the dropdown is open (controlled)
- **`defaultOpen`** `boolean` — Whether the dropdown is open by default (uncontrolled)
- **`selectionMode`** `'single'` — Selection mode for the select
- **`onSelectionChange`** `(key: Key) => void` — Callback fired when the selected option changes
- **`onOpenChange`** `(isOpen: boolean) => void` — Callback fired when the dropdown opens or closes
- **`onFocus`** `(e: FocusEvent) => void` — Callback fired when the select receives focus
- **`onBlur`** `(e: FocusEvent) => void` — Callback fired when the select loses focus
- **`onFocusChange`** `(isFocused: boolean) => void` — Callback fired when focus state changes
- **`aria-label`** `string` — Accessible label when no visible label exists
- **`aria-labelledby`** `string` — ID of element that labels the select
- **`aria-describedby`** `string` — ID of element that describes the select

#### Notable Properties

**isClearable** - Adds a clear button in the rightIcon slot that allows users to clear the selected value. The clear button only appears when a value is selected and the select is not disabled or read-only.

**onClear** - Callback fired when the clear button is pressed, allowing you to perform custom actions when the selection is cleared.

**tooltip** - Enables tooltip display on the trigger button. Can be:
- `string` - Simple tooltip text
- `true` - Auto tooltip on overflow (shows selected value when truncated)
- `object` - Advanced configuration with optional `auto` property

**triggerDescription** - Text description displayed within the trigger button. Different from field-level description provided by FieldWrapper.

**descriptionPlacement** - Controls how description is positioned: `inline` or `block`.

**overlayOffset** - Distance between the select trigger and dropdown in pixels (default: 8).

**direction** - Preferred direction for the dropdown: `top` or `bottom` (default: `bottom`).

**shouldFlip** - Whether the dropdown should flip to fit in viewport (default: `true`).

**suffixPosition** - Position of suffix content relative to validation icons: `before` or `after` (default: `before`).

### Base Properties

Supports [Base properties](../../BaseProperties.md)

### Field Properties

Supports all [Field properties](../../FieldProperties.md)

### Styling Properties

#### styles

Customizes the root wrapper element of the component.

#### triggerStyles

Customizes the trigger button element that opens the dropdown.

**Sub-elements:**
- `Label` - The displayed selected value text or placeholder
- `Prefix` - Container for prefix content
- `Suffix` - Container for suffix content
- `Icon` - Container for left icon
- `RightIcon` - Container for right icon (caret, loading, clear button)
- `Description` - Description text within the trigger
- `Hotkeys` - Keyboard shortcut display

#### listBoxStyles

Customizes the dropdown list container that displays options.

#### overlayStyles

Customizes the popover overlay wrapper that contains the list.

#### optionStyles

Customizes individual option items in the dropdown.

**Sub-elements:**
- `Label` - The main content/text of the option
- `Description` - Secondary description text
- `Prefix` - Container for prefix content
- `Suffix` - Container for suffix content
- `Icon` - Container for left icon
- `RightIcon` - Container for right icon

### Style Properties

These properties allow direct style application without using the `styles` prop:

- **Base:** `display`, `font`, `preset`, `hide`, `whiteSpace`, `opacity`, `transition`
- **Position:** `gridArea`, `order`, `gridColumn`, `gridRow`, `placeSelf`, `alignSelf`, `justifySelf`, `zIndex`, `margin`, `inset`, `position`
- **Dimension:** `width`, `height`, `flexBasis`, `flexGrow`, `flexShrink`, `flex`
- **Block:** `border`, `radius`, `shadow`, `outline`
- **Color:** `color`, `fill`, `fade`, `image`

### Modifiers

The `mods` property accepts the following modifiers you can override:

- `focused` `boolean` — Whether the select has focus
- `disabled` `boolean` — Whether the select is disabled
- `invalid` `boolean` — Whether the select has validation errors
- `valid` `boolean` — Whether the select is valid
- `placeholder` `boolean` — Whether showing placeholder text
- `hovered` `boolean` — Whether the select is being hovered
- `loading` `boolean` — Whether the select is in loading state
- `prefix` `boolean` — Whether prefix content is present
- `suffix` `boolean` — Whether suffix content is present

## Sub-components

### Select.Item

Individual option items within the select dropdown. Each item is rendered using [Item](../content/Item.md) and supports all Item properties for layout, icons, descriptions, and interactive features.

#### Item API

For detailed information about all available item properties, see [Item documentation](../content/Item.md). Key properties include:

- **`key`** `string \| number` — Unique identifier for the item (required)
- **`children`** `ReactNode` — The main content/label for the option
- **`icon`** `ReactNode` — Icon displayed before the content
- **`rightIcon`** `ReactNode` — Icon displayed after the content
- **`description`** `ReactNode` — Secondary text below the main content
- **`descriptionPlacement`** `'inline' \| 'block'` — How the description is positioned
- **`prefix`** `ReactNode` — Content before the main text
- **`suffix`** `ReactNode` — Content after the main text
- **`tooltip`** `string \| boolean \| object` — Tooltip configuration
- **`styles`** `Styles` — Custom styling for the item
- **`qa`** `string` — QA identifier for testing

#### Example with Rich Items

```jsx
<Select label="Users">
  <Select.Item 
    key="user1" 
    icon={<IconUser />}
    description="Administrator"
  >
    John Doe
  </Select.Item>
  <Select.Item 
    key="user2" 
    icon={<IconUser />}
    description="Editor"
    suffix="Online"
  >
    Jane Smith
  </Select.Item>
</Select>
```

### Select.Section

Groups related options together with an optional heading.

- **`title`** `ReactNode` — Optional heading text for the section
- **`children`** `Select.Item[]` — Collection of Select.Item components

## Variants

### Themes

- `default` - Standard select appearance
- `special` - Alternative styling for special contexts

### Types

- `primary` - Primary emphasis styling
- `outline` - Outlined appearance; `isSelected` adds brand-tinted fill
- `clear` - Minimal appearance; `isSelected` adds brand-tinted fill
- `link` - Link-like appearance

### Sizes

- `small` - Compact size for dense interfaces
- `medium` - Standard size for general interfaces (default)
- `large` - Emphasized size for important selections

## Examples

### Basic Usage

```jsx
<Select label="Choose an option">
  <Select.Item key="option1">Option 1</Select.Item>
  <Select.Item key="option2">Option 2</Select.Item>
  <Select.Item key="option3">Option 3</Select.Item>
</Select>
```

### With Default Value

```jsx
<Select label="Color" defaultSelectedKey="purple">
  <Select.Item key="red">Red</Select.Item>
  <Select.Item key="blue">Blue</Select.Item>
  <Select.Item key="purple">Purple</Select.Item>
</Select>
```

### With Placeholder

```jsx
<Select label="Country" placeholder="Select a country">
  <Select.Item key="us">United States</Select.Item>
  <Select.Item key="ca">Canada</Select.Item>
  <Select.Item key="uk">United Kingdom</Select.Item>
</Select>
```

### Clearable

```jsx
<Select
  isClearable
  label="Color"
  defaultSelectedKey="blue"
  placeholder="Choose a color..."
>
  <Select.Item key="red">Red</Select.Item>
  <Select.Item key="blue">Blue</Select.Item>
  <Select.Item key="green">Green</Select.Item>
</Select>
```

### Validation States

```jsx
{/* Valid state */}
<Select
  label="Validated field"
  selectedKey="yes"
  validationState="valid"
>
  <Select.Item key="yes">Yes</Select.Item>
  <Select.Item key="no">No</Select.Item>
</Select>

{/* Invalid state */}
<Select
  label="Required field"
  validationState="invalid"
  errorMessage="Please select an option"
>
  <Select.Item key="yes">Yes</Select.Item>
  <Select.Item key="no">No</Select.Item>
</Select>
```

### Disabled State

```jsx
<Select
  isDisabled
  label="Disabled select"
  selectedKey="option1"
>
  <Select.Item key="option1">Cannot change</Select.Item>
  <Select.Item key="option2">Option 2</Select.Item>
</Select>
```

### With Icon

```jsx
<Select label="Currency" icon={<IconCoin />}>
  <Select.Item key="usd">USD</Select.Item>
  <Select.Item key="eur">EUR</Select.Item>
  <Select.Item key="gbp">GBP</Select.Item>
</Select>
```

### With Description

```jsx
<Select placeholder="Select a color" listBoxStyles={{ width: 'max 30x' }}>
  <Select.Item key="red" description="The color of fire">
    Red
  </Select.Item>
  <Select.Item key="green" description="The color of nature">
    Green
  </Select.Item>
  <Select.Item key="blue" description="The color of the sky">
    Blue
  </Select.Item>
</Select>
```

### With Icons and Descriptions

```jsx
<Select placeholder="Select a color">
  <Select.Item 
    key="yellow" 
    description="Child and light" 
    icon={<IconUser />}
  >
    Yellow
  </Select.Item>
  <Select.Item 
    key="red" 
    description="Hot and strong" 
    prefix={<span>🔥</span>}
  >
    Red
  </Select.Item>
  <Select.Item 
    key="green" 
    description="Fresh and calm" 
    suffix={<Text color="#dark-03">#00A000</Text>}
  >
    Green
  </Select.Item>
</Select>
```

### With Sections (Static)

```jsx
<Select placeholder="Pick something">
  <Select.Section title="Warm colors">
    <Select.Item key="red">Red</Select.Item>
    <Select.Item key="orange">Orange</Select.Item>
    <Select.Item key="yellow">Yellow</Select.Item>
  </Select.Section>
  <Select.Section title="Cool colors">
    <Select.Item key="blue">Blue</Select.Item>
    <Select.Item key="purple">Purple</Select.Item>
  </Select.Section>
</Select>
```

### With Sections (Dynamic)

Sections and items can be defined dynamically using the `items` prop with a render function.

```jsx
const groups = [
  {
    name: 'Fruits',
    children: [
      { id: 'apple', label: 'Apple' },
      { id: 'orange', label: 'Orange' },
    ],
  },
  {
    name: 'Vegetables',
    children: [
      { id: 'carrot', label: 'Carrot' },
      { id: 'peas', label: 'Peas' },
    ],
  },
];

<Select items={groups} placeholder="Choose an item">
  {(group) => (
    <Select.Section key={group.name} title={group.name} items={group.children}>
      {(item) => <Select.Item key={item.id}>{item.label}</Select.Item>}
    </Select.Section>
  )}
</Select>
```

### With Tooltips

```jsx
<Select placeholder="Choose a framework">
  <Select.Item
    key="react"
    tooltip="React - A JavaScript library for building user interfaces"
  >
    React
  </Select.Item>
  <Select.Item
    key="vue"
    tooltip={{ title: 'Vue.js Framework' }}
  >
    Vue.js
  </Select.Item>
  <Select.Item
    key="angular"
    tooltip="Angular - Platform for building mobile and desktop web applications"
  >
    Angular
  </Select.Item>
</Select>
```

### With Disabled Items

```jsx
<Select disabledKeys={['red']}>
  <Select.Item key="red">Red (disabled)</Select.Item>
  <Select.Item key="blue">Blue</Select.Item>
  <Select.Item key="green">Green</Select.Item>
</Select>
```

## Accessibility

### Keyboard Navigation

- `Tab` - Moves focus to the select
- `Space/Enter` - Opens the dropdown
- `Arrow Down` - Opens dropdown and moves to first/next option
- `Arrow Up` - Moves to previous option (when open)
- `Home` - Moves to first option
- `End` - Moves to last option
- `Escape` - Closes dropdown without selecting
- `Enter` - Selects focused option and closes dropdown
- Typing - Navigates to options starting with typed character

### Screen Reader Support

- Component announces as "combobox" or "listbox" to screen readers
- Current selection is announced when changed
- Available options are announced during navigation
- Dropdown state (open/closed) is communicated

### ARIA Properties

- `aria-label` - Provides accessible label when no visible label exists
- `aria-labelledby` - References external label elements
- `aria-describedby` - References additional descriptive text
- `aria-expanded` - Indicates if dropdown is open
- `aria-activedescendant` - References the currently focused option
- `aria-required` - Indicates if selection is required
- `aria-invalid` - Indicates validation state

## Best Practices

1. **Do**: Provide clear, descriptive labels and meaningful option text
   ```jsx
   <Select label="Shipping method">
     <Select.Item key="standard">Standard (5-7 days)</Select.Item>
     <Select.Item key="express">Express (2-3 days)</Select.Item>
   </Select>
   ```

2. **Don't**: Use select for very long lists (use ComboBox or FilterPicker with search instead)
   ```jsx
   {/* Consider ComboBox or FilterPicker for 50+ options */}
   <Select label="Country">
     {/* 100+ countries... */}
   </Select>
   ```

3. **Do**: Use sections to group related options logically
   ```jsx
   <Select label="Category">
     <Select.Section title="Popular">
       <Select.Item key="featured1">Featured Option 1</Select.Item>
     </Select.Section>
     <Select.Section title="All Options">
       <Select.Item key="all1">All Option 1</Select.Item>
     </Select.Section>
   </Select>
   ```

4. **Do**: Provide clear error messages for validation failures
   ```jsx
   <Select
     isRequired
     validationState="invalid"
     errorMessage="Please select a shipping method"
     label="Shipping"
   >
     <Select.Item key="standard">Standard</Select.Item>
   </Select>
   ```

5. **Do**: Consider providing sensible defaults when appropriate
   ```jsx
   <Select label="Language" defaultSelectedKey="en">
     <Select.Item key="en">English</Select.Item>
     <Select.Item key="es">Spanish</Select.Item>
   </Select>
   ```

6. **Do**: Show loading state when options are being fetched
   ```jsx
   <Select isLoading label="Categories" placeholder="Loading...">
     {categories.map(cat => <Select.Item key={cat.id}>{cat.name}</Select.Item>)}
   </Select>
   ```

7. **Accessibility**: Always provide meaningful labels
   ```jsx
   <Select label="Country" aria-label="Select your country">
     <Select.Item key="us">United States</Select.Item>
   </Select>
   ```

8. **Clearable**: Use `isClearable` for optional selections
   ```jsx
   <Select isClearable label="Filter by status" placeholder="All statuses">
     <Select.Item key="active">Active</Select.Item>
     <Select.Item key="inactive">Inactive</Select.Item>
   </Select>
   ```

## Integration with Forms

This component supports all [Field properties](../../FieldProperties.md) when used within a Form. It integrates seamlessly with the form validation system and supports both controlled and uncontrolled modes.

```jsx
<Form>
  <Select
    name="country"
    label="Country"
    isRequired
    validationBehavior="native"
  >
    <Select.Item key="us">United States</Select.Item>
    <Select.Item key="uk">United Kingdom</Select.Item>
    <Select.Item key="ca">Canada</Select.Item>
  </Select>
</Form>
```

## Suggested Improvements

- Add support for multi-selection mode with visual badges
- Implement virtual scrolling for very large option lists (1000+ items)
- Built-in async loading support with loading states per scroll position
- Enhanced keyboard shortcuts for power users (e.g., type to jump to option)
- Custom empty state component when no options are available
- Support for option groups with visual separators beyond sections

## Related Components

- [ComboBox](./ComboBox.md) - For searchable selection with filtering capabilities
- [FilterPicker](./FilterPicker.md) - Alternative with different interaction patterns
- [ListBox](./ListBox.md) - The underlying list component used in Select
- [RadioGroup](./RadioGroup.md) - For visible selection options with fewer choices
- [Item](../content/Item.md) - The base component used for rendering items
