Accordion
A vertically stacked set of interactive headings that reveal or hide their associated content sections.
Built on Radix UI.
- ✓Two selection modes: "single" (one item open at a time) and "multiple" (any number open)
- ✓Animated expand/collapse via CSS keyframes
- ✓ChevronDown indicator rotates 180° when open
- ✓Full keyboard navigation — Arrow Up/Down, Home, End, Space, Enter
- ✓Each item can be individually disabled
- ✓Forwards refs to underlying Radix primitives
import { Accordion }from "@aetherstack/ui"
accordion.tsx
import {
Accordion,
AccordionItem,
AccordionTrigger,
AccordionContent,
} from "@/components/ui/accordion"
export function AccordionDemo() {
return (
<Accordion type="single" collapsible className="w-full">
<AccordionItem value="item-1">
<AccordionTrigger>What is Aether UI?</AccordionTrigger>
<AccordionContent>
Aether UI is a copy-paste component library built with Radix UI and Tailwind CSS.
</AccordionContent>
</AccordionItem>
<AccordionItem value="item-2">
<AccordionTrigger>Is it free?</AccordionTrigger>
<AccordionContent>
Yes. Aether UI is completely free and open source.
</AccordionContent>
</AccordionItem>
<AccordionItem value="item-3">
<AccordionTrigger>How do I install it?</AccordionTrigger>
<AccordionContent>
Run npx aether-ui add accordion in your project.
</AccordionContent>
</AccordionItem>
</Accordion>
)
}Usage
Single selection
With type="single" and collapsible, only one item can be open at a time and clicking again closes it.
Multiple selection
With type="multiple", any number of items can be open simultaneously.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| type* | "single" | "multiple" | — | Controls selection behavior. "single" allows one open item; "multiple" allows many. |
| collapsible | boolean | false | When type="single", allows the open item to be closed by clicking it again. |
| defaultValue | string | string[] | — | The value(s) of the item(s) open by default (uncontrolled). |
| value | string | string[] | — | Controlled open value(s). Use with onValueChange. |
| onValueChange | (value: string | string[]) => void | — | Called when the open state changes. |
| className | string | — | Additional class names applied to the root element. |
AccordionItem
| Prop | Type | Default | Description |
|---|---|---|---|
| value* | string | — | Unique identifier for this item. Used to control open state. |
| disabled | boolean | false | Prevents the item from being opened or closed. |
| className | string | — | Additional class names applied to the item element. |
AccordionTrigger
| Prop | Type | Default | Description |
|---|---|---|---|
| children* | ReactNode | — | The label shown in the trigger button. |
| className | string | — | Additional class names applied to the trigger element. |
AccordionContent
| Prop | Type | Default | Description |
|---|---|---|---|
| children* | ReactNode | — | The content revealed when the item is open. |
| className | string | — | Additional class names applied to the inner content div. |
* Required props
Accessibility
- →Each trigger is a <button> inside a heading — screen readers announce it correctly as an expandable section.
- →Arrow Up/Down moves focus between triggers. Home/End jump to first/last.
- →Space and Enter toggle the open state of the focused item.
- →aria-expanded is set automatically by Radix based on open state.
- →Disabled items are skipped during keyboard navigation.