# Accordion
URL: /design/components/accordion

Stacked headings that reveal or hide content sections.

> For AI agents: a documentation index is available at [llms.txt](/llms.txt). Use `.md` for canonical markdown pages; `.mdx` is kept as a backwards-compatible alias on supported URL paths.

\[interactive preview omitted]

## Installation

With the style-aware registry configured in components.json ("@assistant-ui": "https\://r.assistant-ui.com/styles/{style}/{name}.json"), the flavor resolves from the project style automatically:

```bash
npx shadcn@latest add @assistant-ui/accordion
```

Or add by direct URL without registry configuration:

```bash
npx shadcn@latest add https://r.assistant-ui.com/base/accordion.json
```

Or install manually:

```bash
npm install @base-ui/react
```

Then copy these files (packaged registry content; the source links show where each ships from):

- [components/ui/accordion.tsx](https://r.assistant-ui.com/base/files/accordion/components/ui/accordion.tsx) ([source](https://github.com/assistant-ui/assistant-ui/blob/main/packages/ui/src/components/react/ui/base/accordion.tsx))

```bash
curl -fsSL --create-dirs \
  -o 'components/ui/accordion.tsx' https://r.assistant-ui.com/base/files/accordion/components/ui/accordion.tsx
```

## Usage

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

export function Example() {
  return (
    <Accordion defaultValue={["item-1"]}>
      <AccordionItem value="item-1">
        <AccordionTrigger>Section 1</AccordionTrigger>
        <AccordionContent>Content for section 1.</AccordionContent>
      </AccordionItem>
      <AccordionItem value="item-2">
        <AccordionTrigger>Section 2</AccordionTrigger>
        <AccordionContent>Content for section 2.</AccordionContent>
      </AccordionItem>
    </Accordion>
  );
}
```

Base UI represents the open value as an array and uses the `multiple` prop. Radix uses `type="single"` or `type="multiple"` and represents a single open value as a string.

## Examples

### Multiple items open

\[interactive preview omitted]

### With icons

Add icons or custom content inside the trigger.

\[interactive preview component AccordionWithIconsSample omitted]

Code for AccordionWithIconsSample preview:

```tsx
"use client";

import { CreditCard, HelpCircle, Settings, User } from "lucide-react";
import {
  Accordion,
  AccordionContent,
  AccordionItem,
  AccordionTrigger,
} from "@/components/ui/accordion";

function AccordionWithIconsSample() {
  return (
    <Accordion className="w-[400px]">
      <AccordionItem value="account">
        <AccordionTrigger>
          <span className="flex items-center gap-2">
            <User className="size-4" />
            Account settings
          </span>
        </AccordionTrigger>
        <AccordionContent>
          Manage your account details, profile picture, and personal
          information.
        </AccordionContent>
      </AccordionItem>
      <AccordionItem value="billing">
        <AccordionTrigger>
          <span className="flex items-center gap-2">
            <CreditCard className="size-4" />
            Billing
          </span>
        </AccordionTrigger>
        <AccordionContent>
          View your billing history, manage payment methods, and update your
          subscription.
        </AccordionContent>
      </AccordionItem>
      <AccordionItem value="preferences">
        <AccordionTrigger>
          <span className="flex items-center gap-2">
            <Settings className="size-4" />
            Preferences
          </span>
        </AccordionTrigger>
        <AccordionContent>
          Customize your experience with notification and display settings.
        </AccordionContent>
      </AccordionItem>
    </Accordion>
  );
}
```

### Controlled

Use `value` and `onValueChange` for controlled accordion state.

\[interactive preview component AccordionControlledSample omitted]

Code for AccordionControlledSample preview:

```tsx
"use client";

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

function AccordionControlledSample() {
  const [value, setValue] = useState(["item-1"]);

  return (
    <Accordion value={value} onValueChange={setValue} className="w-[400px]">
      <AccordionItem value="item-1">
        <AccordionTrigger>Overview</AccordionTrigger>
        <AccordionContent>
          This is the overview section content.
        </AccordionContent>
      </AccordionItem>
      <AccordionItem value="item-2">
        <AccordionTrigger>Details</AccordionTrigger>
        <AccordionContent>
          This is the details section content.
        </AccordionContent>
      </AccordionItem>
      <AccordionItem value="item-3">
        <AccordionTrigger>Advanced</AccordionTrigger>
        <AccordionContent>
          This is the advanced section content.
        </AccordionContent>
      </AccordionItem>
    </Accordion>
    <p className="text-muted-foreground text-sm">
      Current value: <code className="font-mono">{value[0] ?? "none"}</code>
    </p>
  );
}
```

### FAQ section

\[interactive preview component AccordionFAQSample omitted]

Code for AccordionFAQSample preview:

```tsx
"use client";

import { CreditCard, HelpCircle, Settings, User } from "lucide-react";
import {
  Accordion,
  AccordionContent,
  AccordionItem,
  AccordionTrigger,
} from "@/components/ui/accordion";

function AccordionFAQSample() {
  return (
    <div className="w-[500px]">
      <div className="mb-4 flex items-center gap-2">
        <HelpCircle className="size-5" />
        <h3 className="text-lg font-semibold">Frequently asked questions</h3>
      </div>
      <Accordion>
        <AccordionItem value="faq-1">
          <AccordionTrigger>
            What payment methods do you accept?
          </AccordionTrigger>
          <AccordionContent>
            We accept all major credit cards, PayPal, and bank transfers for
            annual subscriptions.
          </AccordionContent>
        </AccordionItem>
        <AccordionItem value="faq-2">
          <AccordionTrigger>
            Can I cancel my subscription anytime?
          </AccordionTrigger>
          <AccordionContent>
            Yes. Your access continues until the end of the current billing
            period.
          </AccordionContent>
        </AccordionItem>
        <AccordionItem value="faq-3">
          <AccordionTrigger>Do you offer refunds?</AccordionTrigger>
          <AccordionContent>
            We offer a 30-day money-back guarantee for new subscriptions.
          </AccordionContent>
        </AccordionItem>
      </Accordion>
    </div>
  );
}
```

## API Reference

### Composable API

| Component          | Description                                 |
| ------------------ | ------------------------------------------- |
| `Accordion`        | The root component that manages open items. |
| `AccordionItem`    | A collapsible section container.            |
| `AccordionTrigger` | The control that toggles a section.         |
| `AccordionContent` | The collapsible content panel.              |

### Accordion

- `defaultValue?`: `string[] | string` — The initial open value. Base UI uses an array; single-value Radix accordions use a string.
- `value?`: `string[] | string` — The controlled open value for the selected flavor.
- `onValueChange?`: `(value: string[] | string) => void` — Called when the open items change.
- `multiple`: `boolean` (default `false`) — Base UI: whether multiple items can be open.
- `type?`: `"single" | "multiple"` — Radix: whether one or multiple items can be open.
- `collapsible?`: `boolean` — Radix single mode: whether the open item can close.
- `className?`: `string` — Additional CSS classes.

### AccordionItem

- `value`: `string` — The unique value for the item.
- `disabled?`: `boolean` — Whether the item is disabled.
- `className?`: `string` — Additional CSS classes.

### AccordionTrigger

- `className?`: `string` — Additional CSS classes.

### AccordionContent

- `className?`: `string` — Additional CSS classes for the panel content.