moduix

Accordion

A vertically stacked set of interactive headings that each reveal a section of content.

API Reference

Original primitive API

Behavior, accessibility details, and low-level props are documented by Base UI.

Base UI API

Basic

Base UI is a library of high-quality unstyled React components for design systems and web apps.

import {  Accordion,  AccordionItem,  AccordionPanel,  AccordionTrigger,} from "moduix";export function AccordionDemo() {  return (    <Accordion defaultValue={["what-is-base-ui"]}>      {items.map((item) => (        <AccordionItem key={item.value} value={item.value}>          <AccordionTrigger>{item.title}</AccordionTrigger>          <AccordionPanel>            <div className={styles.panelContent}>{item.description}</div>          </AccordionPanel>        </AccordionItem>      ))}    </Accordion>  );}
.panelContent {  padding: var(--spacing-3);}
const items = [  {    value: "what-is-base-ui",    title: "What is Base UI?",    description:      "Base UI is a library of high-quality unstyled React components for design systems and web apps.",  },  {    value: "getting-started",    title: "How do I get started?",    description:      "Head to the Quick start guide in the docs. If you have used unstyled libraries before, you will feel at home.",  },  {    value: "can-i-use-it",    title: "Can I use it for my project?",    description: "Of course. Base UI is free and open source.",  },];

Full list of component variables available for project-level overrides.

PropertyDefaultDescription
--accordion-colorvar(--color-foreground)Controls accordion text color.
--accordion-disabled-opacityvar(--opacity-disabled)Controls disabled item opacity.
--accordion-focus-ring-colorvar(--color-ring)Controls trigger focus ring color.
--accordion-focus-ring-offsetvar(--border-width-sm)Controls trigger focus ring offset from trigger edge.
--accordion-focus-ring-widthvar(--border-width-md)Controls trigger focus ring outline width.
--accordion-icon-margin-rightvar(--spacing-2)Controls trigger icon right margin.
--accordion-icon-open-transformrotate(45deg) scale(1.1)Controls trigger icon transform when the panel is open.
--accordion-icon-size0.75remControls trigger icon size.
--accordion-icon-transitionvar(--transition-default)Controls trigger icon transition.
--accordion-item-border-colorvar(--color-border)Controls the separator color between accordion items.
--accordion-item-border-widthvar(--border-width-sm)Controls the separator width between accordion items.
--accordion-max-widthcalc(100vw - 8rem)Controls the root accordion max width.
--accordion-panel-colorvar(--color-muted-foreground)Controls panel text color.
--accordion-panel-font-sizevar(--text-md)Controls panel text font size.
--accordion-panel-line-heightvar(--line-height-text-md)Controls panel text line height.
--accordion-panel-transitionvar(--transition-default)Controls panel open and close transition.
--accordion-trigger-bgvar(--color-muted)Controls trigger background color.
--accordion-trigger-bg-hovervar(--color-accent)Controls trigger background color on hover.
--accordion-trigger-font-sizevar(--text-md)Controls trigger text font size.
--accordion-trigger-gapvar(--spacing-4)Controls spacing between trigger content and icon.
--accordion-trigger-line-heightvar(--line-height-text-md)Controls trigger text line height.
--accordion-trigger-padding-x-endvar(--spacing-1)Controls trigger end-side horizontal padding.
--accordion-trigger-padding-x-startvar(--spacing-3)Controls trigger start-side horizontal padding.
--accordion-trigger-padding-yvar(--spacing-2)Controls trigger vertical padding.
--accordion-width24remControls the root accordion width.

Interactive variables scoped for docs preview without changing size scale tokens.

PropertyValueDefaultDescription
--accordion-colorvar(--color-foreground)Controls accordion text color.
--accordion-focus-ring-colorvar(--color-ring)Controls trigger focus ring color.
--accordion-icon-size0.75remControls trigger icon size.
--accordion-item-border-colorvar(--color-border)Controls separator color.
--accordion-item-border-widthvar(--border-width-sm)Controls separator width.
--accordion-panel-colorvar(--color-muted-foreground)Controls panel text color.
--accordion-trigger-bgvar(--color-muted)Controls trigger background color.
--accordion-trigger-bg-hovervar(--color-accent)Controls trigger hover background.
--accordion-trigger-gapvar(--spacing-4)Controls trigger content and icon spacing.
--accordion-trigger-padding-yvar(--spacing-2)Controls trigger vertical padding.

Anatomy

Accordion is composed as a stack of independent items. Keep the trigger and panel inside the same AccordionItem so their state and accessibility wiring stay paired.

Accordion
└─ AccordionItem[value]
   ├─ AccordionTrigger
   │  ├─ label
   │  └─ icon
   └─ AccordionPanel
      └─ content
<Accordion defaultValue={['shipping']}>
  <AccordionItem value="shipping">
    <AccordionTrigger>Shipping details</AccordionTrigger>
    <AccordionPanel>
      <div className={styles.panelContent}>Delivery times, prices, and tracking options.</div>
    </AccordionPanel>
  </AccordionItem>
</Accordion>
PartRole
AccordionRoot state machine. Controls open values, keyboard navigation, multiple, disabled, and orientation.
AccordionItemOne collapsible row. Its value identifies the row for defaultValue, controlled value, and change handlers.
AccordionTriggerSemantic heading and interactive button. It opens or closes the matching panel and renders a default icon.
AccordionPanelThe collapsible content region. Put padding/content wrappers inside it so panel height animations stay clean.

AccordionTrigger renders the Base UI header internally so the common composition stays compact. Use classNames.header, classNames.icon, slotProps.header, and slotProps.icon when you need to style or customize those internal slots. AccordionHeader and AccordionTriggerIcon are still exported for advanced manual composition, but most projects do not need them.

