Skip to main content
Gremorie

Accordion

Vertical stack of expandable sections. Single or multiple open at once, with built-in keyboard navigation.

Overview

Accordion is the coordinated-disclosure primitive: a vertical stack of sections where readers expand and collapse to reveal content in place. Built on Radix Accordion, it ships two modes via type: "single" (one open at a time, optionally with collapsible so the open item can also close) and "multiple" (any number open simultaneously).

Reach for Accordion when siblings should remain visible - the vertical context is preserved, so readers can scan headings without losing their place. When you want full context swaps, use Tabs instead. Don't nest more than two levels deep; depth past that becomes a scavenger hunt.

For a single, isolated "show more" toggle, prefer Collapsible - it's the building block Accordion is composed on.

Preview

The registry is the single source of truth for Gremorie primitives. Each item lists its files, dependencies, and peers so an agent can install it deterministically.

'use client';import {  Accordion,  AccordionContent,  AccordionItem,  AccordionTrigger,} from '@gremorie/rx-display';export function AccordionPreview() {  return (    <Accordion type="single" collapsible defaultValue="reg" className="w-full">      <AccordionItem value="reg">        <AccordionTrigger>What is the registry?</AccordionTrigger>        <AccordionContent>          The registry is the single source of truth for Gremorie primitives.          Each item lists its files, dependencies, and peers so an agent can          install it deterministically.        </AccordionContent>      </AccordionItem>      <AccordionItem value="mcp">        <AccordionTrigger>What does the MCP server do?</AccordionTrigger>        <AccordionContent>          It exposes the registry as MCP tools so any compatible client can          search, read, and apply Gremorie items.        </AccordionContent>      </AccordionItem>      <AccordionItem value="rx">        <AccordionTrigger>What is rx-?</AccordionTrigger>        <AccordionContent>          rx- is the React edition prefix. ng- is the Angular edition prefix.          Both ship side by side.        </AccordionContent>      </AccordionItem>    </Accordion>  );}

Anatomy

Accordion                  the Radix Root; carries type + collapsible
└─ AccordionItem           one section, identified by value
   ├─ AccordionTrigger     the clickable header (renders the chevron)
   └─ AccordionContent     the collapsible body (animated open/close)

Installation

bash npx gremorie@latest add rx-accordion
bash pnpm dlx gremorie@latest add rx-accordion
bash yarn dlx gremorie@latest add rx-accordion
bash bunx --bun gremorie@latest add rx-accordion

Usage

import {
  Accordion,
  AccordionItem,
  AccordionTrigger,
  AccordionContent,
} from "@gremorie/rx-display";

export function Example() {
  return (
    <Accordion type="single" collapsible defaultValue="item-1">
      <AccordionItem value="item-1">
        <AccordionTrigger>What is the registry?</AccordionTrigger>
        <AccordionContent>
          The single source of truth for Gremorie primitives.
        </AccordionContent>
      </AccordionItem>
      <AccordionItem value="item-2">
        <AccordionTrigger>What does the MCP server do?</AccordionTrigger>
        <AccordionContent>
          Exposes the registry as MCP tools.
        </AccordionContent>
      </AccordionItem>
    </Accordion>
  );
}

The Angular edition of this component ships from source today (see the workbench for the side-by-side); its registry entry is coming next.

API

<Accordion>

Wraps Radix Accordion.Root.

PropTypeDefaultDescription
type"single" | "multiple"-Required. "single" lets one item open at a time; "multiple" lets any number open.
collapsiblebooleanfalseOnly with type="single". When true, clicking the open item closes it.
valuestring | string[]-Controlled value(s) of the open item(s). string for single, string[] for multiple.
defaultValuestring | string[]-Uncontrolled default.
onValueChange(value: string | string[]) => void-Fires when an item opens or closes.
disabledbooleanfalseDisables all items.
orientation"vertical" | "horizontal""vertical"Affects keyboard navigation (Arrow keys).
dir"ltr" | "rtl""ltr"Reading direction.

<AccordionItem>

A single section. Wraps Radix Accordion.Item.

PropTypeDefaultDescription
valuestring-Required. Unique identifier - this is what value / defaultValue on Root references.
disabledbooleanfalseDisables this specific item.

Renders with border-b last:border-b-0 for clean stacking.

<AccordionTrigger>

