# Picker

A versatile selection component that combines a trigger button with a dropdown list. It provides a space-efficient interface for selecting one or multiple items from a list, with support for sections, custom summaries, and various UI states.

## When to Use

- Creating selection interfaces where users need to choose from predefined options
- Implementing compact selection interfaces where space is limited
- Building user preference panels with organized option groups
- When you need single or multiple selection from a list
- When you don't need search/filter functionality (use ComboBox or FilterPicker for searchable lists)

## Component

---

### Properties

### Base Properties

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

### Styling Properties

#### styles

Customizes the root wrapper element and the trigger button of the Picker component.

**Sub-elements:**
- None

#### triggerStyles

Customizes the DialogTrigger wrapper that contains the trigger button and manages the popover.

**Sub-elements:**
- None

#### listBoxStyles

Customizes the ListBox component styles within the popover. See [ListBox documentation](./ListBox.md) for available sub-elements.

**Sub-elements:**
- `Label` - Item label text
- `Description` - Item description text  
- `Content` - Item content wrapper
- `Checkbox` - Checkbox element in multiple selection mode
- `CheckboxWrapper` - Wrapper around checkbox

#### popoverStyles

Customizes the popover Dialog that contains the ListBox. See [Dialog documentation](../overlays/Dialog.md) for available sub-elements.

**Sub-elements:**
- None for Dialog in popover mode

#### headerStyles

Customizes the header area when `header` prop is provided.

**Sub-elements:**
- None

#### footerStyles

Customizes the footer area when `footer` prop is provided.

**Sub-elements:**
- None

### Style Properties

These properties allow direct style application without using the `styles` prop: `display`, `font`, `preset`, `hide`, `opacity`, `whiteSpace`, `width`, `height`, `flexBasis`, `flexGrow`, `flexShrink`, `flex`, `gridArea`, `order`, `gridColumn`, `gridRow`, `placeSelf`, `alignSelf`, `justifySelf`, `zIndex`, `margin`, `inset`, `position`, `color`, `fill`, `fade`.

### Modifiers

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

| Modifier | Type | Description |
|----------|------|-------------|
| `placeholder` | `boolean` | Applied when no selection is made |
| `selected` | `boolean` | Applied when items are selected |

## Sub-components

### Picker.Item

Represents individual selectable items within the Picker dropdown. Each item is rendered using [Item](../content/Item.md) and inherits all its properties.

#### Key Properties

See [Item documentation](../content/Item.md) for the complete API. Common properties include:

| Property | Type | Description |
|----------|------|-------------|
| `key` | `string \| number` | Unique identifier for the item (required) |
| `children` | `ReactNode` | The main content/label for the item |
| `textValue` | `string` | Accessible text for screen readers (required for complex content) |
| `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 relative to content |
| `prefix` | `ReactNode` | Content before the main text |
| `suffix` | `ReactNode` | Content after the main text |
| `isDisabled` | `boolean` | Whether the item is disabled |
| `tooltip` | `string \| boolean \| TooltipProps` | Tooltip configuration |
| `styles` | `Styles` | Custom styling for the item |
| `qa` | `string` | QA identifier for testing |

#### Examples with Rich Items

**With Icons and Descriptions:**
```jsx
<Picker label="Team Selection" selectionMode="single">
  <Picker.Item 
    key="active" 
    icon={<IconUsers />}
    description="All active team members"
  >
    Active Users
  </Picker.Item>
  <Picker.Item 
    key="admins" 
    icon={<IconShield />}
    description="Admin users only"
  >
    Administrators
  </Picker.Item>
</Picker>
```

**With Prefix and Suffix:**
```jsx
<Picker label="Select Plan" selectionMode="single">
  <Picker.Item 
    key="free"
    prefix={<Badge>Free</Badge>}
    suffix="$0/mo"
  >
    Basic Plan
  </Picker.Item>
  <Picker.Item 
    key="pro"
    prefix={<Badge type="primary">Pro</Badge>}
    suffix="$29/mo"
  >
    Pro Plan
  </Picker.Item>
