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.