expansion_panels

Accordion

Expand/collapse sections for dense content.

Accordion Examples

Copy-ready examples with live previews.

Basic usage (single)

Default is type='single'.

Live preview

Content

Content

Basic (single)

import { useMemo } from "react";
import Accordion from "@/packages/ui/src/_components/accordion/Accordion";
import type { AccordionItem } from "@/packages/ui/src/_components/accordion/Accordion.type";

export default function Example() {
  const items = useMemo<AccordionItem[]>(
    () => [
      { id: "a1", title: "Account", content: <p>Content</p> },
      { id: "a2", title: "Billing", content: <p>Content</p> },
    ],
    []
  );

  return <Accordion items={items} />;
}

Multiple + defaultValue

Allows more than one item to be open.

Live preview

Content

Content

Content

Multiple

import { useMemo } from "react";
import Accordion from "@/packages/ui/src/_components/accordion/Accordion";
import type { AccordionItem } from "@/packages/ui/src/_components/accordion/Accordion.type";

export default function Example() {
  const items = useMemo<AccordionItem[]>(
    () => [
      { id: "a1", title: "Account", content: <p>Content</p> },
      { id: "a2", title: "Billing", content: <p>Content</p> },
      { id: "a3", title: "Security", content: <p>Content</p> },
    ],
    []
  );

  return (
    <Accordion
      type="multiple"
      defaultValue={["a1", "a3"]}
      items={items}
    />
  );
}

Controlled (single)

You control state with value + onValueChange.

When type='single', value is usually a string.

Live preview

Content

Content

Controlled (single)

import { useMemo, useState } from "react";
import Accordion from "@/packages/ui/src/_components/accordion/Accordion";
import type { AccordionItem, AccordionValue } from "@/packages/ui/src/_components/accordion/Accordion.type";

export default function Example() {
  const items = useMemo<AccordionItem[]>(
    () => [
      { id: "a1", title: "Account", content: <p>Content</p> },
      { id: "a2", title: "Billing", content: <p>Content</p> },
    ],
    []
  );

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

  return (
    <Accordion
      type="single"
      value={value}
      onValueChange={(next: AccordionValue) => setValue(String(next))}
      items={items}
    />
  );
}

Controlled (multiple)

Normalize to string[] for stable state.

When type='multiple', value is usually a string[].

Live preview

Content

Content

Content

Controlled (multiple)

import { useMemo, useState } from "react";
import Accordion from "@/packages/ui/src/_components/accordion/Accordion";
import type { AccordionItem, AccordionValue } from "@/packages/ui/src/_components/accordion/Accordion.type";

export default function Example() {
  const items = useMemo<AccordionItem[]>(
    () => [
      { id: "a1", title: "Account", content: <p>Content</p> },
      { id: "a2", title: "Billing", content: <p>Content</p> },
      { id: "a3", title: "Security", content: <p>Content</p> },
    ],
    []
  );

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

  return (
    <Accordion
      type="multiple"
      value={value}
      onValueChange={(next: AccordionValue) => setValue(next as string[])}
      items={items}
    />
  );
}

rightSlot (badge/action)

Per-item right slot for auxiliary UI.

Live preview

Content

Item rightSlot

import type { AccordionItem } from "@/_components/accordion/Accordion.type";

const items: AccordionItem[] = [
  {
    id: "n1",
    title: "What's new",
    rightSlot: <span style={{ padding: "2px 8px", borderRadius: 999 }}>NEW</span>,
    content: <p>Content</p>,
  },
];

Variant + size + chevron icon

Customize visual variant, size, and chevron icon settings.

Live preview

Content

Content

Variant + size + chevron

import { useMemo } from "react";
import Accordion from "@/packages/ui/src/_components/accordion/Accordion";
import type { AccordionItem } from "@/packages/ui/src/_components/accordion/Accordion.type";

export default function Example() {
  const items = useMemo<AccordionItem[]>(
    () => [
      { id: "a1", title: "Account", content: <p>Content</p> },
      { id: "a2", title: "Billing", content: <p>Content</p> },
    ],
    []
  );

  return (
    <Accordion
      variant="primary"
      size="large"
      chevronIconName="chevron_right"
      chevronIconStyle="rounded"
      items={items}
    />
  );
}

Disabled accordion

Disables all interaction.

Live preview

Content

Content

Disabled accordion

import { useMemo } from "react";
import Accordion from "@/packages/ui/src/_components/accordion/Accordion";
import type { AccordionItem } from "@/packages/ui/src/_components/accordion/Accordion.type";

export default function Example() {
  const items = useMemo<AccordionItem[]>(
    () => [
      { id: "a1", title: "Account", content: <p>Content</p> },
      { id: "a2", title: "Billing", content: <p>Content</p> },
    ],
    []
  );

  return <Accordion disabled items={items} />;
}

On this page

Accordion Props

Accordion — Props
PropTypeRequiredDefaultDescription
itemsAccordionItem[]YesItems to render (text/description/content + optional icon/slot/disabled).
type"single" | "multiple"No"single"Selection mode (one open at a time vs multiple).
collapsiblebooleanNotrueWhen type='single', allows closing the currently open item.
valuestring | string[]NoControlled value (string for single, string[] for multiple).
defaultValuestring | string[]NoUncontrolled initial value.
onValueChange(next: string | string[]) => voidNoFired when open items change (works for controlled/uncontrolled).
variant"neutral" | "neutral-inverse" | "primary" | "secondary" | "tertiary" | "success" | "warning" | "danger" | "info"NoSemantic/tone variant (mapped to classes).
size"small" | "medium" | "large"NoSize preset (mapped to classes).
chevronIconNamestringNo"expand_more"Chevron icon name (Material Symbols), e.g. "expand_more".
chevronIconStyle"outlined" | "rounded" | "sharp"NoFont family variant for Material Symbols chevron.
disabledbooleanNoDisables the whole accordion interaction.
classNamestringNoExtra className appended to the root element.
customStylesReact.CSSPropertiesNoInline styles applied to the root element.