> ## Documentation Index
> Fetch the complete documentation index at: https://docs.devreadykit.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Dropdown

> A composed dropdown menu with support for single and multiple selection.

export const DropdownSkillsExamplePreview = () => <iframe src="https://kerny-custom.vercel.app/preview/DropdownSkillsExample" frameBorder="0" width="100%" height="500"></iframe>;

export const DropdownUserRoleExamplePreview = () => <iframe src="https://kerny-custom.vercel.app/preview/DropdownUserRoleExample" frameBorder="0" width="100%" height="500"></iframe>;

export const DropdownGroupedExamplePreview = () => <iframe src="https://kerny-custom.vercel.app/preview/DropdownGroupedExample" frameBorder="0" width="100%" height="500"></iframe>;

export const DropdownTagExamplePreview = () => <iframe src="https://kerny-custom.vercel.app/preview/DropdownTagExample" frameBorder="0" width="100%" height="600"></iframe>;

export const DropdownCountryExamplePreview = () => <iframe src="https://kerny-custom.vercel.app/preview/DropdownCountryExample" frameBorder="0" width="100%" height="600"></iframe>;

export const DropdownBasicExamplePreview = () => <iframe src="https://kerny-custom.vercel.app/preview/DropdownBasicExample" frameBorder="0" width="100%" height="400"></iframe>;

## Overview

The Dropdown component is built from composable pieces:

* `Dropdown.Root` manages open state, selection, and keyboard interaction.
* `Dropdown.Select` renders the trigger button with label, helper text, and icons.
* `Dropdown.Popover` and `Dropdown.Menu` display the list of options with proper focus management.
* `Dropdown.Section` groups options and can render checkbox-style multi selection.
* `Dropdown.Item` registers an option and handles selection feedback.

Combine these primitives to build controlled or uncontrolled dropdowns with single or multiple selection.

## Basic Usage

<Tabs>
  <Tab title="Code">
    ```tsx theme={null}
    import { useState } from 'react';
    import { Dropdown } from '@peppermint-design/devreadykit-custom';

    const OPTIONS = [
      { value: 'option-1', label: 'Option 1' },
      { value: 'option-2', label: 'Option 2' },
      { value: 'option-3', label: 'Option 3' },
    ];

    export default function App() {
      const [value, setValue] = useState<string | null>(null);

      return (
        <Dropdown.Root value={value} onChange={setValue} className="w-full max-w-xs">
          <Dropdown.Select
              label="Country/region"
              placeholder="Select country"
              helperText="Used for taxes and shipping."
          />
          <Dropdown.Popover>
            <Dropdown.Menu>
              <Dropdown.Section>
                {OPTIONS.map((option) => (
                  <Dropdown.Item key={option.value} value={option.value}>
                    {option.label}
                  </Dropdown.Item>
                ))}
              </Dropdown.Section>
            </Dropdown.Menu>
          </Dropdown.Popover>
        </Dropdown.Root>
      );
    }
    ```
  </Tab>

  <Tab title="Preview">
    <DropdownBasicExamplePreview />
  </Tab>
</Tabs>

## Single Selection

<Tabs>
  <Tab title="Code">
    ```tsx theme={null}
    import { useState } from 'react';
    import { Dropdown } from '@peppermint-design/devreadykit-custom';

    const COUNTRIES = [
      { value: 'us', label: 'United States' },
      { value: 'ca', label: 'Canada' },
      { value: 'uk', label: 'United Kingdom' },
      { value: 'de', label: 'Germany' },
      { value: 'fr', label: 'France' },
    ];

    export default function CountrySelector() {
      const [country, setCountry] = useState<string | null>(null);

      return (
        <Dropdown.Root value={country} onChange={setCountry} className="w-full max-w-xs">
          <Dropdown.Select label="Country" placeholder="Select country" helperText="Pick one option" />
          <Dropdown.Popover>
            <Dropdown.Menu>
              <Dropdown.Section>
                {COUNTRIES.map((item) => (
                  <Dropdown.Item key={item.value} value={item.value}>
                    {item.label}
                  </Dropdown.Item>
                ))}
              </Dropdown.Section>
            </Dropdown.Menu>
          </Dropdown.Popover>
        </Dropdown.Root>
      );
    }
    ```
  </Tab>

  <Tab title="Preview">
    <DropdownCountryExamplePreview />
  </Tab>
