Skip to content
Esc
navigateopen⌘Jpreview
On this page

Accordion

A vertically stacked set of interactive headings that each reveal a section of content.

import * as stylex from '@stylexjs/stylex';

import {
  Accordion,
  AccordionContent,
  AccordionItem,
  AccordionTrigger,
} from '@/components/ui/accordion';
import { container } from '@/lib/constants.stylex';

export default function AccordionDemo() {
  return (
    <Accordion multiple={false} style={styles.root}>
      <AccordionItem value="item-1">
        <AccordionTrigger>Is it accessible?</AccordionTrigger>
        <AccordionContent>
          Yes. It adheres to the WAI-ARIA design pattern.
        </AccordionContent>
      </AccordionItem>
      <AccordionItem value="item-2">
        <AccordionTrigger>Is it styled?</AccordionTrigger>
        <AccordionContent>
          Yes. It comes with default styles that match the other components.
        </AccordionContent>
      </AccordionItem>
      <AccordionItem value="item-3">
        <AccordionTrigger>Is it animated?</AccordionTrigger>
        <AccordionContent>
          Yes. It animates open with the panel height from Base UI.
        </AccordionContent>
      </AccordionItem>
    </Accordion>
  );
}

const styles = stylex.create({
  root: {
    maxWidth: container.lg,
  },
});

Install

npx shadcn@latest add @madeui/accordion

Usage

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

Composition

<Accordion>
  <AccordionItem value="…">
    <AccordionTrigger />
    <AccordionContent />
  </AccordionItem>
</Accordion>

Multiple

Pass multiple to keep several items expanded at the same time.

Yes. Pass `multiple` to keep several items expanded at once.

Yes. Each item tracks its own open state independently.

import * as stylex from '@stylexjs/stylex';

import {
  Accordion,
  AccordionContent,
  AccordionItem,
  AccordionTrigger,
} from '@/components/ui/accordion';
import { container } from '@/lib/constants.stylex';

export default function AccordionMultiple() {
  return (
    <Accordion multiple defaultValue={['item-1', 'item-2']} style={styles.root}>
      <AccordionItem value="item-1">
        <AccordionTrigger>Can I open more than one?</AccordionTrigger>
        <AccordionContent>
          Yes. Pass `multiple` to keep several items expanded at once.
        </AccordionContent>
      </AccordionItem>
      <AccordionItem value="item-2">
        <AccordionTrigger>Is state still per-item?</AccordionTrigger>
        <AccordionContent>
          Yes. Each item tracks its own open state independently.
        </AccordionContent>
      </AccordionItem>
      <AccordionItem value="item-3">
        <AccordionTrigger>Can I set an initial selection?</AccordionTrigger>
        <AccordionContent>
          Yes, via `defaultValue` — an array of the values that start open.
        </AccordionContent>
      </AccordionItem>
    </Accordion>
  );
}

const styles = stylex.create({
  root: {
    maxWidth: container.lg,
  },
});

Disabled

Pass disabled on an AccordionItem to keep it inert.

import * as stylex from '@stylexjs/stylex';

import {
  Accordion,
  AccordionContent,
  AccordionItem,
  AccordionTrigger,
} from '@/components/ui/accordion';
import { container } from '@/lib/constants.stylex';

export default function AccordionDisabled() {
  return (
    <Accordion multiple={false} style={styles.root}>
      <AccordionItem value="item-1">
        <AccordionTrigger>Available plan</AccordionTrigger>
        <AccordionContent>
          This plan can be selected and configured.
        </AccordionContent>
      </AccordionItem>
      <AccordionItem value="item-2" disabled>
        <AccordionTrigger>Enterprise plan (disabled)</AccordionTrigger>
        <AccordionContent>
          Contact sales to unlock this plan.
        </AccordionContent>
      </AccordionItem>
    </Accordion>
  );
}

const styles = stylex.create({
  root: {
    maxWidth: container.lg,
  },
});

API reference

Built on Base UI Accordion. All props are forwarded to the underlying Base UI parts (Root, Item, Trigger, Panel); see the Base UI Accordion API reference. Pass multiple={false} for single-open behavior. Every part also accepts a style prop (StyleXStyles, merged last).

AccordionTrigger renders the Base UI Header + Trigger pair with a rotating chevron; AccordionContent wraps the Base UI Panel and animates open using the panel height provided by Base UI.

Was this page helpful?