# DropdownButton

> Slug: `dropdown-button` · Category: Actions

## When to use
- Trigger the "selecting" variant of `MenuDropdown` — the visible control that opens a listbox-style menu and reflects the current selection.
- Implement a single-select or multi-select picker with form-field appearance.

## When NOT to use
- Native form selection — use `Select` (uses native `<select>` semantics with floating label).
- Free-text input — use `TextField`.
- Plain action menu (not a value picker) — use `MenuButton`.
- Standalone outside a `MenuDropdown` composition — this component requires `labelId` and `menuId` wiring.

## Variants & decision tree
- One selected value rendered inside the trigger -> `behavior="single"` (default).
- Many selections shown as a leading badge count ("3, items selected") -> `behavior="multi"`.

## States
- `isExpanded` -> drives `aria-expanded`. Toggle from your `MenuDropdown` controller.
- `disabled` -> `aria-disabled` (focusable).
- `isInvalid` -> `aria-invalid="true"` for form validation.
- `focused` -> force-focus class for design review.
- Inverse via theme or `inverse` prop.

## Props
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| **`id`** | `string` | — | Unique id; multi-select derives `${id}-selected-items-badge`. |
| **`labelId`** | `string` | — | id of the label element (`aria-labelledby`). |
| **`menuId`** | `string` | — | id of the controlled menu (`aria-controls`). |
| `behavior` | `'single' \| 'multi'` | `'single'` | Selection model. |
| `isExpanded` | `boolean` | `false` | Whether the menu is open. |
| `selectedItems` | `{ id, text }[]` | `[]` | Selected items; single shows `[0].text`, multi shows count. |
| `disabled` | `boolean` | — | Sets `aria-disabled`. |
| `isInvalid` | `boolean` | — | Sets `aria-invalid`. |
| `describedBy` | `string` | — | Extra `aria-describedby` (multi prepends the badge id). |
| `inverse` | `boolean` | inherits | Dark-background styling. |

## Usage examples
```tsx
import { useState } from 'react';
import { DropdownButton } from 'arrow-react-bootstrap';

// Single select trigger
const [open, setOpen] = useState(false);
<label id="size-label">Size</label>
<DropdownButton
  id="size-trigger"
  labelId="size-label"
  menuId="size-menu"
  isExpanded={open}
  selectedItems={[{ id: 'm', text: 'Medium' }]}
  onClick={() => setOpen(o => !o)}
/>

// Multi-select with count badge
<DropdownButton
  id="filters"
  behavior="multi"
  labelId="filters-label"
  menuId="filters-menu"
  isExpanded={open}
  selectedItems={[{ id: 'a', text: 'A' }, { id: 'b', text: 'B' }, { id: 'c', text: 'C' }]}
/>
```

## Composition
- Always pair with `MenuDropdown` (provides the `<ul role="listbox">`).
- Bind keyboard handling and outside-click via the `useMenuDropdown` hook in your controller.

## Accessibility
- Renders a `<button role="combobox">` with `aria-haspopup="listbox"`.
- Requires `labelId` (no inline `aria-label` is set by default).
- `aria-expanded`, `aria-controls`, `aria-describedby` are wired from props.

## Do / Don't
- Do: use within a controlled `MenuDropdown` composition.
- Do: keep `id`, `labelId`, `menuId` distinct and stable.
- Don't: pass children; the visible value is derived from `selectedItems`.
- Don't: use as a generic action button — use `Button` or `MenuButton`.