</Tabs>

## Multiple Selection

Use `Dropdown.Root` with `multiple` and render a `Dropdown.Section` with `variant="checkbox"` to display checkbox affordances. The trigger automatically shows the number of selected items, so render a summary elsewhere if you need labels.

<Tabs>
  <Tab title="Code">
    ```tsx theme={null}
    import { useState } from 'react';
    import { Dropdown } from '@peppermint-design/devreadykit-custom';

    const TAGS = ['React', 'Vue', 'Angular', 'Svelte', 'Solid'];

    export default function TagSelector() {
      const [tags, setTags] = useState<string[]>([]);

      return (
        <div className="space-y-3">
          <Dropdown.Root multiple value={tags} onChange={setTags} className="w-full max-w-xs">
            <Dropdown.Select label="Tags" placeholder="Select tags" helperText="Choose one or more tags" />
            <Dropdown.Popover>
              <Dropdown.Menu>
                <Dropdown.Section variant="checkbox">
                  {TAGS.map((tag) => (
                    <Dropdown.Item key={tag} value={tag}>
                      {tag}
                    </Dropdown.Item>
                  ))}
                </Dropdown.Section>
              </Dropdown.Menu>
            </Dropdown.Popover>
          </Dropdown.Root>

          {tags.length > 0 && (
            <div className="flex flex-wrap gap-2 text-sm text-neutral-40">
              {tags.map((tag) => (
                <span key={tag} className="rounded-full bg-primary-95 px-2 py-1 text-primary-50">
                  {tag}
                </span>
              ))}
            </div>
          )}
        </div>
      );
    }
    ```
  </Tab>

  <Tab title="Preview">
    <DropdownTagExamplePreview />
  </Tab>
</Tabs>

## With Groups

Render multiple `Dropdown.Section` blocks to visually separate categories. Add custom headings within a section as needed.

<Tabs>
  <Tab title="Code">
    ```tsx theme={null}
    import { useState } from 'react';
    import { Dropdown } from '@peppermint-design/devreadykit-custom';

    const CATEGORIES = {
      Frontend: [
        { value: 'react', label: 'React' },
        { value: 'vue', label: 'Vue' },
        { value: 'angular', label: 'Angular' },
      ],
      Backend: [
        { value: 'node', label: 'Node.js' },
        { value: 'python', label: 'Python' },
        { value: 'go', label: 'Go' },
      ],
      Database: [
        { value: 'postgres', label: 'PostgreSQL' },
        { value: 'mysql', label: 'MySQL' },
        { value: 'mongodb', label: 'MongoDB' },
      ],
    } as const;

    export default function GroupedDropdown() {
      const [category, setCategory] = useState<string | null>(null);

      return (
        <Dropdown.Root value={category} onChange={setCategory} className="w-full max-w-xs">
          <Dropdown.Select label="Category" placeholder="Select a category" />
          <Dropdown.Popover className="w-[260px]">
            <Dropdown.Menu>
              {Object.entries(CATEGORIES).map(([groupLabel, items]) => (
                <Dropdown.Section key={groupLabel}>
                  <p className="px-100 pb-100 text-200 font-semibold uppercase tracking-wide text-neutral-40">
                    {groupLabel}
                  </p>
                  {items.map((item) => (
                    <Dropdown.Item key={item.value} value={item.value}>
                      {item.label}
                    </Dropdown.Item>
                  ))}
                </Dropdown.Section>
              ))}
            </Dropdown.Menu>
          </Dropdown.Popover>
        </Dropdown.Root>
      );
    }
    ```
  </Tab>

  <Tab title="Preview">
    <DropdownGroupedExamplePreview />
  </Tab>
</Tabs>

## Props

