<!-- Generated by scripts/gen-docs.mts from the JSDoc in registry/. Do not edit; run `pnpm run docs`. -->

# Accordion

A stack of titles that each open their own content, for FAQs and long settings pages. One item opens at a time unless you pass `multiple`. Panels grow to their measured height with CSS, titles sit inside headings, closed content is in the server HTML and found by the page search of browsers that support `hidden="until-found"`, and rows are 44px tall on touch screens.

```tsx
import { Accordion } from "@/components/ouro/accordion/accordion";
```

## Example

```tsx
<Accordion
  items={[
    { value: "storage", title: "How long does it keep?", content: "Three days in the fridge." },
    { value: "freeze", title: "Can I freeze it?", content: "Yes, for up to a month." },
  ]}
/>
<Accordion multiple defaultValue={["storage"]} items={items} />
```

## Use instead when

- Use `Collapsible` instead for a single section that opens and closes.
- Use `Tabs` instead when exactly one section always shows and the titles fit in a row.

## Props

The props the modes share. Type: `AccordionProps`.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `className` | `string` |  | Layout only: margins, width, grid placement (`mt-6`). Appearance classes warn in development. |
| `disabled` | `boolean` |  | Keeps every item from opening or closing. |
| `headingLevel` | `2 \| 3 \| 4 \| 5 \| 6` | `3` | The outline level of each title, so the items sit in the page's heading structure: `headingLevel={2}` renders `<h2>`. |
| `items` (required) | `readonly AccordionItem[]` |  | The items, in order. |
| `ref` | `Ref<HTMLDivElement>` |  | Reaches the rendered element. |

## Modes

`AccordionProps` is a union: pass the props of exactly one mode. Mixing them is a type error.

### Multiple: `AccordionMultipleProps`

Several items open at once. The value is the list of open items.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `defaultValue` | `readonly string[]` | [] | The items open first, when the component keeps its own state. |
| `multiple` (required) | `true` |  | Lets several items be open at once, and makes the value a list. |
| `onValueChange` | `((value: string[]) => void)` |  | Called with the open items' values whenever one opens or closes. |
| `value` | `readonly string[]` |  | The open items' values, when you control them. Pair it with `onValueChange`. |

### Single: `AccordionSingleProps`

One item open at a time (the default). The value is the open item's, or `null` when all are closed.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `defaultValue` | `string \| null` | none | The item open first, when the component keeps its own state. |
| `multiple` | `false` |  | Lets several items be open at once, and makes the value a list. |
| `onValueChange` | `((value: string \| null) => void)` |  | Called with the open item's value, or `null` when the person closes it. |
| `value` | `string \| null` |  | The open item's value, or `null` for none, when you control it. Pair it with `onValueChange`. |

## Don't use

These are not props. Passing one fails the type check with the fix in the error, and in development a console message names the fix.

- `collapsible`: Not a prop. An open item always closes when its title is pressed again.
- `onChange`: Not a prop. Ouro UI uses `onValueChange`: `<Accordion onValueChange={(value) => …}>`.
- `type`: Not a prop. One item opens at a time by default; for several, pass `multiple`: `<Accordion multiple>`.

## `className` is for layout only

Pass margins, width and grid placement (`mt-4`, `w-full`, `col-span-2`). Your classes always win over Ouro UI's: Accordion merges `className` last with `cn` (tailwind-merge), so a class that conflicts with its own replaces it.[^layout-classes]

Appearance comes from props, not classes. In development, a class that sets appearance logs one warning per component instance, naming the prop to use instead. A class sets appearance when, after its variants (`hover:`, `sm:`) and any `!` are removed, it starts with `bg-`, `text-`, `border-`, `rounded-`, `shadow-`, `font-`, `ring-`, `from-`, `via-`, `to-`, `fill-` or `stroke-`, or is `border`, `rounded`, `shadow` or `ring`, or has a `dark:` variant. Text wrapping, overflow and table layout classes (`text-wrap`, `text-ellipsis`, `border-collapse`) are layout and do not warn.

Alignment classes (`text-center`) warn too: set alignment on a parent element.

## Types

### `AccordionItem`

One item: a title that opens and closes its content.

```ts
interface AccordionItem {
  /**
   * Identifies the item: `value`, `defaultValue` and `onValueChange` use it. Unique within the
   * accordion. @default the item's index, as a string ("0", "1", …)
   */
  value?: string | undefined;
  /**
   * The title, always visible. It is the button that opens the item, inside a heading.
   */
  title: ReactNode;
  /** What shows while the item is open. */
  content: ReactNode;
  /** Shows the item but keeps it from opening or closing. */
  disabled?: boolean | undefined;
}
```

[^layout-classes]: test:registry/ouro/components/ouro/accordion/accordion.test.tsx::Accordion > lets app layout classes win verify:testExists(registry/ouro/components/ouro/accordion/accordion.test.tsx::Accordion > lets app layout classes win)
