GitHub

Accordion

A vertically stacked set of expandable panels for showing and hiding content.

CMSPayload CMS Integration

Accordion content can be fully managed through CMS fields, perfect for FAQ sections, product details, and collapsible content areas.

CMS Demo

See how content editors configure accordions in a CMS:

Loading...
CMS ConfigurationSimulates Payload CMS accordion configuration with localization

Payload Block Example

// In your Payload CMS block config
export const FaqBlock = {
  slug: "faq",
  fields: [
    { name: "title", type: "text", localized: true },
    {
      name: "items",
      type: "array",
      fields: [
        { name: "question", type: "text", localized: true, required: true },
        { name: "answer", type: "richText", localized: true, required: true },
      ],
    },
    { name: "allowMultiple", type: "checkbox" },
  ],
}

Rendering the Block

import {
  Accordion,
  AccordionItem,
  AccordionTrigger,
  AccordionContent,
} from "@mordecai-design-system/ui"

export function FaqSection({ data }) {
  return (
    <div>
      <h2>{data.title}</h2>
      <Accordion>
        {data.items.map((item, i) => (
          <AccordionItem key={i} value={`item-${i}`}>
            <AccordionTrigger>{item.question}</AccordionTrigger>
            <AccordionContent>{item.answer}</AccordionContent>
          </AccordionItem>
        ))}
      </Accordion>
    </div>
  )
}

Basic Usage

Loading...
AccordionAn expandable content section

Installation

pnpm add @corew500/ui

Usage

import {
  Accordion,
  AccordionItem,
  AccordionTrigger,
  AccordionContent,
} from "@mordecai-design-system/ui"
<Accordion>
  <AccordionItem value="item-1">
    <AccordionTrigger>Is it accessible?</AccordionTrigger>
    <AccordionContent>
      Yes. It adheres to the WAI-ARIA design pattern.
    </AccordionContent>
  </AccordionItem>
</Accordion>

Examples

Multiple Open Items

<Accordion openMultiple>
  <AccordionItem value="item-1">
    <AccordionTrigger>First item</AccordionTrigger>
    <AccordionContent>First content</AccordionContent>
  </AccordionItem>
  <AccordionItem value="item-2">
    <AccordionTrigger>Second item</AccordionTrigger>
    <AccordionContent>Second content</AccordionContent>
  </AccordionItem>
</Accordion>

Default Open Item

<Accordion defaultValue={['item-1']}>
  <AccordionItem value="item-1">
    <AccordionTrigger>This is open by default</AccordionTrigger>
    <AccordionContent>Content visible on load</AccordionContent>
  </AccordionItem>
</Accordion>

Controlled

const [value, setValue] = useState<string[]>([])

<Accordion value={value} onValueChange={setValue}>
  <AccordionItem value="item-1">
    <AccordionTrigger>Controlled accordion</AccordionTrigger>
    <AccordionContent>Content</AccordionContent>
  </AccordionItem>
</Accordion>

Sub-components

| Component | Description | |-----------|-------------| | Accordion | Root container | | AccordionItem | Individual expandable item | | AccordionTrigger | Clickable header that toggles content | | AccordionContent | Collapsible content panel |

Props

Accordion

PropTypeDefaultDescription
valueAccordionValue—The controlled value of the item(s) that should be expanded. To render an uncontrolled accordion, use the `defaultValue` prop instead.
defaultValueAccordionValue—The uncontrolled value of the item(s) that should be initially expanded. To render a controlled accordion, use the `value` prop instead.
disabledenumfalseWhether the component should ignore user interaction.
hiddenUntilFoundenumfalseAllows the browser’s built-in page search to find and expand the panel contents. Overrides the `keepMounted` prop and uses `hidden="until-found"` to hide the element without removing it from the DOM.
keepMountedenumfalseWhether to keep the element in the DOM while the panel is closed. This prop is ignored when `hiddenUntilFound` is used.
loopFocusenumtrueWhether to loop keyboard focus back to the first item when the end of the list is reached while using the arrow keys.
onValueChange(value: AccordionValue, eventDetails: AccordionRootChangeEventDetails) => void—Event handler called when an accordion item is expanded or collapsed. Provides the new value as an argument.
multipleenumfalseWhether multiple items can be open at the same time.
orientationenum'vertical'The visual orientation of the accordion. Controls whether roving focus uses left/right or up/down arrow keys.
styleenum—Style applied to the element, or a function that returns a style object based on the component’s state.
classNameenum—CSS class applied to the element, or a function that returns a class based on the component’s state.
renderenum—Allows you to replace the component’s HTML element with a different tag, or compose it with another component. Accepts a `ReactElement` or a function that returns the element to render.

AccordionItem

PropTypeDefaultDescription
valueany—A unique value that identifies this accordion item. If no value is provided, a unique ID will be generated automatically. Use when controlling the accordion programmatically, or to set an initial open state. @example ```tsx <Accordion.Root value={['a']}> <Accordion.Item value="a" /> // initially open <Accordion.Item value="b" /> // initially closed </Accordion.Root> ```
onOpenChange(open: boolean, eventDetails: AccordionItemChangeEventDetails) => void—Event handler called when the panel is opened or closed.
styleenum—Style applied to the element, or a function that returns a style object based on the component’s state.
classNameenum—CSS class applied to the element, or a function that returns a class based on the component’s state.
renderenum—Allows you to replace the component’s HTML element with a different tag, or compose it with another component. Accepts a `ReactElement` or a function that returns the element to render.
disabledenumfalseWhether the component should ignore user interaction.