Accordion
Accordion organizes related content into collapsible sections so users can
scan dense pages and open the details they need. Keep behavior props on the root
so Spar owns the open/closed state model.
Usage
import { Accordion } from '@takeoff-ui/react-spar';
<Accordion>
<Accordion.Item>
<Accordion.Header>
<Accordion.Trigger>
<Accordion.Indicator />
</Accordion.Trigger>
</Accordion.Header>
<Accordion.Content />
</Accordion.Item>
</Accordion>
Playground
Multiple Panels
Controlled
Custom Indicator
Disabled Item
Without Indicator
Force-Mounted Content
Accessibility & Keyboard
- Each
Accordion.Triggerrenders a native<button>and exposesaria-expandedplusaria-controlspointing at its panel. - Each
Accordion.Contentis arole="region"labelled by the matching trigger viaaria-labelledby. Accordion.Headerrenders anh1–h6heading; pick the level that fits the surrounding document outline.- Stable trigger / panel ids derive from the
idset onAccordion.Item; override there if you need deterministic markup.
| Key | Behavior |
|---|---|
| Enter / Space | Toggle the focused trigger. |
| ↓ / ↑ | Move focus to the next / previous trigger (vertical orientation). |
| → / ← | Move focus to the next / previous trigger (orientation="horizontal"). |
| Home / End | Move focus to the first / last trigger. |
Disabled items skip both pointer and keyboard activation and surface
data-disabled on the item root for theme recipes.
API Reference
Accordion
See Spar Accordion docs for primitive behavior.
Props
| Name | Type | Default | Description |
|---|---|---|---|
| children | React.ReactNode | - | Accordion.Item elements rendered inside the disclosure container. |
| type | AccordionType | 'grouped' | Visual grouping. |
| mode | AccordionMode | 'default' | Density mode. Pairs with any AccordionType. |
| size | AccordionSize | 'base' | Size scale. |
| classNames | Partial<Record<"root", string>> | - | Per-slot class name overrides. |
| slotProps | Partial<Record<"root", React.HTMLAttributes<HTMLElement>>> | - | Per-slot HTML attribute overrides. |
| defaultValue | AccordionCurrentValue | - | Uncontrolled initial item identifier(s). Used only on mount. |
| multiple | boolean | false | When true, multiple items can be expanded at once. |
| value | AccordionCurrentValue | - | Controlled item identifier(s). Match the value of the items that should be expanded. |
| collapsible | boolean | true | In single mode, when true, an active item can be collapsed by clicking it again. When false, one item is always expanded. Has no effect in multi mode. |
| disabled | boolean | false | Disables every item in the accordion. |
| orientation | Orientation | 'vertical' | Orientation for keyboard navigation. |
| className | string | - | Appends custom classes to the root slot of this part. |
Events
| Name | Type | Default | Description |
|---|---|---|---|
| onValueChange | (next: AccordionCurrentValue) => void | - | Fired when the open value changes. The payload preserves the canonical shape: scalar in single mode, array in multiple mode. |
Data attributes
| Attribute | Applied when | Purpose |
|---|---|---|
| data-slot="root" | Always | Stable selector for wrapper styling on the root slot. |
| data-mode | Always | Reflects the resolved mode prop. Theme recipes can scope per-mode rules without reading React props. |
| data-size | Always | Reflects the resolved size prop so theme recipes can scope size variants. |
Accordion.Item
See Spar Accordion docs for primitive behavior.
Props
| Name | Type | Default | Description |
|---|---|---|---|
| children | React.ReactNode | - | Accordion.Header and Accordion.Content elements that compose the item. |
| classNames | Partial<Record<"root", string>> | - | Per-slot class name overrides. |
| slotProps | Partial<Record<"root", React.HTMLAttributes<HTMLElement>>> | - | Per-slot HTML attribute overrides. |
| value | AccordionValue | - | Stable identity for this item. |
| disabled | boolean | false | Disables this item. |
| className | string | - | Appends custom classes to the root slot of this part. |
Data attributes
| Attribute | Applied when | Purpose |
|---|---|---|
| data-slot="root" | Always | Stable selector for wrapper styling on the root slot. |
| data-type | Always | Reflects the resolved type prop. Theme recipes can target items per type. |
| data-mode | Always | Reflects the resolved mode prop. Theme recipes can scope per-mode rules without reading React props. |
| data-size | Always | Reflects the resolved size prop so theme recipes can scope size variants. |
| data-state="open" | When expanded. | Spar open-state hook. |
| data-state="closed" | When collapsed. | Spar closed-state hook. |
Accordion.Header
See Spar Accordion docs for primitive behavior.
Props
| Name | Type | Default | Description |
|---|---|---|---|
| children | React.ReactNode | - | Accordion.Trigger element rendered inside the heading tag. |
| classNames | Partial<Record<"root", string>> | - | Per-slot class name overrides. |
| slotProps | Partial<Record<"root", React.HTMLAttributes<HTMLElement>>> | - | Per-slot HTML attribute overrides. |
| level | number | 3 | Heading level (1-6) for document hierarchy |
| className | string | - | Appends custom classes to the root slot of this part. |
Data attributes
| Attribute | Applied when | Purpose |
|---|---|---|
| data-slot="root" | Always | Stable selector for wrapper styling on the root slot. |
| data-state="open" | When expanded. | Spar open-state hook. |
| data-state="closed" | When collapsed. | Spar closed-state hook. |
Accordion.Trigger
See Spar Accordion docs for primitive behavior.
Props
| Name | Type | Default | Description |
|---|---|---|---|
| children | React.ReactNode | - | Accessible label for the trigger button. |
| startContent | React.ReactNode | - | Leading content rendered before the title — typically an icon, but accepts any node. The wrapper element (class + data-slot) is invariant; only the inner node is consumer-supplied. |
| classNames | Partial<Record<AccordionTriggerSlot, string>> | - | Per-slot class name overrides. |
| slotProps | Partial<Record<AccordionTriggerSlot, React.HTMLAttributes<HTMLElement>>> | - | Per-slot HTML attribute overrides. |
| className | string | - | Appends custom classes to the root slot of this part. |
Data attributes
| Attribute | Applied when | Purpose |
|---|---|---|
| data-slot="root" | Always | Stable selector for wrapper styling on the root slot. |
| data-state="open" | When expanded. | Spar open-state hook. |
| data-state="closed" | When collapsed. | Spar closed-state hook. |
Accordion.Content
See Spar Accordion docs for primitive behavior.
Props
| Name | Type | Default | Description |
|---|---|---|---|
| children | React.ReactNode | - | Panel body. Animated open/closed by Spar. |
| classNames | Partial<Record<"root", string>> | - | Per-slot class name overrides. |
| slotProps | Partial<Record<"root", React.HTMLAttributes<HTMLElement>>> | - | Per-slot HTML attribute overrides. |
| forceMount | boolean | false | Force content to remain mounted when closed |
| className | string | - | Appends custom classes to the root slot of this part. |
Events
| Name | Type | Default | Description |
|---|---|---|---|
| onBeforeMatch | (event: Event) => void | - | Callback fired when content is found via browser search |
Data attributes
| Attribute | Applied when | Purpose |
|---|---|---|
| data-slot="root" | Always | Stable selector for wrapper styling on the root slot. |
| data-state="open" | When expanded. | Spar open-state hook. |
| data-state="closed" | When collapsed. | Spar closed-state hook. |
Type Definitions
| Name | Definition |
|---|---|
| AccordionType | 'grouped' | 'divided' |
| AccordionMode | 'default' | 'compact' |
| AccordionSize | 'base' | 'large' |
| AccordionCurrentValue | AccordionValue | AccordionValue[] |
| Orientation | 'vertical' | 'horizontal' |
| AccordionValue | string | number |
| AccordionTriggerSlot | 'root' | 'startContent' | 'title' |