GitHub
Core
Glass
Brutal
Humanist

Accordion

Accordion components allow users to show and hide sections of content. Use them for FAQs, settings panels, or any UI where space is limited and content can be progressively disclosed.

Accordion Playground

Accordion Playground
Preview
Code
Controls
Size:
Default
Large
Container:
Single Open:

Installation

You can add the accordion component to your project manually:

1

Install the following dependencies:

npm install class-variance-authority clsx tailwind-merge @phosphor-icons/react @react-aria/focus @react-aria/interactions
2

Copy and paste the following code into your project.

Loading source code...
3

Update the import paths to match your project setup.

Update the import aliases (e.g. @/components, @/utils) in the copied files to match your project's path configuration.

Basic Usage

A single AccordionItem works as a standalone component:

import { AccordionItem } from '@versaui/ui/components/Accordion';
function Example() {
  return (
    <AccordionItem title="What payment methods do you accept?">
      We accept all major credit cards, PayPal, and bank transfers.
    </AccordionItem>
  );
}

Accordion Group

Use the Accordion wrapper to coordinate multiple items. Set singleOpen to allow only one item open at a time:

import { Accordion, AccordionItem } from '@versaui/ui/components/Accordion';
function FAQ() {
  return (
    <Accordion singleOpen gap={12}>
      <AccordionItem id="q1" title="What payment methods do you accept?">
        We accept all major credit cards, PayPal, and bank transfers.
      </AccordionItem>
      <AccordionItem id="q2" title="How do I cancel my subscription?">
        You can cancel anytime from your account settings.
      </AccordionItem>
      <AccordionItem id="q3" title="Can I upgrade my plan?">
        Yes, upgrades are prorated and take effect immediately.
      </AccordionItem>
    </Accordion>
  );
}

For multiple items open simultaneously, omit the singleOpen prop:

<Accordion gap={12}>
  <AccordionItem id="section1" title="Section 1">Content 1</AccordionItem>
  <AccordionItem id="section2" title="Section 2">Content 2</AccordionItem>
</Accordion>

Controlled State

For external state control, use isOpen and onOpenChange:

import { useState } from 'react';
import { AccordionItem } from '@versaui/ui/components/Accordion';
function ControlledExample() {
  const [isOpen, setIsOpen] = useState(false);
  return (
    <AccordionItem
      isOpen={isOpen}
      onOpenChange={setIsOpen}
      title="Controlled Section"
    >
      This accordion is controlled by parent state.
    </AccordionItem>
  );
}

Variants

Size

Two sizes are available — default and large:

<AccordionItem size="default" title="Default Size">
  Standard padding and typography.
</AccordionItem>
<AccordionItem size="large" title="Large Size">
  Larger padding and typography for prominent sections.
</AccordionItem>

Container

Set container={false} for a borderless variant with only a bottom divider:

<AccordionItem container={false} title="Borderless Section">
  This variant has no container background.
</AccordionItem>

Rich Content

The accordion body accepts any React content:

<AccordionItem title="Account Settings">
  <p>Update your profile information below.</p>
  <button onClick={() => console.log('clicked')}>
    Edit Profile
  </button>
</AccordionItem>

Accessibility

The Accordion component is fully accessible:

  • Keyboard navigation: Press Enter or Space to toggle when focused
  • Screen readers: Trigger announces expanded/collapsed state via aria-expanded
  • Focus management: Visual focus ring appears when navigating via keyboard
  • Semantic structure: Uses role="button" for trigger, role="region" for content

AccordionItem Props

PropTypeDefaultDescription
titlestringRequired. Header text.
childrenReactNodeRequired. Content revealed when expanded.
size'default' | 'large''default'Controls padding and typography.
containerbooleantrueShow background/border or only bottom divider.
isOpenbooleanControlled open state.
defaultOpenbooleanfalseInitial open state (uncontrolled).
onOpenChange(open: boolean) => voidCallback when open state changes.
disabledbooleanfalsePrevents interaction.
idstringautoUnique ID for group coordination.
classNamestring''Additional CSS classes.

Accordion (Group) Props

PropTypeDefaultDescription
childrenReactNodeRequired. AccordionItem components.
singleOpenbooleanfalseOnly one item open at a time.
gapnumber0Gap between items in pixels.
defaultOpenItemsstring[][]IDs of initially open items.
openItemsstring[]Controlled array of open item IDs.
onOpenItemsChange(ids: string[]) => voidCallback when open items change.
classNamestring''Additional CSS classes.

On this page