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
API Reference
Accordion
| Prop | Type | Default | Description |
|---|---|---|---|
type | 'single' | 'multiple' | 'single' | Defines accordion behavior. 'single' allows only one open item; 'multiple' allows multiple open items |
defaultValue | string | string[] | -- | Sets initial open state(s); string for single type, array for multiple |
value | string | string[] | -- | Controlled open state(s); requires onValueChange for updates |
onValueChange | (value: string | string[]) => void | -- | Callback fired when open state changes |
collapsible | boolean | true | Allows collapsing the currently open item by clicking again (single type only) |
renderOnce | boolean | false | Mounts content only on first expand and preserves it afterward |
dir | 'ltr' | 'rtl' | -- | Text direction override. Resolved via useDirection (dir prop -> DirectionProvider -> 'ltr'). |
className | string | -- | Additional CSS classes applied to the root div |
children | React.ReactNode | -- | AccordionItem elements to render inside the accordion |
...props | React.HTMLProps<HTMLDivElement> | -- | Additional props to spread to the content div |
AccordionItem Props
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | (required) | Unique identifier tying trigger to content |
children | [trigger: ReactNode, content: ReactNode] | (required) | Two nodes: first the AccordionTrigger, second the AccordionContent |
className | string | -- | Additional CSS classes applied to the details element |
...props | React.HTMLProps<HTMLDetailsElement> | -- | Additional props to spread to the details element |
AccordionTrigger Props
| Prop | Type | Default | Description |
|---|---|---|---|
icon | React.ReactNode | -- | Custom icon component; defaults to a rotating ChevronDown |
className | string | -- | Additional CSS classes applied to the summary element |
children | React.ReactNode | -- | Content rendered as the trigger label |
...props | React.HTMLProps<HTMLElement> | -- | Additional props to spread to the summary element |
AccordionContent Props
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | -- | Additional CSS classes applied to the content div |
children | React.ReactNode | -- | Content to reveal when the accordion item is expanded |
...props | React.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.