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

PropTypeDefaultDescription
type*"single" | "multiple"Controls selection behavior. "single" allows one open item; "multiple" allows many.
collapsiblebooleanfalseWhen type="single", allows the open item to be closed by clicking it again.
defaultValuestring | string[]The value(s) of the item(s) open by default (uncontrolled).
valuestring | string[]Controlled open value(s). Use with onValueChange.
onValueChange(value: string | string[]) => voidCalled when the open state changes.
classNamestringAdditional class names applied to the root element.

AccordionItem

PropTypeDefaultDescription
value*stringUnique identifier for this item. Used to control open state.
disabledbooleanfalsePrevents the item from being opened or closed.
classNamestringAdditional class names applied to the item element.

AccordionTrigger

PropTypeDefaultDescription
children*ReactNodeThe label shown in the trigger button.
classNamestringAdditional class names applied to the trigger element.

AccordionContent

PropTypeDefaultDescription
children*ReactNodeThe content revealed when the item is open.
classNamestringAdditional 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.