</Picker>
```

### Picker.Section

Groups related items together under an optional section heading. Sections provide visual and semantic grouping for better organization.

#### Properties

| Property | Type | Default | Description |
|----------|------|---------|-------------|
| `title` | `ReactNode` | - | Section heading text (optional) |
| `children` | `Picker.Item[]` | - | Collection of Picker.Item components (required) |

#### Example

```jsx
<Picker label="Food Categories" selectionMode="single">
  <Picker.Section title="Fruits">
    <Picker.Item key="apple">Apple</Picker.Item>
    <Picker.Item key="banana">Banana</Picker.Item>
  </Picker.Section>
  <Picker.Section title="Vegetables">
    <Picker.Item key="carrot">Carrot</Picker.Item>
    <Picker.Item key="broccoli">Broccoli</Picker.Item>
  </Picker.Section>
</Picker>
```

**Note:** Sections disable virtualization. For large datasets (50+ items), use a flat structure with the `items` prop instead.

## Content Patterns

### Static Children Pattern

The most common pattern for Picker is to provide static children using `Picker.Item` and `Picker.Section` components:

```jsx
<Picker label="Select Options">
  <Picker.Item key="apple">Apple</Picker.Item>
  <Picker.Item key="banana">Banana</Picker.Item>
  <Picker.Section title="Vegetables">
    <Picker.Item key="carrot">Carrot</Picker.Item>
  </Picker.Section>
</Picker>
```

### Dynamic Content Pattern

For large datasets or dynamic content, use the `items` prop with a render function. This pattern enables automatic virtualization for performance:

```jsx
<Picker
  label="Large Dataset"
  items={largeDataArray}
>
  {(item) => (
    <Picker.Item key={item.id} textValue={item.name}>
      {item.name}
    </Picker.Item>
  )}
</Picker>
```

**Key Benefits:**
- **Virtualization**: Automatically enabled for large lists without sections
- **Performance**: Only renders visible items in the DOM
- **Dynamic Content**: Perfect for data fetched from APIs or changing datasets
- **Memory Efficient**: Handles thousands of items smoothly

**When to Use:**
- Lists with 50+ items
- Dynamic data from APIs
- Content that changes frequently
- When virtualization performance is needed

## Variants

### Selection Modes

| Mode | Description | Use Case |
|------|-------------|----------|
| `single` | Select only one item at a time | Category selection, single choice questions |
| `multiple` | Select multiple items with checkboxes | Tags, filters, permissions |

### Trigger Button Types

The trigger button supports various visual styles via the `type` prop:

| Type | Description | Use Case |
|------|-------------|----------|
| `outline` | Outlined button with border (default) | Standard form inputs |
| `clear` | Transparent background | Toolbar actions, compact interfaces |
| `primary` | Primary brand color | Emphasized selections |
| `secondary` | Secondary color variant | Alternative emphasis |
| `neutral` | Neutral color scheme | Subtle selections |

### Trigger Button Themes

Control the color scheme with the `theme` prop:

| Theme | Description |
|-------|-------------|
| `default` | Standard theme (default) |
| `danger` | Red/destructive color (also applied automatically when `validationState="invalid"`) |

### Sizes

| Size | Height | Use Case |
|------|--------|----------|
| `small` | ~28px | Dense interfaces, compact layouts |
| `medium` | ~32px | Standard forms (default) |
| `large` | ~40px | Emphasized selections, accessibility |

## Examples

### Basic Single Selection

Standard single-selection picker with a placeholder and label.

```jsx
<Picker 
  label="Favorite Fruit" 
  placeholder="Select a fruit"
  selectionMode="single"
>
  <Picker.Item key="apple">Apple</Picker.Item>
  <Picker.Item key="banana">Banana</Picker.Item>
  <Picker.Item key="orange">Orange</Picker.Item>
</Picker>
```

### Multiple Selection

Multiple selection mode with checkboxes for clarity.

```jsx
<Picker
  label="Favorite Fruits"
  placeholder="Select fruits"
  selectionMode="multiple"
  isCheckable
>
  <Picker.Item key="apple">Apple</Picker.Item>
  <Picker.Item key="banana">Banana</Picker.Item>
  <Picker.Item key="orange">Orange</Picker.Item>