Composition

Use Accordion for root state and behavior props such as value, defaultValue, onValueChange, multiple, disabled, orientation, and loopFocus. Use keepMounted or hiddenUntilFound on the root or panel when closed content must stay in the DOM.

Style the public parts with className on Accordion, AccordionItem, AccordionTrigger, and AccordionPanel. AccordionTrigger also accepts icon, hideIcon, classNames, and slotProps for the internal header and icon slots. All Base UI behavior props such as render, keepMounted, and hiddenUntilFound pass through to the matching primitive part.

Examples

Multiple

Use the multiple prop to allow multiple items to be open at the same time.

Base UI is a library of high-quality unstyled React components for design systems and web apps.

Of course. Base UI is free and open source.
import {  Accordion,  AccordionItem,  AccordionPanel,  AccordionTrigger,} from "moduix";export function MultipleAccordionDemo() {  return (    <Accordion multiple defaultValue={["what-is-base-ui", "can-i-use-it"]}>      {items.map((item) => (        <AccordionItem key={item.value} value={item.value}>          <AccordionTrigger>{item.title}</AccordionTrigger>          <AccordionPanel>            <div className={styles.panelContent}>{item.description}</div>          </AccordionPanel>        </AccordionItem>      ))}    </Accordion>  );}
.panelContent {  padding: var(--spacing-3);}
const items = [  {    value: "what-is-base-ui",    title: "What is Base UI?",    description:      "Base UI is a library of high-quality unstyled React components for design systems and web apps.",  },  {    value: "getting-started",    title: "How do I get started?",    description:      "Head to the Quick start guide in the docs. If you have used unstyled libraries before, you will feel at home.",  },  {    value: "can-i-use-it",    title: "Can I use it for my project?",    description: "Of course. Base UI is free and open source.",  },];

Controlled

Control the open panels from React state when the accordion needs to coordinate with other UI.

Head to the Quick start guide in the docs. If you have used unstyled libraries before, you will feel at home.

import {  Accordion,  AccordionItem,  AccordionPanel,  AccordionTrigger,} from "moduix";import { useState } from "react";export function ControlledAccordionDemo() {  const [value, setValue] = useState(["getting-started"] as string[])  return (    <Accordion value={value} onValueChange={setValue}>      {items.map((item) => (        <AccordionItem key={item.value} value={item.value}>          <AccordionTrigger>{item.title}</AccordionTrigger>          <AccordionPanel>            <div className={styles.panelContent}>{item.description}</div>          </AccordionPanel>        </AccordionItem>      ))}    </Accordion>  );}
.panelContent {  padding: var(--spacing-3);}
const items = [  {    value: "what-is-base-ui",    title: "What is Base UI?",    description:      "Base UI is a library of high-quality unstyled React components for design systems and web apps.",  },  {    value: "getting-started",    title: "How do I get started?",    description:      "Head to the Quick start guide in the docs. If you have used unstyled libraries before, you will feel at home.",  },  {    value: "can-i-use-it",    title: "Can I use it for my project?",    description: "Of course. Base UI is free and open source.",  },];

Disabled Item

Set disabled on an item to keep it visible while preventing interaction.

Base UI is a library of high-quality unstyled React components for design systems and web apps.

import {  Accordion,  AccordionItem,  AccordionPanel,  AccordionTrigger,} from "moduix";export function DisabledItemAccordionDemo() {  return (    <Accordion defaultValue={["what-is-base-ui"]}>      {items.map((item) => (        <AccordionItem          key={item.value}          value={item.value}          disabled={item.value === "getting-started"}        >          <AccordionTrigger>{item.title}</AccordionTrigger>          <AccordionPanel>            <div className={styles.panelContent}>{item.description}</div>          </AccordionPanel>        </AccordionItem>      ))}    </Accordion>  );}
.panelContent {  padding: var(--spacing-3);}
const items = [  {    value: "what-is-base-ui",    title: "What is Base UI?",    description:      "Base UI is a library of high-quality unstyled React components for design systems and web apps.",  },  {    value: "getting-started",    title: "How do I get started?",    description:      "Head to the Quick start guide in the docs. If you have used unstyled libraries before, you will feel at home.",  },  {    value: "can-i-use-it",    title: "Can I use it for my project?",    description: "Of course. Base UI is free and open source.",  },];

Custom Icon

Pass icon to replace the default visual marker and style the icon slot with classNames.icon.

Base UI is a library of high-quality unstyled React components for design systems and web apps.

import {  Accordion,  AccordionItem,  AccordionPanel,  AccordionTrigger,  ChevronDownIcon,} from "moduix";export function CustomStylesAccordionDemo() {  return (    <Accordion defaultValue={["what-is-base-ui"]}>      {items.map((item) => (        <AccordionItem key={item.value} value={item.value}>          <AccordionTrigger            icon={<ChevronDownIcon />}            classNames={{ icon: styles.customIcon }}          >            {item.title}          </AccordionTrigger>          <AccordionPanel>            <div className={styles.panelContent}>{item.description}</div>          </AccordionPanel>        </AccordionItem>      ))}    </Accordion>  );}
.panelContent {  padding: var(--spacing-3);}.customIcon {  --accordion-icon-open-transform: rotate(180deg);}
const items = [  {    value: "what-is-base-ui",    title: "What is Base UI?",    description:      "Base UI is a library of high-quality unstyled React components for design systems and web apps.",  },  {    value: "getting-started",    title: "How do I get started?",    description:      "Head to the Quick start guide in the docs. If you have used unstyled libraries before, you will feel at home.",  },  {    value: "can-i-use-it",    title: "Can I use it for my project?",    description: "Of course. Base UI is free and open source.",  },];

On this page