| Component | Prop         | Type                                                                                      | Default     | Description                                                        |
| :-------- | :----------- | :---------------------------------------------------------------------------------------- | :---------- | :----------------------------------------------------------------- |
| Root      | value        | `string \| number \| (string \| number)[] \| null`                                        | —           | Controlled selected value(s); pass an array when `multiple` is set |
| Root      | defaultValue | `string \| number \| (string \| number)[] \| null`                                        | —           | Uncontrolled initial value(s)                                      |
| Root      | onChange     | `(value: string \| number \| null) => void` \|\| `(values: (string \| number)[]) => void` | —           | Fired when the selection changes; signature depends on `multiple`  |
| Root      | multiple     | `boolean`                                                                                 | `false`     | Enables multiple selection mode                                    |
| Root      | className    | `string`                                                                                  | —           | Applies custom classes to the wrapper                              |
| Select    | label        | `React.ReactNode`                                                                         | —           | Optional field label rendered above the trigger                    |
| Select    | required     | `boolean`                                                                                 | `false`     | Shows an asterisk next to the label                                |
| Select    | placeholder  | `string`                                                                                  | `"Select"`  | Placeholder text when nothing is selected                          |
| Select    | startIcon    | `React.ReactNode`                                                                         | —           | Icon displayed on the left of the trigger                          |
| Select    | helperText   | `React.ReactNode`                                                                         | —           | Helper text shown below the trigger                                |
| Select    | errorMessage | `React.ReactNode`                                                                         | —           | Error text shown below the trigger with error styling              |
| Select    | className    | `string`                                                                                  | —           | Additional classes for the trigger button                          |
| Popover   | className    | `string`                                                                                  | —           | Styles for the popover container                                   |
| Popover   | children     | `React.ReactNode`                                                                         | —           | Popover contents, usually a `Dropdown.Menu`                        |
| Menu      | className    | `string`                                                                                  | —           | Styles for the menu surface                                        |
| Menu      | maxHeight    | `number`                                                                                  | `320`       | Sets the max height before the menu scrolls                        |
| Menu      | children     | `React.ReactNode`                                                                         | —           | Menu sections and other content                                    |
| Section   | className    | `string`                                                                                  | —           | Adds spacing or borders around a section                           |
| Section   | variant      | `"default" \| "checkbox"`                                                                 | `"default"` | Renders checkbox visuals when set to `"checkbox"`                  |
| Section   | children     | `React.ReactNode`                                                                         | —           | Section content such as `Dropdown.Item` elements                   |
| Item      | value        | `string \| number`                                                                        | —           | Value emitted on selection; defaults to the text content           |
| Item      | disabled     | `boolean`                                                                                 | `false`     | Disables the option                                                |
| Item      | startIcon    | `React.ReactNode`                                                                         | —           | Optional leading icon when `variant="default"`                     |
| Item      | className    | `string`                                                                                  | —           | Custom classes for the option                                      |
| Item      | children     | `React.ReactNode`                                                                         | —           | Option label/content                                               |

## Examples

### Multi-Select with Custom Display

<Tabs>
  <Tab title="Code">
    ```tsx theme={null}
    import { useState } from 'react';
    import { Dropdown } from '@peppermint-design/devreadykit-custom';

    const skills = ['JavaScript', 'TypeScript', 'React', 'Node.js', 'Python', 'Go'];

    export default function SkillsSelector() {
      const [selected, setSelected] = useState<string[]>([]);

      return (
        <div className="space-y-3">
          <label className="block text-sm font-medium text-neutral-40">Skills</label>

          <Dropdown.Root multiple value={selected} onChange={setSelected} className="w-full max-w-xs">
            <Dropdown.Select placeholder="Select skills" helperText="Pick the technologies you work with" />
            <Dropdown.Popover>
              <Dropdown.Menu>
                <Dropdown.Section variant="checkbox">
                  {skills.map((skill) => (
                    <Dropdown.Item key={skill} value={skill}>
                      {skill}
                    </Dropdown.Item>
                  ))}
                </Dropdown.Section>
              </Dropdown.Menu>
            </Dropdown.Popover>
          </Dropdown.Root>

          {selected.length > 0 && (
            <div className="flex flex-wrap gap-2 text-sm text-neutral-40">
              {selected.map((skill) => (
                <span key={skill} className="inline-flex items-center gap-1 rounded-full bg-primary-95 px-2 py-1 text-primary-50">
                  {skill}
                </span>
              ))}
            </div>
          )}
        </div>
      );
    }
    ```
  </Tab>

  <Tab title="Preview">
    <DropdownSkillsExamplePreview />
  </Tab>
</Tabs>