</Picker>
```

### With Clear Button

Enable users to clear their selection with a clear button that appears when an item is selected.

```jsx
<Picker
  label="Favorite Fruit"
  placeholder="Select a fruit"
  selectionMode="single"
  isClearable
  defaultSelectedKey="apple"
>
  <Picker.Item key="apple">Apple</Picker.Item>
  <Picker.Item key="banana">Banana</Picker.Item>
  <Picker.Item key="orange">Orange</Picker.Item>
</Picker>
```

### Multiple Selection with Select All

Add a "Select All" option for quick selection of all available items in multiple selection mode.

```jsx
<Picker
  label="Favorite Fruits"
  placeholder="Select fruits"
  selectionMode="multiple"
  showSelectAll
  selectAllLabel="All Fruits"
  isCheckable
>
  <Picker.Item key="apple">Apple</Picker.Item>
  <Picker.Item key="banana">Banana</Picker.Item>
  <Picker.Item key="orange">Orange</Picker.Item>
</Picker>
```

### Custom Summary

Customize how the selected items are displayed in the trigger button using a custom render function.

```jsx
<Picker
  label="Favorite Fruits"
  placeholder="Select fruits"
  selectionMode="multiple"
  isCheckable
  renderSummary={({ selectedLabels, selectedKeys }) => {
    if (!selectedLabels || selectedLabels.length === 0) return null;
    if (selectedLabels.length === 1) return selectedLabels[0];
    return `${selectedLabels.length} fruits selected`;
  }}
>
  <Picker.Item key="apple">Apple</Picker.Item>
  <Picker.Item key="banana">Banana</Picker.Item>
  <Picker.Item key="orange">Orange</Picker.Item>
</Picker>
```

### With Sections

Organize items into logical groups with section headers.

```jsx
<Picker
  label="Favorite Food"
  placeholder="Select a food"
  selectionMode="single"
>
  <Picker.Section title="Fruits">
    <Picker.Item key="apple">Apple</Picker.Item>
    <Picker.Item key="banana">Banana</Picker.Item>
    <Picker.Item key="orange">Orange</Picker.Item>
  </Picker.Section>
  <Picker.Section title="Vegetables">
    <Picker.Item key="carrot">Carrot</Picker.Item>
    <Picker.Item key="broccoli">Broccoli</Picker.Item>
    <Picker.Item key="spinach">Spinach</Picker.Item>
  </Picker.Section>
</Picker>
```

### Different Sizes

Picker supports three sizes: small, medium (default), and large.

```jsx
<Picker 
  size="small"
  label="Small Picker"
  placeholder="Select a fruit"
>
  <Picker.Item key="apple">Apple</Picker.Item>
  <Picker.Item key="banana">Banana</Picker.Item>
</Picker>

<Picker 
  size="medium"
  label="Medium Picker"
  placeholder="Select a fruit"
>
  <Picker.Item key="apple">Apple</Picker.Item>
  <Picker.Item key="banana">Banana</Picker.Item>
</Picker>

<Picker 
  size="large"
  label="Large Picker"
  placeholder="Select a fruit"
>
  <Picker.Item key="apple">Apple</Picker.Item>
  <Picker.Item key="banana">Banana</Picker.Item>
</Picker>
```

### Disabled State

Disable the picker to prevent user interaction.

```jsx
<Picker
  label="Favorite Fruit"
  placeholder="Select a fruit"
  selectionMode="single"
  isDisabled
  defaultSelectedKey="apple"
>
  <Picker.Item key="apple">Apple</Picker.Item>
  <Picker.Item key="banana">Banana</Picker.Item>
</Picker>
```

### With Validation

Display validation states and error messages.

```jsx
<Picker
  label="Favorite Fruit"
  placeholder="Select a fruit"
  selectionMode="single"
  isRequired
  validationState="invalid"
  message="Please select a fruit"
>
  <Picker.Item key="apple">Apple</Picker.Item>
  <Picker.Item key="banana">Banana</Picker.Item>
</Picker>
```

### With Description

Add helpful description text below the label.

```jsx
<Picker
  label="Favorite Fruit"
  description="Choose your favorite fruit from the list"
  placeholder="Select a fruit"
  selectionMode="single"
