Marble UI
← Components

Accordion

Preview: Divided

One collapsible section. Group several in an Accordion. Height animates via --disclosure-panel-height.

Import

import { Accordion, AccordionItem } from '@marbleui/ui'

Props

<Accordion>

PropTypeDefaultDescription
variant'divided' | 'separated''divided'divided: hairlines between items (use default AccordionItems). separated: gaps (use variant="card" items).

Also accepts React Aria props (80).

<AccordionItem>alias of Disclosure

PropTypeDefaultDescription
children *requiredReactNode—
title *requiredReactNode—
iconReactNode—
level1 | 2 | 3 | 4 | 5 | 63Heading level of the trigger (default 3). Match it to the surrounding outline.
variant'default' | 'card''divided'

Also accepts React Aria props (79).

Accessibility

Keyboard interaction, focus management and ARIA semantics come from the underlying primitive: React Aria DisclosureGroup. Follow the primitive's docs for the full keyboard map.

Usage notes

Group of collapsible sections, such as an FAQ. For a single standalone collapsible section use Disclosure; for mutually exclusive content panels use Tabs.

<Accordion defaultExpandedKeys={['trial']}>
  <AccordionItem id="trial" title="Is there a free trial?">Yes, 14 days.</AccordionItem>
  <AccordionItem id="cancel" title="Can I cancel anytime?">Yes.</AccordionItem>
</Accordion>
  • AccordionItem is Disclosure; every item needs a unique id.
  • By default only one item is open. Add allowsMultipleExpanded to allow several.
  • Controlled: expandedKeys and onExpandedChange; uncontrolled: defaultExpandedKeys.
  • variant="separated" on Accordion pairs with variant="card" on the items; the default divided pairs with default items.
Example source · show
import { Accordion, AccordionItem } from './accordion'

const faq = [
  { id: 'trial', q: 'Is there a free trial?', a: 'Yes. Every plan starts with 14 days free, no card required.' },
  { id: 'cancel', q: 'Can I cancel anytime?', a: 'Cancel from billing settings. You keep access until the end of the period.' },
  { id: 'seats', q: 'How do seats work?', a: 'You pay for active members. Guests and viewers are always free.' },
]

export const styles = {
  Divided: () => (
    <Accordion className="w-[26rem]" defaultExpandedKeys={['trial']}>
      {faq.map((f) => (
        <AccordionItem key={f.id} id={f.id} title={f.q}>{f.a}</AccordionItem>
      ))}
    </Accordion>
  ),
  Separated: () => (
    <Accordion variant="separated" className="w-[26rem]" allowsMultipleExpanded>
      {faq.map((f) => (
        <AccordionItem key={f.id} id={f.id} variant="card" title={f.q}>{f.a}</AccordionItem>
      ))}
    </Accordion>
  ),
}

Source: packages/ui/src/accordion/accordion.tsx

Catalog

Category
layout
Priority
Foundation
Primitive
react-aria
React Aria
DisclosureGroup
Base UI
Accordion