The clickable header. Wraps Radix Accordion.Trigger inside an Accordion.Header for proper semantics. Includes a ChevronDown icon that rotates 180 degrees when the item opens ([&[data-state=open]>svg]:rotate-180).

PropTypeDefaultDescription
classNamestring-Extra classes merged via cn.

<AccordionContent>

The collapsible content panel. Animates open and closed using data-[state=closed]:animate-accordion-up and data-[state=open]:animate-accordion-down. Wraps content in an inner div with pt-0 pb-4.

Composition

  1. <Accordion> owns the state (type, controlled value or uncontrolled defaultValue).
  2. One or more <AccordionItem> with unique value props.
  3. Inside each item: an <AccordionTrigger> (the header) followed by <AccordionContent> (the body).

The Trigger renders inside an internal Accordion.Header so the heading semantics are correct - you do not need to wrap the trigger in your own <h3>.

Variations

Multiple sections open

57 primitives across 8 packages.

Added Message, Prompt, Response.

'use client';import {  Accordion,  AccordionContent,  AccordionItem,  AccordionTrigger,} from '@gremorie/rx-display';export function AccordionMultiplePreview() {  return (    <Accordion      type="multiple"      defaultValue={['release-1', 'release-2']}      className="w-full"    >      <AccordionItem value="release-1">        <AccordionTrigger>v1.0 - Initial release</AccordionTrigger>        <AccordionContent>57 primitives across 8 packages.</AccordionContent>      </AccordionItem>      <AccordionItem value="release-2">        <AccordionTrigger>v1.1 - AI primitives</AccordionTrigger>        <AccordionContent>Added Message, Prompt, Response.</AccordionContent>      </AccordionItem>      <AccordionItem value="release-3">        <AccordionTrigger>v1.2 - Patterns layer</AccordionTrigger>        <AccordionContent>          Composed patterns: DataTable, FormBuilder.        </AccordionContent>      </AccordionItem>    </Accordion>  );}

With type="multiple", any number of items can stay open at once. Pass an array to defaultValue to open several on load - useful for release notes or feature breakdowns.

Disabled item

'use client';import {  Accordion,  AccordionContent,  AccordionItem,  AccordionTrigger,} from '@gremorie/rx-display';export function AccordionDisabledPreview() {  return (    <Accordion type="single" collapsible className="w-full">      <AccordionItem value="account">        <AccordionTrigger>Account</AccordionTrigger>        <AccordionContent>          Update your profile, email, and password.        </AccordionContent>      </AccordionItem>      <AccordionItem value="billing" disabled>        <AccordionTrigger>Billing (upgrade required)</AccordionTrigger>        <AccordionContent>          Billing settings are available on paid plans.        </AccordionContent>      </AccordionItem>      <AccordionItem value="notifications">        <AccordionTrigger>Notifications</AccordionTrigger>        <AccordionContent>          Choose which events send you an email.        </AccordionContent>      </AccordionItem>    </Accordion>  );}

Set disabled on an individual AccordionItem to lock it. Disabled triggers render with aria-disabled="true" and are skipped during arrow-key navigation.

Controlled value

const [open, setOpen] = useState<string>('billing');

<Accordion type="single" collapsible value={open} onValueChange={setOpen}>
  <AccordionItem value="account">
    <AccordionTrigger>Account</AccordionTrigger>
    <AccordionContent>...</AccordionContent>
  </AccordionItem>
  <AccordionItem value="billing">
    <AccordionTrigger>Billing</AccordionTrigger>
    <AccordionContent>...</AccordionContent>
  </AccordionItem>
</Accordion>;

Accessibility

  • WAI-ARIA Accordion pattern: Radix sets role="region" on each content panel with aria-labelledby pointing at its trigger; the trigger gets aria-expanded and aria-controls.
  • Keyboard: Tab moves between triggers; Space or Enter toggles the focused trigger; ArrowDown / ArrowUp navigate between triggers (loops at the ends). Home and End jump to first and last.
  • Headings: each trigger is wrapped in an internal Accordion.Header (renders as a <h3> by default) so screen readers announce the section as a heading.
  • Disabled items: render with aria-disabled="true" and are skipped during arrow-key navigation.
  • Reduced motion: animations use data-[state] selectors with prefers-reduced-motion queries inherited from the keyframes config.
  • Collapsible - the single-section building block Accordion is composed on.
  • Tabs - use when readers should context-swap rather than browse siblings.
  • Card - common host for an Accordion inside a settings panel.

On this page