>
  <Picker.Item key="apple">Apple</Picker.Item>
  <Picker.Item key="banana">Banana</Picker.Item>
</Picker>
```

## Accessibility

The Picker component is built with React Aria hooks and provides comprehensive accessibility support out of the box.

### Keyboard Navigation

| Key | Action |
|-----|--------|
| `Tab` | Moves focus to/from the trigger button |
| `Space` or `Enter` | Opens the dropdown popover when focused on trigger |
| `Arrow Up` or `Arrow Down` | Opens the popover when closed; navigates through items when open |
| `Escape` | Closes the popover and returns focus to trigger |
| `Space` or `Enter` | Selects the focused item (single mode closes popover automatically) |

**In the popover:**
- Arrow keys navigate through items
- Home/End keys jump to first/last item
- Type-ahead: typing characters focuses matching items
- In multiple selection mode: Space toggles selection without closing

### Screen Reader Support

- Trigger button announces as "button" with current selection state
- When empty: announces placeholder text
- When selected: announces selected item(s) or count
- Popover opening/closing is announced to screen readers
- Item selection changes are announced immediately
- Loading state announces "loading" to users
- Validation errors are associated and announced
- Section headers are properly announced when navigating

### ARIA Properties

The component automatically manages ARIA attributes:

| Attribute | Usage |
|-----------|-------|
| `aria-label` | Labels the trigger when no visible label exists |
| `aria-labelledby` | Associates the label with the trigger |
| `aria-expanded` | Indicates whether the popover is open (true/false) |
| `aria-haspopup` | Indicates the button controls a listbox (listbox) |
| `aria-describedby` | Associates help text and error messages |
| `aria-invalid` | Indicates validation state (true when invalid) |
| `aria-required` | Indicates required fields (true when required) |
| `aria-disabled` | Indicates disabled state |

### Best Practices for Accessibility

1. **Always provide a label**: Use the `label` prop or `aria-label` for screen reader users
   ```jsx
   <Picker label="Select Category">...</Picker>
   ```

2. **Use meaningful placeholders**: Placeholders should describe the expected selection
   ```jsx
   <Picker placeholder="Choose a category" label="Category">...</Picker>
   ```

3. **Provide help text**: Use `description` for additional context
   ```jsx
   <Picker 
     label="Priority"
     description="Select the task priority level"
   >...</Picker>
   ```

4. **Handle validation properly**: Use `validationState` and `message` props
   ```jsx
   <Picker 
     validationState="invalid"
     message="Please select an option"
   >...</Picker>
   ```

5. **Use `textValue` for complex items**: Ensures screen readers can announce item content
   ```jsx
   <Picker.Item textValue="User Name - Role">
     <ComplexUserComponent />
   </Picker.Item>
   ```

## Best Practices

1. **Do**: Provide clear, descriptive labels and placeholders
   ```jsx
   <Picker 
     label="Product Category" 
     placeholder="Choose a category..."
     selectionMode="single"
   >
     <Picker.Item key="electronics">Electronics</Picker.Item>
     <Picker.Item key="clothing">Clothing</Picker.Item>
   </Picker>
   ```

2. **Don't**: Use overly long option texts that will be truncated
   ```jsx
   // Avoid
   <Picker.Item key="long">
     This is an extremely long option text that will be truncated and hard to read
   </Picker.Item>
   
   // Instead, use description
   <Picker.Item key="short" description="Additional details here">
     Short Label
   </Picker.Item>
   ```

3. **Do**: Use sections for logical grouping
   ```jsx
   <Picker label="Select Food" selectionMode="single">
     <Picker.Section title="Fruits">
       <Picker.Item key="apple">Apple</Picker.Item>
     </Picker.Section>
     <Picker.Section title="Vegetables">
       <Picker.Item key="carrot">Carrot</Picker.Item>
     </Picker.Section>
   </Picker>
   ```

4. **Do**: Use the `items` prop for large datasets to enable virtualization
   ```jsx
   <Picker items={largeDataset} label="Select Item">
     {(item) => <Picker.Item key={item.id}>{item.name}</Picker.Item>}
   </Picker>
   ```

5. **Do**: Use `isClearable` for optional single selections
   ```jsx
   <Picker 
     label="Optional Filter"
     selectionMode="single" 
     isClearable
     placeholder="Choose an option..."
   >
     <Picker.Item key="option1">Option 1</Picker.Item>
   </Picker>
   ```

6. **Do**: Use `showSelectAll` for efficient multiple selection
   ```jsx
   <Picker 
     label="Permissions"
     selectionMode="multiple" 
     showSelectAll 
     selectAllLabel="All Permissions"
     isCheckable
   >
     <Picker.Item key="read">Read</Picker.Item>
     <Picker.Item key="write">Write</Picker.Item>
   </Picker>
   ```

7. **Do**: Use `isCheckable` in multiple selection mode for clarity
   ```jsx
   <Picker 
     label="Select Options"
     selectionMode="multiple" 
     isCheckable
   >
     <Picker.Item key="option1">Option 1</Picker.Item>
   </Picker>
   ```

8. **Accessibility**: Always provide meaningful `aria-label` when label is not visible
9. **Performance**: Use `textValue` prop for items with complex content
10. **UX**: Provide feedback for empty states and loading states

## Integration with Forms

This component supports all [Field properties](../form/Field.md) when used within a Form context. The Picker automatically handles form validation, touched states, error messages, and integrates seamlessly with form submission.

### Basic Form Integration

```jsx
import { Form, Picker } from '@cube-dev/ui-kit';

