Accordion

Accordion

Vertically stacked disclosure sections built on Base UI. Single or multiple open panels, animated height, and full keyboard support.

Playground

multiple
disabled
<Accordion className="w-96">
  <AccordionItem value="shipping">
    <AccordionTrigger>How long does shipping take?</AccordionTrigger>
    <AccordionContent>…</AccordionContent>
  </AccordionItem>
  {/* more items */}
</Accordion>

Preview

Each AccordionItem pairs an AccordionTrigger with an AccordionContent panel. The trigger swaps its chevron while expanded, and the panel animates its height open and closed.

<Accordion className="w-96" multiple={false}>
  <AccordionItem value="shipping">
    <AccordionTrigger>How long does shipping take?</AccordionTrigger>
    <AccordionContent>
      <p>Orders ship within 24 hours and arrive in 3–5 business days.</p>
    </AccordionContent>
  </AccordionItem>
  <AccordionItem value="returns">
    <AccordionTrigger>What is the return policy?</AccordionTrigger>
    <AccordionContent>
      <p>Every purchase can be returned within 30 days.</p>
    </AccordionContent>
  </AccordionItem>
</Accordion>

Installation

npx shadcn@latest add https://espresso-base-ui.vercel.app/r/accordion.json

Usage

import {
  Accordion,
  AccordionContent,
  AccordionItem,
  AccordionTrigger,
} from "@/components/ui/accordion"
<Accordion multiple={false}>
  <AccordionItem value="item-1">
    <AccordionTrigger>Question</AccordionTrigger>
    <AccordionContent>Answer</AccordionContent>
  </AccordionItem>
</Accordion>

Multiple open

Panels open independently by default (multiple is true). Pass defaultValue an array of item values to pre-expand panels; pass multiple={false} for the classic one-at-a-time accordion.

Orders ship within 24 hours and arrive in 3–5 business days. Express delivery arrives the next business day.

Every purchase can be returned within 30 days in its original condition for a full refund.

<Accordion className="w-96" defaultValue={["shipping", "returns"]}>
  {/* items */}
</Accordion>

Disabled item

Disable a single item with disabled on AccordionItem – it dims, ignores pointer input and is skipped by keyboard navigation. The same prop on the root disables the whole accordion.

<AccordionItem value="locked" disabled>
  <AccordionTrigger>Disabled question</AccordionTrigger>
  <AccordionContent>Never visible.</AccordionContent>
</AccordionItem>

API reference

Accordion forwards all Base UI accordion root props. Item values default to their index, so value is only required for controlled state or non-positional identity.

Accordion

PropTypeDefaultDescription
multiplebooleantrueWhether several panels can be open at once. false gives one-at-a-time behavior.
defaultValueany[]–Item values expanded on first render (uncontrolled).
valueany[]–Controlled list of expanded item values.
onValueChange(value: any[]) => void–Fires with the next expanded values.
disabledbooleanfalseDisables every item in the accordion.

AccordionItem

PropTypeDefaultDescription
valueany–Identity of the item within the root value array. Defaults to the item's index.
disabledbooleanfalseDisables just this item.
ComponentDescription
AccordionRoot flex column (data-slot="accordion"), owns the expanded-value state.
AccordionItemOne section (data-slot="accordion-item") with a bottom border between items.
AccordionTriggerHeader button (data-slot="accordion-trigger") with automatic up/down chevrons; wrapped in the Base UI heading element.
AccordionContentCollapsible panel (data-slot="accordion-content") animating between 0 and --accordion-panel-height.

Accessibility & styling hooks

Base UI wires the trigger and panel with aria-expanded and aria-controls, renders the trigger inside a heading, and supports Arrow keys, Home and End between triggers. State is exposed as data-open / data-closed on the panel and aria-expanded on the trigger; every part carries a data-slot attribute for styling.

Search documentation

Search the component docs