# Accordion

Vertically stacked headings that each reveal a section of content.

Source: [accordion.tsx](https://github.com/jakejarvis/jarvis-ui/blob/main/src/components/ui/accordion.tsx)

```tsx
import {
  Accordion,
  AccordionContent,
  AccordionItem,
  AccordionTrigger,
} from "@/components/ui/accordion";

export default function AccordionBasic() {
  return (
    <Accordion defaultValue={["billing"]} className="max-w-md">
      <AccordionItem value="billing">
        <AccordionTrigger>How does billing work?</AccordionTrigger>
        <AccordionContent>
          <p>You’re billed monthly for each member. Invoices are emailed on the 1st.</p>
          <p>
            You can download past invoices from <a href="#billing-settings">Billing settings</a>.
          </p>
        </AccordionContent>
      </AccordionItem>
      <AccordionItem value="members">
        <AccordionTrigger>Can I invite people outside my company?</AccordionTrigger>
        <AccordionContent>
          Yes. Guests can view and comment on the projects you share with them.
        </AccordionContent>
      </AccordionItem>
      <AccordionItem value="export">
        <AccordionTrigger>How do I export my data?</AccordionTrigger>
        <AccordionContent>
          Open Settings, then Export, and choose CSV or JSON. Large exports are emailed to you.
        </AccordionContent>
      </AccordionItem>
    </Accordion>
  );
}
```

## Installation

Add the registry, once per project:

```bash
npx shadcn@latest registry add @jarvis=https://ui.jarv.is/r/{name}.json
```

Then add the component:

```bash
npx shadcn@latest add @jarvis/accordion
```

## Usage

```tsx
import {
  Accordion,
  AccordionContent,
  AccordionItem,
  AccordionTrigger,
} from "@/components/ui/accordion";

export function Faq() {
  return (
    <Accordion>
      <AccordionItem value="billing">
        <AccordionTrigger>How does billing work?</AccordionTrigger>
        <AccordionContent>You’re billed monthly for each member.</AccordionContent>
      </AccordionItem>
      <AccordionItem value="export">
        <AccordionTrigger>How do I export my data?</AccordionTrigger>
        <AccordionContent>Open Settings, then Export, and choose CSV or JSON.</AccordionContent>
      </AccordionItem>
    </Accordion>
  );
}
```

Give each item a `value` to open it with `defaultValue`, or control the open items with `value`
and `onValueChange`.

## Composition

- `Accordion`
  - `AccordionItem`
    - `AccordionTrigger`
    - `AccordionContent`

## Examples

### Multiple

Opening one section closes the others unless you set `multiple`.

```tsx
import {
  Accordion,
  AccordionContent,
  AccordionItem,
  AccordionTrigger,
} from "@/components/ui/accordion";

export default function AccordionMultiple() {
  return (
    <Accordion multiple defaultValue={["notifications", "appearance"]} className="max-w-md">
      <AccordionItem value="notifications">
        <AccordionTrigger>Notifications</AccordionTrigger>
        <AccordionContent>
          Email for mentions and assignments, push for everything else.
        </AccordionContent>
      </AccordionItem>
      <AccordionItem value="appearance">
        <AccordionTrigger>Appearance</AccordionTrigger>
        <AccordionContent>Match the system theme, with compact density.</AccordionContent>
      </AccordionItem>
      <AccordionItem value="language">
        <AccordionTrigger>Language</AccordionTrigger>
        <AccordionContent>English (United States).</AccordionContent>
      </AccordionItem>
    </Accordion>
  );
}
```

### Disabled item

```tsx
import {
  Accordion,
  AccordionContent,
  AccordionItem,
  AccordionTrigger,
} from "@/components/ui/accordion";

export default function AccordionDisabled() {
  return (
    <Accordion className="max-w-md">
      <AccordionItem value="plans">
        <AccordionTrigger>Which plan is right for me?</AccordionTrigger>
        <AccordionContent>
          Start on the free plan, and upgrade when you need more members or storage.
        </AccordionContent>
      </AccordionItem>
      <AccordionItem value="sso" disabled>
        <AccordionTrigger>Do you support single sign-on?</AccordionTrigger>
        <AccordionContent>Single sign-on is available on the Enterprise plan.</AccordionContent>
      </AccordionItem>
    </Accordion>
  );
}
```

## Props

| Part | Extends |
| --- | --- |
| `Accordion` | [`Accordion.Root`](https://base-ui.com/react/components/accordion#root) |
| `AccordionItem` | [`Accordion.Item`](https://base-ui.com/react/components/accordion#item) |
| `AccordionTrigger` | [`Accordion.Trigger`](https://base-ui.com/react/components/accordion#trigger) |
| `AccordionContent` | [`Accordion.Panel`](https://base-ui.com/react/components/accordion#panel) |

The tables leave out `className`, `style` and `render`. Parts built on Base UI take them as its [styling](https://base-ui.com/react/handbook/styling) and [composition](https://base-ui.com/react/handbook/composition) guides describe.

### Accordion

| Prop                | Type                                                                                    | Description                                                                                                                                                                                                              |
| ------------------- | --------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `value?`            | `AccordionValue<any>`                                                                   | The controlled value of the item(s) that should be expanded. To render an uncontrolled accordion, use the `defaultValue` prop instead.                                                                                   |
| `defaultValue?`     | `AccordionValue<any>`                                                                   | The uncontrolled value of the item(s) that should be initially expanded. To render a controlled accordion, use the `value` prop instead.                                                                                 |
| `disabled?`         | `boolean`                                                                               | Whether the component should ignore user interaction. Default: `false`                                                                                                                                                   |
| `hiddenUntilFound?` | `boolean`                                                                               | Allows the browser's built-in page search to find and expand the panel contents. Overrides the `keepMounted` prop and uses `hidden="until-found"` to hide the element without removing it from the DOM. Default: `false` |
| `keepMounted?`      | `boolean`                                                                               | Whether to keep the element in the DOM while the panel is closed. This prop is ignored when `hiddenUntilFound` is used. Default: `false`                                                                                 |
| `loopFocus?`        | `boolean`                                                                               | **Deprecated.** Deprecated following the [APG guidance update](https://github.com/w3c/aria-practices/pull/3434) to remove roving focus. This prop no longer affects keyboard focus behavior.                             |
| `onValueChange?`    | `((value: AccordionValue<any>, eventDetails: AccordionRootChangeEventDetails) => void)` | Event handler called when an accordion item is expanded or collapsed. Provides the new value as an argument.                                                                                                             |
| `multiple?`         | `boolean`                                                                               | Whether multiple items can be open at the same time. Default: `false`                                                                                                                                                    |
| `orientation?`      | `"horizontal" \| "vertical"`                                                            | **Deprecated.** Deprecated following the [APG guidance update](https://github.com/w3c/aria-practices/pull/3434) to remove roving focus. This prop no longer affects keyboard focus behavior. Default: `'vertical'`       |

### AccordionItem

| Prop            | Type                                                                         | Description                                                                                                                                                                                                     |
| --------------- | ---------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `value?`        | `any`                                                                        | A unique value that identifies this accordion item. If no value is provided, a unique ID will be generated automatically. Use when controlling the accordion programmatically, or to set an initial open state. |
| `onOpenChange?` | `((open: boolean, eventDetails: Accordion.Item.ChangeEventDetails) => void)` | Event handler called when the panel is opened or closed.                                                                                                                                                        |
| `disabled?`     | `boolean`                                                                    | Whether the component should ignore user interaction. Default: `false`                                                                                                                                          |

### AccordionTrigger

| Prop            | Type      | Description                                                                                                                                                                                       |
| --------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `nativeButton?` | `boolean` | Whether the component renders a native `<button>` element when replacing it via the `render` prop. Set to `false` if the rendered element is not a button (for example, `<div>`). Default: `true` |

### AccordionContent

| Prop                | Type      | Description                                                                                                                                                                                                              |
| ------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `hiddenUntilFound?` | `boolean` | Allows the browser's built-in page search to find and expand the panel contents. Overrides the `keepMounted` prop and uses `hidden="until-found"` to hide the element without removing it from the DOM. Default: `false` |
| `keepMounted?`      | `boolean` | Whether to keep the element in the DOM while the panel is closed. This prop is ignored when `hiddenUntilFound` is used. Default: `false`                                                                                 |