function MyForm() {
  const handleSubmit = (values) => {
    console.log('Form values:', values);
  };

  return (
    <Form onSubmit={handleSubmit}>
      <Picker
        name="category"
        label="Product Category"
        isRequired
        selectionMode="single"
        placeholder="Select a category"
        rules={[{ required: true, message: 'Category is required' }]}
      >
        <Picker.Item key="electronics">Electronics</Picker.Item>
        <Picker.Item key="clothing">Clothing</Picker.Item>
        <Picker.Item key="books">Books</Picker.Item>
      </Picker>

      <Button type="submit">Submit</Button>
    </Form>
  );
}
```

### Multiple Selection in Forms

```jsx
<Form onSubmit={handleSubmit}>
  <Picker
    name="tags"
    label="Tags"
    selectionMode="multiple"
    isCheckable
    placeholder="Select tags"
    defaultValue={['tag1', 'tag2']}
    rules={[
      { required: true, message: 'At least one tag is required' },
      { type: 'array', min: 2, message: 'Select at least 2 tags' }
    ]}
  >
    <Picker.Item key="tag1">Tag 1</Picker.Item>
    <Picker.Item key="tag2">Tag 2</Picker.Item>
    <Picker.Item key="tag3">Tag 3</Picker.Item>
  </Picker>

  <Button type="submit">Submit</Button>
</Form>
```

### Key Form Properties

| Property | Description |
|----------|-------------|
| `name` | Field name in form data (required for form integration) |
| `rules` | Validation rules array |
| `defaultValue` | Initial value (use with uncontrolled forms) |
| `value` | Controlled value (use with controlled forms) |
| `isRequired` | Marks field as required and adds visual indicator |
| `validationState` | Manual validation state control |
| `message` | Error or help message |

## Advanced Features

### Custom Summary Rendering

Customize how the selection is displayed in the trigger button. The `renderSummary` function receives different parameters based on selection mode:

```jsx
const renderSummary = ({ selectedLabels, selectedKeys, selectionMode }) => {
  if (selectionMode === 'single') {
    return selectedLabels?.[0] ? `Selected: ${selectedLabels[0]}` : null;
  }
  
  if (!selectedKeys || selectedKeys.length === 0) return null;
  if (selectedKeys === 'all') return 'All items selected';
  if (selectedKeys.length === 1) return selectedLabels[0];
  if (selectedKeys.length <= 3) return selectedLabels.join(', ');
  return `${selectedKeys.length} items selected`;
};

<Picker 
  label="Custom Summary"
  selectionMode="multiple"
  renderSummary={renderSummary}
>
  <Picker.Item key="apple">Apple</Picker.Item>
  <Picker.Item key="banana">Banana</Picker.Item>
  <Picker.Item key="orange">Orange</Picker.Item>
