Skip to content

Navigation

Accordion

A stack of expandable answers.

When to use it: Use it to hide optional detail while keeping headings visible.

On this page

Example

Orders leave our warehouse in two business days.

Accordion.tsxtsx
import {
  Accordion,
  AccordionHeader,
  AccordionItem,
  AccordionPanel,
  AccordionTrigger,
} from "@comp0/react";
import { ChevronDownIcon } from "@heroicons/react/16/solid";

export function Example() {
  return (
    <Accordion
      as="div"
      className="divide-y divide-zinc-950/10 rounded border border-zinc-950/10 dark:divide-white/10 dark:border-white/10"
      defaultValue="shipping"
    >
      <AccordionItem value="shipping">
        <AccordionHeader className="m-0">
          <AccordionTrigger className="group flex w-full items-center justify-between px-3 py-2.5 text-left text-base text-zinc-900 sm:py-2 sm:text-sm dark:text-zinc-100">
            Shipping{" "}
            <ChevronDownIcon
              className="size-4 text-zinc-400 transition-transform duration-150 ease-out group-data-open:rotate-180 motion-reduce:transition-none"
              aria-hidden="true"
            />
          </AccordionTrigger>
        </AccordionHeader>
        <AccordionPanel className="docs-accordion-panel grid grid-rows-[1fr] overflow-hidden transition-[grid-template-rows] duration-150 ease-out motion-reduce:transition-none [&[hidden]]:grid-rows-[0fr]">
          <div className="min-h-0 overflow-hidden">
            <div className="px-3 pb-3 text-base text-zinc-600 sm:text-sm dark:text-zinc-400">
              Orders leave our warehouse in two business days.
            </div>
          </div>
        </AccordionPanel>
      </AccordionItem>
      <AccordionItem value="returns">
        <AccordionHeader className="m-0">
          <AccordionTrigger className="group flex w-full items-center justify-between px-3 py-2.5 text-left text-base text-zinc-900 sm:py-2 sm:text-sm dark:text-zinc-100">
            Returns{" "}
            <ChevronDownIcon
              className="size-4 text-zinc-400 transition-transform duration-150 ease-out group-data-open:rotate-180 motion-reduce:transition-none"
              aria-hidden="true"
            />
          </AccordionTrigger>
        </AccordionHeader>
        <AccordionPanel className="docs-accordion-panel grid grid-rows-[1fr] overflow-hidden transition-[grid-template-rows] duration-150 ease-out motion-reduce:transition-none [&[hidden]]:grid-rows-[0fr]">
          <div className="min-h-0 overflow-hidden">
            <div className="px-3 pb-3 text-base text-zinc-600 sm:text-sm dark:text-zinc-400">
              Returns are accepted within 30 days.
            </div>
          </div>
        </AccordionPanel>
      </AccordionItem>
    </Accordion>
  );
}

Anatomy

Dashed frames are invisible state providers; shaded shapes own real DOM. Numbered pins match the list below.

A wireframe sketch of the assembled component. Each numbered marker matches a part in the list that follows.

  1. Accordion

    Open-item state provider. Does not add a DOM element.

  2. AccordionItem

    Owns an item wrapper. Owns a DOM element.

  3. AccordionHeader

    Heading wrapper. Owns a DOM element.

  4. AccordionTrigger

    Native button that opens its panel. Owns a DOM element.

  5. AccordionPanel

    Revealed region. Owns a DOM element.

Step by step

  1. 1

    Add the main part

    Start Accordion with one AccordionItem and value.

  2. 2

    Add the supporting parts

    Put Header and Trigger before the matching Panel.

  3. 3

    Make the behavior clear

    Use defaultValue for the item that should begin open.

    Exampletsx
    <Accordion defaultValue="one"><AccordionItem value="one"><AccordionHeader><AccordionTrigger>Details</AccordionTrigger></AccordionHeader><AccordionPanel>More information.</AccordionPanel></AccordionItem></Accordion>

Keyboard

Moves to next trigger.
Moves to previous trigger.
Toggles the item.
Space
Toggles the item.

Forms and accessibility

No native form behavior.

Accessibility checklist

  • Write trigger headings that describe the hidden content.
  • Keep the expanded state visually clear.
  • Do not hide important error messages inside a collapsed item.

API reference

Importtsx
import { Accordion, AccordionHeader, AccordionItem, AccordionPanel, AccordionTrigger } from "@comp0/react";

Accordion

Context only

Open-item state provider.

PropTypeDescription
type"single" | "multiple"How many items may stay open.
valuestring | string[]Controlled open items.
defaultValuestring | string[]Initial open items.
onChange(value) => voidReceives the next open items.
collapsiblebooleanAllows closing the last open item.

AccordionItem

DOM element

Owns an item wrapper.

PropTypeDescription
valuestringIdentity used by the root’s open state.
disabledbooleanDisables the item.

AccordionHeader

DOM element

Heading wrapper.

PropTypeDescription
level1 | 2 | 3 | 4 | 5 | 6Heading element to render; defaults to h3.

AccordionTrigger

DOM element

Native button that opens its panel.

PropTypeDescription
disabledbooleanDisables this trigger on top of the item's disabled state.

AccordionPanel

DOM element

Revealed region.

PropTypeDescription
role"region" | "group"Use group when many panels would flood landmarks.

Style hooks

Attributes that appear while a state is true. Target them with Tailwind data variants such as data-open:bg-zinc-100, or with any CSS selector.

[data-open]

on AccordionItem, AccordionTrigger, AccordionPanel

The item is expanded.
[data-disabled]

on AccordionItem, AccordionTrigger

The trigger is disabled.

Keep exploring