---
title: Accordion
description: A set of collapsible panels with headings.
links:
  doc: https://base-ui.com/react/components/accordion
  api: https://base-ui.com/react/components/accordion#api-reference
---

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

type AccordionItem = {
  id: string;
  title: string;
  content: string;
};

export const accordionItems: AccordionItem[] = [
  {
    id: 'item-1',
    title: 'What is your return policy?',
    content:
      "We accept returns within 30 days of purchase, provided the item is unused and in its original condition. To start a return, you'll need your order number and the email address used at checkout. Once your return is approved, we'll send you instructions along with a prepaid return label (where applicable). Refunds are typically processed within 5-7 business days after the item is received.",
  },
  {
    id: 'item-2',
    title: 'How long does shipping take?',
    content:
      "Shipping times depend on your location and the shipping method selected at checkout. Standard shipping usually takes 3-5 business days, while express shipping can arrive in 1-2 business days. You'll receive a tracking link as soon as your order ships, so you can monitor delivery progress. Please note that delays may occur during peak periods or due to customs processing for international orders.",
  },
  {
    id: 'item-3',
    title: 'Do you offer customer support?',
    content:
      'Yes, our customer support team is here to help. You can reach us Monday through Friday from 9am to 5pm via email or live chat. We aim to respond to all inquiries within 24 hours, and often much sooner. For faster service, include your order number and a brief description of the issue so we can resolve it as quickly as possible.',
  },
];

export function AccordionDemo() {
  return (
    <Accordion className='w-full'>
      {accordionItems.map((accordionItem) => {
        return (
          <AccordionItem key={accordionItem.id} value={accordionItem.id}>
            <AccordionTrigger>{accordionItem.title}</AccordionTrigger>
            <AccordionContent>{accordionItem.content}</AccordionContent>
          </AccordionItem>
        );
      })}
    </Accordion>
  );
}
```

## Installation

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

**Install the following dependencies:**

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

**Copy and paste the following code into your project.**

```tsx
'use client';

import { Accordion as AccordionPrimitive } from '@base-ui/react/accordion';
import { PlusIcon } from 'lucide-react';

import { cn } from '@/lib/utils';

function Accordion({ className, ...props }: AccordionPrimitive.Root.Props) {
  return (
    <AccordionPrimitive.Root
      data-slot='accordion'
      className={cn('flex w-full flex-col', className)}
      {...props}
    />
  );
}

function AccordionItem({ className, ...props }: AccordionPrimitive.Item.Props) {
  return (
    <AccordionPrimitive.Item
      data-slot='accordion-item'
      className={cn('not-last:border-b', className)}
      {...props}
    />
  );
}

function AccordionTrigger({
  className,
  children,
  ...props
}: AccordionPrimitive.Trigger.Props) {
  return (
    <AccordionPrimitive.Header className='mt-0 mb-0 flex py-4'>
      <AccordionPrimitive.Trigger
        className={cn(
          'group/accordion-trigger relative flex flex-1 cursor-pointer items-start justify-between gap-4 rounded-md border border-transparent text-left text-sm font-medium transition-all outline-none hover:underline focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:after:border-ring disabled:pointer-events-none disabled:opacity-64 **:data-[slot=accordion-trigger-icon]:ml-auto **:data-[slot=accordion-trigger-icon]:size-4 **:data-[slot=accordion-trigger-icon]:text-muted-foreground [&[data-panel-open]>svg]:rotate-45',
          className
        )}
        data-slot='accordion-trigger'
        {...props}
      >
        {children}
        <PlusIcon className='pointer-events-none size-4 shrink-0 translate-y-0.5 opacity-72 transition-transform duration-150 ease-out' />
      </AccordionPrimitive.Trigger>
    </AccordionPrimitive.Header>
  );
}

function AccordionContent({
  className,
  children,
  ...props
}: AccordionPrimitive.Panel.Props) {
  return (
    <AccordionPrimitive.Panel
      className='h-(--accordion-panel-height) overflow-hidden text-sm text-muted-foreground transition-[height] duration-150 ease-out data-ending-style:h-0 data-starting-style:h-0'
      data-slot='accordion-panel'
      {...props}
    >
      <div className={cn('pt-0 pb-4', className)}>{children}</div>
    </AccordionPrimitive.Panel>
  );
}

export { Accordion, AccordionItem, AccordionTrigger, AccordionContent };
```

**Update the import paths to match your project setup.**

## Usage

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

```tsx
<Accordion>
  <AccordionItem value="item-1">
    <AccordionTrigger>Is it accessible?</AccordionTrigger>
    <AccordionPanel>
      Yes. It adheres to the WAI-ARIA design pattern.
    </AccordionPanel>
  </AccordionItem>
</Accordion>
```