</Picker>
```

### Icon-Only Mode

For space-constrained interfaces, hide the summary text and show only an icon:

```jsx
<Picker
  renderSummary={false}
  icon={<FilterIcon />}
  aria-label="Filter options"
  type="clear"
  selectionMode="multiple"
>
  <Picker.Item key="option1">Option 1</Picker.Item>
  <Picker.Item key="option2">Option 2</Picker.Item>
</Picker>
```

### Controlled Mode

Full control over selection state for integration with external state management:

**Single Selection:**
```jsx
const [selectedKey, setSelectedKey] = useState(null);

<Picker
  label="Controlled Picker"
  selectionMode="single"
  selectedKey={selectedKey}
  onSelectionChange={(key) => setSelectedKey(key)}
>
  <Picker.Item key="apple">Apple</Picker.Item>
  <Picker.Item key="banana">Banana</Picker.Item>
</Picker>
```

**Multiple Selection:**
```jsx
const [selectedKeys, setSelectedKeys] = useState([]);

<Picker
  label="Controlled Multiple"
  selectionMode="multiple"
  isCheckable
  selectedKeys={selectedKeys}
  onSelectionChange={(keys) => {
    if (keys === 'all') {
      setSelectedKeys(['apple', 'banana', 'orange']);
    } else {
      setSelectedKeys(keys);
    }
  }}
>
  <Picker.Item key="apple">Apple</Picker.Item>
  <Picker.Item key="banana">Banana</Picker.Item>
  <Picker.Item key="orange">Orange</Picker.Item>
</Picker>
```

### Dynamic Items with Sorting

Use the `items` prop with `sortSelectedToTop` to automatically sort selected items to the top when the picker opens:

```jsx
const fruits = [
  { key: 'apple', label: 'Apple' },
  { key: 'banana', label: 'Banana' },
  { key: 'orange', label: 'Orange' },
  { key: 'mango', label: 'Mango' },
];

<Picker
  label="Sorted Picker"
  items={fruits}
  sortSelectedToTop
  defaultSelectedKeys={['banana', 'mango']}
  selectionMode="multiple"
  isCheckable
>
  {(item) => <Picker.Item key={item.key}>{item.label}</Picker.Item>}
</Picker>
```

## Performance

### Optimization Tips

1. **Use Dynamic Content Pattern for Large Lists**
   - For lists with 50+ items, use the `items` prop with a render function
   - This enables automatic virtualization for better performance
   - Only visible items are rendered in the DOM

2. **Avoid Sections with Large Datasets**
   - Virtualization is disabled when sections are present
   - For large lists, prefer flat structure or use filtering instead

3. **Provide `textValue` for Complex Content**
   - When items contain complex JSX, provide a `textValue` prop
   - This helps with accessibility and potential search functionality

4. **Consider Controlled Mode for Expensive Operations**
   - Use controlled mode to debounce expensive operations
   - Handle state updates efficiently in your own state management

### Virtualization

Virtualization is automatically enabled when using the `items` prop without sections:

```jsx
// ✅ Virtualized - excellent performance with thousands of items
<Picker 
  items={thousandsOfItems}
  label="Large Dataset"
>
  {(item) => <Picker.Item key={item.id}>{item.name}</Picker.Item>}
</Picker>

// ❌ Not virtualized - sections disable virtualization
<Picker items={largeArray}>
  <Picker.Section title="All Items">
    {largeArray.map(item => (
      <Picker.Item key={item.id}>{item.name}</Picker.Item>
    ))}
  </Picker.Section>
</Picker>
```

### Content Optimization

Optimize complex item content with the `textValue` prop for better accessibility:

```jsx
<Picker label="Select User" items={users}>
  {(user) => (
    <Picker.Item 
      key={user.id} 
      textValue={`${user.name} - ${user.role}`}
    >
      <UserCard user={user} />
    </Picker.Item>
  )}
</Picker>
```

## Related Components

- [ComboBox](./ComboBox.md) - Use when you need search/filter functionality or custom value entry
- [ListBox](./ListBox.md) - Use for always-visible list selection without a trigger
- [Select](./Select.md) - Use for native select behavior
- [Button](../actions/Button.md) - The underlying trigger component
- [Dialog](../overlays/Dialog.md) - The popover container component
