Skip to main content

accordion

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

Philosophy

Accordions solve the progressive disclosure problem — show the outline, hide the details until requested. We use a compound component pattern (Accordion -> AccordionItem -> AccordionTrigger + AccordionContent) because each piece needs independent control while sharing open/close state. The type="single" vs type="multiple" distinction maps directly to whether sections are mutually exclusive.

Installation


npx @gentleduck/cli add accordion

npx @gentleduck/cli add accordion

Usage

import { Accordion, AccordionItem, AccordionTrigger, AccordionContent } from '@/components/ui/accordion'
import { Accordion, AccordionItem, AccordionTrigger, AccordionContent } from '@/components/ui/accordion'
<Accordion type="single" collapsible>
  <AccordionItem value="item-1">
    <AccordionTrigger>Is it accessible?</AccordionTrigger>
    <AccordionContent>Yes. It adheres to the WAI-ARIA design pattern.</AccordionContent>
  </AccordionItem>
</Accordion>
<Accordion type="single" collapsible>
  <AccordionItem value="item-1">
    <AccordionTrigger>Is it accessible?</AccordionTrigger>
    <AccordionContent>Yes. It adheres to the WAI-ARIA design pattern.</AccordionContent>
  </AccordionItem>
</Accordion>

Examples

Default

ChevronDown Icon

multiple

Component Composition

Loading diagram...

API Reference

Accordion

PropTypeDefaultDescription
type'single' | 'multiple''single'Defines accordion behavior. 'single' allows only one open item; 'multiple' allows multiple open items
defaultValuestring | string[]--Sets initial open state(s); string for single type, array for multiple
valuestring | string[]--Controlled open state(s); requires onValueChange for updates
onValueChange(value: string | string[]) => void--Callback fired when open state changes
collapsiblebooleantrueAllows collapsing the currently open item by clicking again (single type only)
renderOncebooleanfalseMounts content only on first expand and preserves it afterward
dir'ltr' | 'rtl'--Text direction override. Resolved via useDirection (dir prop -> DirectionProvider -> 'ltr').
classNamestring--Additional CSS classes applied to the root div
childrenReact.ReactNode--AccordionItem elements to render inside the accordion
...propsReact.HTMLProps<HTMLDivElement>--Additional props to spread to the content div

AccordionItem Props

PropTypeDefaultDescription
valuestring(required)Unique identifier tying trigger to content
children[trigger: ReactNode, content: ReactNode](required)Two nodes: first the AccordionTrigger, second the AccordionContent
classNamestring--Additional CSS classes applied to the details element
...propsReact.HTMLProps<HTMLDetailsElement>--Additional props to spread to the details element

AccordionTrigger Props

PropTypeDefaultDescription
iconReact.ReactNode--Custom icon component; defaults to a rotating ChevronDown
classNamestring--Additional CSS classes applied to the summary element
childrenReact.ReactNode--Content rendered as the trigger label
...propsReact.HTMLProps<HTMLElement>--Additional props to spread to the summary element

AccordionContent Props

PropTypeDefaultDescription
classNamestring--Additional CSS classes applied to the content div
childrenReact.ReactNode--Content to reveal when the accordion item is expanded
...propsReact.HTMLProps<HTMLDivElement>--Additional props to spread to the content div

RTL Support

Direction is resolved through the shared primitives direction module. Use a local dir="rtl" override when the component exposes it, or set DirectionProvider at app/root level for global RTL/LTR behavior.