# Accordion

An accessible React accordion for Next.js: sections that open and close with a smooth height change, as one card, separate cards or plain rows. Built on Radix.

Source: https://ui.fewtone.com/components/accordion

## Installation

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

## Usage

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

export function Faq() {
  return (
    <Accordion type="single" collapsible>
      <AccordionItem value="refunds">
        <AccordionTrigger>Can I get a refund?</AccordionTrigger>
        <AccordionContent>Yes, within 30 days of your purchase.</AccordionContent>
      </AccordionItem>
      <AccordionItem value="shipping">
        <AccordionTrigger>How long does shipping take?</AccordionTrigger>
        <AccordionContent>Three to five working days.</AccordionContent>
      </AccordionItem>
    </Accordion>
  )
}
```

## API reference

### Accordion

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `variant` | `"card" \| "separated" \| "plain"` | `"card"` | Card is one surface with a rule between sections. Separated makes each section its own card, and an open one moves apart from the rest. Plain is rows and rules only, for inside a surface that's already a card. |
| `type` | `"single" \| "multiple"` | – | Single opens one section at a time; multiple lets each open on its own. |
| `value` | `string \| string[]` | – | The open section (single) or sections (multiple), when you control them. |
| `defaultValue` | `string \| string[]` | – | The section or sections open at first. |
| `onValueChange` | `(value: string) => void \| (value: string[]) => void` | – | Called when a section opens or closes. Single sends an empty string once it's closed. |
| `collapsible` | `boolean` | `false` | Single only: the open section closes when its question is pressed again. |
| `disabled` | `boolean` | `false` | Prevents opening or closing any section. |

### AccordionItem

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `value` | `string` | – | Names the section in the accordion's value. |
| `disabled` | `boolean` | `false` | Prevents opening or closing it. |

### AccordionTrigger

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `children` | `ReactNode` | – | The question. |

### AccordionContent

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `className` | `string` | – | Applies to the inner block, so padding and text styles never fight the height animation. |

**When to use it:** Use Accordion for FAQs and long pages split into sections people scan and open one by one. Use type="multiple" when sections are independent. Card is the default; separated suits a few large sections, and plain goes inside a surface that is already a card (a Card, Sheet or Dialog). Use Tabs when one panel at a time should show in the same place, and don't hide content people need to compare side by side.
**Built on:** Radix Accordion.
**Accessibility pattern:** https://www.w3.org/WAI/ARIA/apg/patterns/accordion/
**npm packages (installed by the CLI):** class-variance-authority@^0.7.1, lucide-react@^1.52.0, motion@^14.0.0, radix-ui@^1.7.0.

## Examples

### Card, separated and plain

One section open at a time. It glides open as its answer sharpens in and the chevron turns; separated sections also move apart from their neighbours.

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

const variants: { variant: AccordionVariant; label: string }[] = [
  { variant: "card", label: "Card" },
  { variant: "separated", label: "Separated" },
  { variant: "plain", label: "Plain" },
];

const questions = [
  {
    value: "accessible",
    question: "Is it accessible?",
    answer: "Yes. It follows the WAI-ARIA accordion pattern.",
  },
  {
    value: "nextjs",
    question: "Does it work with Next.js?",
    answer: "Yes, server components included.",
  },
  {
    value: "style",
    question: "Can I restyle it?",
    answer: "Yes. It's your code, styled with Tailwind CSS.",
  },
];

/*
 * The three looks side by side, named underneath, the first section open in each. Each one hangs from the top
 * of a box as tall as its tallest state (any section open, two-line answers), so opening and closing never
 * changes the preview's height or moves the labels.
 */
export default function AccordionVariants() {
  return (
    <ul className="flex w-full flex-wrap items-start justify-center gap-8">
      {variants.map(({ variant, label }) => (
        <li key={variant} className="flex w-64 flex-col gap-4">
          <div className="min-h-64">
            <Accordion type="single" collapsible defaultValue="accessible" variant={variant}>
              {questions.map(({ value, question, answer }) => (
                <AccordionItem key={value} value={value}>
                  <AccordionTrigger>{question}</AccordionTrigger>
                  <AccordionContent>{answer}</AccordionContent>
                </AccordionItem>
              ))}
            </Accordion>
          </div>
          <span className="text-center text-xs text-muted-foreground">{label}</span>
        </li>
      ))}
    </ul>
  );
}
```

### Several open at once

With type="multiple", each section opens and closes on its own.

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

/**
 * Each section opens and closes on its own. The box is as tall as all three open, so the preview never
 * changes height.
 */
export default function AccordionMultiple() {
  return (
    <div className="min-h-72 w-full max-w-md">
      <Accordion type="multiple" defaultValue={["shipping"]}>
        <AccordionItem value="shipping">
          <AccordionTrigger>Shipping</AccordionTrigger>
          <AccordionContent>Orders arrive in three to five working days.</AccordionContent>
        </AccordionItem>
        <AccordionItem value="returns">
          <AccordionTrigger>Returns</AccordionTrigger>
          <AccordionContent>Send it back within 30 days for a full refund.</AccordionContent>
        </AccordionItem>
        <AccordionItem value="warranty">
          <AccordionTrigger>Warranty</AccordionTrigger>
          <AccordionContent>Two years on every part, with free repairs.</AccordionContent>
        </AccordionItem>
      </Accordion>
    </div>
  );
}
```

## Related

- [Tabs](https://ui.fewtone.com/components/tabs.md): Accessible React tabs for Next.js, with an underline or pill that slides to the active tab and panels that glide in, built on Radix Tabs.
