component

Accordion

A collapsible disclosure component built on native <details> and <summary> elements. Use it to progressively reveal content — FAQs, settings panels, or any list of sections where showing everything at once would overwhelm the page.

Expansion Behavior

The type prop controls how many items can be open at once. single (default) collapses the previously open item when another opens — keeping the view focused. multiple lets any number of items be open simultaneously.

Use collapsible (default true) on single accordions to allow the open item to be collapsed back to nothing.

Single

What is Pindoba?

Pindoba is a design system providing framework-agnostic UI components for Astro, React, and Svelte.

How do I install it?

Install individual packages via pnpm, for example: pnpm add @pindoba/astro-accordion.

Is it customizable?

Yes — every component exposes a passThrough prop for custom styles and HTML attributes on each slot.

Multiple

What is Pindoba?

Pindoba is a design system providing framework-agnostic UI components for Astro, React, and Svelte.

How do I install it?

Install individual packages via pnpm, for example: pnpm add @pindoba/astro-accordion.

Is it customizable?

Yes — every component exposes a passThrough prop for custom styles and HTML attributes on each slot.

Disabled Item

Available Section

This item can be expanded and collapsed normally.

Disabled Section

This item is not accessible when disabled.

Another Available Section

This item is also available for interaction.

---
import Accordion from "../Accordion.astro";
import AccordionItem from "../AccordionItem.astro";
import { stack } from "@pindoba/styled-system/patterns";
---

<div
  class={stack({
    gap: "xl",
    direction: "column",
  })}
>
  <!-- Single mode (default) -->
  <div>
    <h3>Single</h3>
    <Accordion type="single" data-collapsible="true">
      <AccordionItem value="item-1" title="What is Pindoba?" open>
        <p>
          Pindoba is a design system providing framework-agnostic UI components
          for Astro, React, and Svelte.
        </p>
      </AccordionItem>
      <AccordionItem value="item-2" title="How do I install it?">
        <p>
          Install individual packages via pnpm, for example:
          <code>pnpm add @pindoba/astro-accordion</code>.
        </p>
      </AccordionItem>
      <AccordionItem value="item-3" title="Is it customizable?">
        <p>
          Yes — every component exposes a <code>passThrough</code> prop for custom
          styles and HTML attributes on each slot.
        </p>
      </AccordionItem>
    </Accordion>
  </div>

  <!-- Multiple mode -->
  <div>
    <h3>Multiple</h3>
    <Accordion type="multiple">
      <AccordionItem value="item-1" title="What is Pindoba?" open>
        <p>
          Pindoba is a design system providing framework-agnostic UI components
          for Astro, React, and Svelte.
        </p>
      </AccordionItem>
      <AccordionItem value="item-2" title="How do I install it?" open>
        <p>
          Install individual packages via pnpm, for example:
          <code>pnpm add @pindoba/astro-accordion</code>.
        </p>
      </AccordionItem>
      <AccordionItem value="item-3" title="Is it customizable?">
        <p>
          Yes — every component exposes a <code>passThrough</code> prop for custom
          styles and HTML attributes on each slot.
        </p>
      </AccordionItem>
    </Accordion>
  </div>

  <!-- Disabled item -->
  <div>
    <h3>Disabled Item</h3>
    <Accordion type="single">
      <AccordionItem value="item-1" title="Available Section" open>
        <p>This item can be expanded and collapsed normally.</p>
      </AccordionItem>
      <AccordionItem value="item-2" title="Disabled Section" disabled>
        <p>This item is not accessible when disabled.</p>
      </AccordionItem>
      <AccordionItem value="item-3" title="Another Available Section">
        <p>This item is also available for interaction.</p>
      </AccordionItem>
    </Accordion>
  </div>
</div>

Size

Three sizes scale the trigger padding, content padding, and font size together. The size is set once on the root <Accordion> and inherited by every item.

Small

Compact section

Small size uses tighter padding and a smaller font — suitable for dense layouts or secondary content areas.

Another compact section

Inherits size="sm" from the root — no need to repeat on each item.

Medium (default)

Standard section

Medium size is the default — balanced padding and font size for most use cases.

Another standard section

Inherits size="md" from the root.

Large

Spacious section

Large size uses generous padding and a larger font — ideal for prominent content or marketing pages.

Another spacious section

Inherits size="lg" from the root.

Per-item override

Small (inherited)

This item uses the root's size="sm".

Large (override)

This item sets its own size="lg", which overrides the root's sm.

Small again (inherited)

Back to inheriting from the root.

---
import Accordion from "../Accordion.astro";
import AccordionItem from "../AccordionItem.astro";
import { stack } from "@pindoba/styled-system/patterns";
---

<div
  class={stack({
    gap: "xl",
    direction: "column",
  })}
>
  <!-- Small — size on the root cascades to items via CSS variables -->
  <div>
    <h3>Small</h3>
    <Accordion type="single" size="sm">
      <AccordionItem value="item-1" title="Compact section" open>
        <p>
          Small size uses tighter padding and a smaller font — suitable for
          dense layouts or secondary content areas.
        </p>
      </AccordionItem>
      <AccordionItem value="item-2" title="Another compact section">
        <p>
          Inherits <code>size="sm"</code> from the root — no need to repeat on each
          item.
        </p>
      </AccordionItem>
    </Accordion>
  </div>

  <!-- Medium (default) -->
  <div>
    <h3>Medium (default)</h3>
    <Accordion type="single" size="md">
      <AccordionItem value="item-1" title="Standard section" open>
        <p>
          Medium size is the default — balanced padding and font size for most
          use cases.
        </p>
      </AccordionItem>
      <AccordionItem value="item-2" title="Another standard section">
        <p>Inherits <code>size="md"</code> from the root.</p>
      </AccordionItem>
    </Accordion>
  </div>

  <!-- Large -->
  <div>
    <h3>Large</h3>
    <Accordion type="single" size="lg">
      <AccordionItem value="item-1" title="Spacious section" open>
        <p>
          Large size uses generous padding and a larger font — ideal for
          prominent content or marketing pages.
        </p>
      </AccordionItem>
      <AccordionItem value="item-2" title="Another spacious section">
        <p>Inherits <code>size="lg"</code> from the root.</p>
      </AccordionItem>
    </Accordion>
  </div>

  <!-- Per-item override -->
  <div>
    <h3>Per-item override</h3>
    <Accordion type="single" size="sm">
      <AccordionItem value="item-1" title="Small (inherited)" open>
        <p>This item uses the root's <code>size="sm"</code>.</p>
      </AccordionItem>
      <AccordionItem value="item-2" title="Large (override)" size="lg">
        <p>
          This item sets its own <code>size="lg"</code>, which overrides the
          root's <code>sm</code>.
        </p>
      </AccordionItem>
      <AccordionItem value="item-3" title="Small again (inherited)">
        <p>Back to inheriting from the root.</p>
      </AccordionItem>
    </Accordion>
  </div>
</div>

Items Array

For data-driven usage, pass an items array to <Accordion> and it renders one <AccordionItem> per entry. Root-level props (size, feedback, background, …) act as defaults; each entry can override via its own fields. Body content is provided per framework: named slots in Astro (<Fragment slot="<value>">), named snippets or the snippets map in Svelte (keyed by each item’s value). For rich custom trigger content, fall back to slot composition with <AccordionItem> directly.

Items array with cascaded defaults

First

Rendered from a named slot matching the item's value. Inherits size="md" and feedback="primary" from the root.

Second

Same defaults as the first.

Third

Also inherits from the root.

Per-item overrides

Default (size=sm, feedback=neutral)

Uses root defaults.

Overrides size

Item sets size: "lg", which wins over the root's sm.

Overrides feedback

Item sets feedback: "danger", which wins over the root's neutral.

Disabled

Set per item.

With subtitles

Authentication

OAuth providers and session settings

Configure sign-in options.

Database

Connection strings, pooling, migrations

Manage database connectivity.

Storage

File uploads and CDN

Configure object storage and CDN.

---
import Accordion from "../Accordion.astro";
import { stack } from "@pindoba/styled-system/patterns";
---

<div
  class={stack({
    gap: "xl",
    direction: "column",
  })}
>
  <!-- Basic items array with named slots -->
  <div>
    <h3>Items array with cascaded defaults</h3>
    <Accordion
      type="single"
      size="md"
      feedback="primary"
      items={[
        { value: "first", title: "First", open: true },
        { value: "second", title: "Second" },
        { value: "third", title: "Third" },
      ]}
    >
      <Fragment slot="first">
        <p>
          Rendered from a named slot matching the item's <code>value</code>.
          Inherits <code>size="md"</code> and <code>feedback="primary"</code> from
          the root.
        </p>
      </Fragment>
      <Fragment slot="second">
        <p>Same defaults as the first.</p>
      </Fragment>
      <Fragment slot="third">
        <p>Also inherits from the root.</p>
      </Fragment>
    </Accordion>
  </div>

  <!-- Per-item overrides -->
  <div>
    <h3>Per-item overrides</h3>
    <Accordion
      type="multiple"
      size="sm"
      feedback="neutral"
      items={[
        {
          value: "default",
          title: "Default (size=sm, feedback=neutral)",
          open: true,
        },
        { value: "larger", title: "Overrides size", size: "lg", open: true },
        { value: "danger", title: "Overrides feedback", feedback: "danger" },
        { value: "disabled", title: "Disabled", disabled: true },
      ]}
    >
      <Fragment slot="default">
        <p>Uses root defaults.</p>
      </Fragment>
      <Fragment slot="larger">
        <p>
          Item sets <code>size: "lg"</code>, which wins over the root's <code
            >sm</code
          >.
        </p>
      </Fragment>
      <Fragment slot="danger">
        <p>
          Item sets <code>feedback: "danger"</code>, which wins over the root's
          <code>neutral</code>.
        </p>
      </Fragment>
      <Fragment slot="disabled">
        <p>Set per item.</p>
      </Fragment>
    </Accordion>
  </div>

  <!-- Subtitles -->
  <div>
    <h3>With subtitles</h3>
    <Accordion
      type="single"
      size="md"
      items={[
        {
          value: "auth",
          title: "Authentication",
          subtitle: "OAuth providers and session settings",
        },
        {
          value: "db",
          title: "Database",
          subtitle: "Connection strings, pooling, migrations",
        },
        {
          value: "storage",
          title: "Storage",
          subtitle: "File uploads and CDN",
        },
      ]}
    >
      <Fragment slot="auth">
        <p>Configure sign-in options.</p>
      </Fragment>
      <Fragment slot="db">
        <p>Manage database connectivity.</p>
      </Fragment>
      <Fragment slot="storage">
        <p>Configure object storage and CDN.</p>
      </Fragment>
    </Accordion>
  </div>
</div>

Feedback Colors

Accordion items use Panel under the hood — pass feedback and border on the root to color all items consistently. Use feedback for semantic meaning: primary for key content, success for completed flows, warning for notices, and danger for critical information.

Neutral

General information

Neutral is the default feedback color — use it for standard content without any special semantic meaning.

Additional details

Each item inherits the feedback color and border from the root.

Primary

Getting started

Primary feedback applies the brand color palette — use it to highlight important content or onboarding steps.

Next steps

Each item inherits the feedback color and border from the root.

Success

Completed tasks

Success feedback conveys positive outcomes — use it for completed steps, confirmation flows, or resolved states.

What's next

Each item inherits the feedback color and border from the root.

Warning

Deprecation notice

Warning feedback draws attention to caution states — use it for deprecation notices, rate limits, or soft restrictions.

Migration guide

Each item inherits the feedback color and border from the root.

Danger

Breaking changes

Danger feedback signals critical or destructive information — use it for breaking changes, error states, or irreversible actions.

How to resolve

Each item inherits the feedback color and border from the root.

---
import Accordion from "../Accordion.astro";
import AccordionItem from "../AccordionItem.astro";
import { stack } from "@pindoba/styled-system/patterns";
---

<div
  class={stack({
    gap: "xl",
    direction: "column",
  })}
>
  <!-- Neutral -->
  <div>
    <h3>Neutral</h3>
    <Accordion type="single" feedback="neutral">
      <AccordionItem value="item-1" title="General information" open>
        <p>
          Neutral is the default feedback color — use it for standard content
          without any special semantic meaning.
        </p>
      </AccordionItem>
      <AccordionItem value="item-2" title="Additional details">
        <p>Each item inherits the feedback color and border from the root.</p>
      </AccordionItem>
    </Accordion>
  </div>

  <!-- Primary -->
  <div>
    <h3>Primary</h3>
    <Accordion type="single" feedback="primary">
      <AccordionItem value="item-1" title="Getting started" open>
        <p>
          Primary feedback applies the brand color palette — use it to highlight
          important content or onboarding steps.
        </p>
      </AccordionItem>
      <AccordionItem value="item-2" title="Next steps">
        <p>Each item inherits the feedback color and border from the root.</p>
      </AccordionItem>
    </Accordion>
  </div>

  <!-- Success -->
  <div>
    <h3>Success</h3>
    <Accordion type="single" feedback="success">
      <AccordionItem value="item-1" title="Completed tasks" open>
        <p>
          Success feedback conveys positive outcomes — use it for completed
          steps, confirmation flows, or resolved states.
        </p>
      </AccordionItem>
      <AccordionItem value="item-2" title="What's next">
        <p>Each item inherits the feedback color and border from the root.</p>
      </AccordionItem>
    </Accordion>
  </div>

  <!-- Warning -->
  <div>
    <h3>Warning</h3>
    <Accordion type="single" feedback="warning">
      <AccordionItem value="item-1" title="Deprecation notice" open>
        <p>
          Warning feedback draws attention to caution states — use it for
          deprecation notices, rate limits, or soft restrictions.
        </p>
      </AccordionItem>
      <AccordionItem value="item-2" title="Migration guide">
        <p>Each item inherits the feedback color and border from the root.</p>
      </AccordionItem>
    </Accordion>
  </div>

  <!-- Danger -->
  <div>
    <h3>Danger</h3>
    <Accordion type="single" feedback="danger">
      <AccordionItem value="item-1" title="Breaking changes" open>
        <p>
          Danger feedback signals critical or destructive information — use it
          for breaking changes, error states, or irreversible actions.
        </p>
      </AccordionItem>
      <AccordionItem value="item-2" title="How to resolve">
        <p>Each item inherits the feedback color and border from the root.</p>
      </AccordionItem>
    </Accordion>
  </div>
</div>

Emphasis

emphasis follows panel’s three-tier model. primary fills each item with the feedback accent surface and contrast text. secondary (default) uses the feedback-tinted soft surface — the standard accordion look. tertiary keeps the surface neutral but tints the trigger text and border with the feedback color, useful when a tinted background would compete with the surrounding page.

Set emphasis per <AccordionItem> for slot-composed accordions (each child carries its own panel surface). When you use the items array on <Accordion>, the root-level emphasis acts as a default for every item — same shape as background, border, and padding.

Primary

Filled accent surface

Primary emphasis fills each item with the feedback's accent surface and uses contrast text. Use it for the most prominent accordion sections.

More detail

The trigger and indicator read against the bold surface.

Secondary (default)

Feedback-tinted soft surface

Secondary emphasis paints each item with the feedback's soft surface. This is the default — most accordions use it.

More detail

Trigger text picks up the feedback's accent color.

Tertiary

Neutral surface, feedback text

Tertiary emphasis keeps the surface neutral but tints the text and border with the feedback color. Useful when a tinted background would compete with surrounding content.

More detail

The trigger and content read against neutral surface.

---
import Accordion from "../Accordion.astro";
import AccordionItem from "../AccordionItem.astro";
import { stack } from "@pindoba/styled-system/patterns";
---

<div class={stack({ gap: "xl", direction: "column" })}>
  <!-- Primary — filled feedback accent surface -->
  <div>
    <h3>Primary</h3>
    <Accordion type="single" feedback="primary">
      <AccordionItem
        value="item-1"
        title="Filled accent surface"
        emphasis="primary"
        open
      >
        <p>
          Primary emphasis fills each item with the feedback's accent surface
          and uses contrast text. Use it for the most prominent accordion
          sections.
        </p>
      </AccordionItem>
      <AccordionItem value="item-2" title="More detail" emphasis="primary">
        <p>The trigger and indicator read against the bold surface.</p>
      </AccordionItem>
    </Accordion>
  </div>

  <!-- Secondary (default) — feedback-tinted soft surface -->
  <div>
    <h3>Secondary (default)</h3>
    <Accordion type="single" feedback="primary">
      <AccordionItem value="item-1" title="Feedback-tinted soft surface" open>
        <p>
          Secondary emphasis paints each item with the feedback's soft surface.
          This is the default — most accordions use it.
        </p>
      </AccordionItem>
      <AccordionItem value="item-2" title="More detail">
        <p>Trigger text picks up the feedback's accent color.</p>
      </AccordionItem>
    </Accordion>
  </div>

  <!-- Tertiary — neutral surface, feedback-tinted text -->
  <div>
    <h3>Tertiary</h3>
    <Accordion type="single" feedback="primary">
      <AccordionItem
        value="item-1"
        title="Neutral surface, feedback text"
        emphasis="tertiary"
        open
      >
        <p>
          Tertiary emphasis keeps the surface neutral but tints the text and
          border with the feedback color. Useful when a tinted background would
          compete with surrounding content.
        </p>
      </AccordionItem>
      <AccordionItem value="item-2" title="More detail" emphasis="tertiary">
        <p>The trigger and content read against neutral surface.</p>
      </AccordionItem>
    </Accordion>
  </div>
</div>

Rich Triggers

Accordion items use Banner internally for their trigger area. This means you can add a subtitle, inline icons via headingLeading / headingTrailing, and a trailing element at the far right of the trigger row — all without replacing the whole trigger.

Subtitle

Authentication

Configure OAuth providers and session settings

Add a subtitle to provide secondary context below the title without losing the clickable trigger area.

Database

Connection strings, pooling, and migrations

Configure your database connection and migration settings here.

Storage

File uploads and CDN configuration

Set up file storage providers and CDN delivery options.

Heading Trailing

Open Issues

12

Use the heading-trailing slot to place a badge, count, or status indicator inline with the title text.

Pull Requests

3

Active pull requests waiting for review.

Deployments

1

Recent deployment activity and logs.

Leading Icon

Profile

Use the heading-leading slot to prepend a Stamp icon directly beside the title text.

Notifications

Notification preferences and delivery settings.

Security

Two-factor authentication and session management.

Preferences

General application preferences and defaults.

Trailing Action

Environment Variables

12 variables

Use the trailing slot to place content at the far right of the trigger row — outside the title/subtitle, before the expand indicator.

Build Cache

Active

Current build cache status and invalidation controls.

---
import Accordion from "../Accordion.astro";
import AccordionItem from "../AccordionItem.astro";
import Stamp from "@pindoba/astro-stamp";
import { Icon } from "astro-icon/components";
import { stack } from "@pindoba/styled-system/patterns";
import { css } from "@pindoba/styled-system/css";

const badge = css({
  display: "inline-flex",
  alignItems: "center",
  px: "xs",
  py: "3xs",
  borderRadius: "full",
  fontSize: "xs",
  fontWeight: "semibold",
  background: "colorPalette.surface.step.3",
  color: "colorPalette.text",
});
---

<div
  class={stack({
    gap: "xl",
    direction: "column",
  })}
>
  <!-- Subtitle -->
  <div>
    <h3>Subtitle</h3>
    <Accordion type="single" collapsible>
      <AccordionItem
        value="item-1"
        title="Authentication"
        subtitle="Configure OAuth providers and session settings"
      >
        <Stamp
          slot="leading"
          feedback="neutral"
          emphasis="secondary"
          shape="square"
        >
          <Icon name="lucide:key-round" />
        </Stamp>
        <p>
          Add a <code>subtitle</code> to provide secondary context below the title
          without losing the clickable trigger area.
        </p>
      </AccordionItem>
      <AccordionItem
        value="item-2"
        title="Database"
        subtitle="Connection strings, pooling, and migrations"
      >
        <Stamp
          slot="leading"
          feedback="neutral"
          emphasis="secondary"
          shape="square"
        >
          <Icon name="lucide:database" />
        </Stamp>
        <p>Configure your database connection and migration settings here.</p>
      </AccordionItem>
      <AccordionItem
        value="item-3"
        title="Storage"
        subtitle="File uploads and CDN configuration"
      >
        <Stamp
          slot="leading"
          feedback="neutral"
          emphasis="secondary"
          shape="square"
        >
          <Icon name="lucide:hard-drive" />
        </Stamp>
        <p>Set up file storage providers and CDN delivery options.</p>
      </AccordionItem>
    </Accordion>
  </div>

  <!-- Heading trailing — count or status badge -->
  <div>
    <h3>Heading Trailing</h3>
    <Accordion type="multiple">
      <AccordionItem value="item-1" title="Open Issues">
        <span slot="heading-trailing" class={badge}>12</span>
        <p>
          Use the <code>heading-trailing</code> slot to place a badge, count, or status
          indicator inline with the title text.
        </p>
      </AccordionItem>
      <AccordionItem value="item-2" title="Pull Requests">
        <span slot="heading-trailing" class={badge}>3</span>
        <p>Active pull requests waiting for review.</p>
      </AccordionItem>
      <AccordionItem value="item-3" title="Deployments">
        <span slot="heading-trailing" class={badge}>1</span>
        <p>Recent deployment activity and logs.</p>
      </AccordionItem>
    </Accordion>
  </div>

  <!-- Leading icon -->
  <div>
    <h3>Leading Icon</h3>
    <Accordion type="single" collapsible>
      <AccordionItem value="item-1" title="Profile">
        <Stamp
          slot="heading-leading"
          feedback="primary"
          emphasis="secondary"
          shape="circle"
          size="xs"
        >
          <Icon name="lucide:user" />
        </Stamp>
        <p>
          Use the <code>heading-leading</code> slot to prepend a Stamp icon directly
          beside the title text.
        </p>
      </AccordionItem>
      <AccordionItem value="item-2" title="Notifications">
        <Stamp
          slot="heading-leading"
          feedback="warning"
          emphasis="secondary"
          shape="circle"
          size="xs"
        >
          <Icon name="lucide:bell" />
        </Stamp>
        <p>Notification preferences and delivery settings.</p>
      </AccordionItem>
      <AccordionItem value="item-3" title="Security">
        <Stamp
          slot="heading-leading"
          feedback="success"
          emphasis="secondary"
          shape="circle"
          size="xs"
        >
          <Icon name="lucide:shield" />
        </Stamp>
        <p>Two-factor authentication and session management.</p>
      </AccordionItem>
      <AccordionItem value="item-4" title="Preferences">
        <Stamp
          slot="heading-leading"
          feedback="neutral"
          emphasis="secondary"
          shape="circle"
          size="xs"
        >
          <Icon name="lucide:settings" />
        </Stamp>
        <p>General application preferences and defaults.</p>
      </AccordionItem>
    </Accordion>
  </div>

  <!-- Trailing row action -->
  <div>
    <h3>Trailing Action</h3>
    <Accordion type="single" collapsible>
      <AccordionItem value="item-1" title="Environment Variables">
        <span
          slot="trailing"
          class={css({
            fontSize: "xs",
            color: "neutral.text.muted",
            fontWeight: "normal",
            flexShrink: 0,
          })}
        >
          12 variables
        </span>
        <p>
          Use the <code>trailing</code> slot to place content at the far right of
          the trigger row — outside the title/subtitle, before the expand indicator.
        </p>
      </AccordionItem>
      <AccordionItem value="item-2" title="Build Cache">
        <span
          slot="trailing"
          class={css({
            fontSize: "xs",
            color: "success.text",
            fontWeight: "semibold",
            flexShrink: 0,
          })}
        >
          Active
        </span>
        <p>Current build cache status and invalidation controls.</p>
      </AccordionItem>
    </Accordion>
  </div>
</div>

Custom Styling

The passThrough prop on AccordionItem reaches into any slot — item, trigger, indicator, or content. Use style for Panda CSS overrides and props for extra HTML attributes. On the root Accordion, passThrough.root applies to the wrapper <div>.

Custom Trigger Style

src/index.ts

Use passThrough.trigger.style on an item to restyle its trigger — here applying a monospace font for a file-tree appearance.

src/components/Button.astro

The style is applied via Panda CSS css.raw(), giving you full access to design tokens and responsive utilities.

Custom Content Style

Separated content area

Use passThrough.content.style on an item to customize its content area — here adding a bold top border using the current feedback color palette.

Another section

Each item's content slot gets the same custom styles.

ARIA Attributes

What does this do?

Use passThrough.root.props on the accordion to forward HTML attributes to the root element — here adding role="region" and an aria-label for screen reader context.

Why use passThrough?

passThrough is the escape hatch for any customization not covered by component props. It keeps the public API clean while remaining fully flexible.

---
import Accordion from "../Accordion.astro";
import AccordionItem from "../AccordionItem.astro";
import { stack } from "@pindoba/styled-system/patterns";
import { css } from "@pindoba/styled-system/css";
---

<div
  class={stack({
    gap: "xl",
    direction: "column",
  })}
>
  <!-- Custom trigger style -->
  <div>
    <h3>Custom Trigger Style</h3>
    <Accordion type="single">
      <AccordionItem
        value="item-1"
        title="src/index.ts"
        open
        passThrough={{
          trigger: {
            style: css.raw({
              fontFamily: "mono",
              fontSize: "sm",
              letterSpacing: "0.04em",
            }),
          },
        }}
      >
        <p>
          Use <code>passThrough.trigger.style</code> on an item to restyle its trigger
          — here applying a monospace font for a file-tree appearance.
        </p>
      </AccordionItem>
      <AccordionItem
        value="item-2"
        title="src/components/Button.astro"
        passThrough={{
          trigger: {
            style: css.raw({
              fontFamily: "mono",
              fontSize: "sm",
              letterSpacing: "0.04em",
            }),
          },
        }}
      >
        <p>
          The style is applied via Panda CSS <code>css.raw()</code>, giving you
          full access to design tokens and responsive utilities.
        </p>
      </AccordionItem>
    </Accordion>
  </div>

  <!-- Custom content style -->
  <div>
    <h3>Custom Content Style</h3>
    <Accordion type="single" feedback="primary">
      <AccordionItem
        value="item-1"
        title="Separated content area"
        open
        passThrough={{
          content: {
            style: css.raw({
              borderTop: "2px solid",
              borderColor: "colorPalette.border.bold",
            }),
          },
        }}
      >
        <p>
          Use <code>passThrough.content.style</code> on an item to customize its content
          area — here adding a bold top border using the current feedback color palette.
        </p>
      </AccordionItem>
      <AccordionItem
        value="item-2"
        title="Another section"
        passThrough={{
          content: {
            style: css.raw({
              borderTop: "2px solid",
              borderColor: "colorPalette.border.bold",
            }),
          },
        }}
      >
        <p>Each item's content slot gets the same custom styles.</p>
      </AccordionItem>
    </Accordion>
  </div>

  <!-- ARIA attributes via passThrough props -->
  <div>
    <h3>ARIA Attributes</h3>
    <Accordion
      type="single"
      passThrough={{
        root: {
          props: {
            role: "region",
            "aria-label": "Frequently asked questions",
          },
        },
      }}
    >
      <AccordionItem value="item-1" title="What does this do?" open>
        <p>
          Use <code>passThrough.root.props</code> on the accordion to forward HTML
          attributes to the root element — here adding
          <code>role="region"</code> and an <code>aria-label</code> for screen reader
          context.
        </p>
      </AccordionItem>
      <AccordionItem value="item-2" title="Why use passThrough?">
        <p>
          <code>passThrough</code> is the escape hatch for any customization not covered
          by component props. It keeps the public API clean while remaining fully
          flexible.
        </p>
      </AccordionItem>
    </Accordion>
  </div>
</div>

Props

Accordion

props · 15 total
prop type default req description
type "single""multiple" "single" Expansion behavior. single allows one item open at a time and collapses siblings. multiple allows any number of items to be open simultaneously.
collapsible boolean true In single mode, allow the open item to be collapsed back to nothing. Has no effect in multiple mode.
value string[] [] Controlled list of expanded item values. Bind this prop to track or set expansion state externally.
defaultValue string[] undefined Uncontrolled initial list of expanded item values.
onValueChange (value: string[]) => void undefined Callback fired whenever the expanded set changes.
disabled boolean false Disable the entire accordion and all its items.
size "sm""md""lg" "md" Controls trigger padding, content padding, and font size for all items.
feedback "neutral""primary""success""warning""danger" undefined Semantic feedback color applied to each item's Panel background. Inherited by all items unless overridden per-item.
emphasis "primary""secondary""tertiary" undefined Visual emphasis applied to each item's Panel. primary: solid feedback accent surface with contrast text. secondary: feedback-tinted soft surface (default). tertiary: neutral surface with bold feedback…

emphasis

Visual emphasis applied to each item's Panel. primary: solid feedback accent surface with contrast text. secondary: feedback-tinted soft surface (default). tertiary: neutral surface with bold feedback-tinted text. Inherited by all items unless overridden per-item.

Type "primary" | "secondary" | "tertiary"
Default undefined
Required No
background "surface.soft""surface.step.1""surface.step.2""surface.step.3""surface.deep""transparent" undefined Surface level for each item's Panel background. Inherited by all items unless overridden per-item.
border "none""default""bold""muted" undefined Box-shadow ring border applied to each item. Uses box-shadow so it is layout-neutral.
padding "none""5xs""4xs""3xs""2xs""xs""sm""md""lg""xl""2xl""3xl""4xl""5xl""6xl""7xl""8xl""9xl""10xl""11xl" undefined Internal padding for each item's Panel. Inherited by all items unless overridden per-item.
radius "none""5xs""4xs""3xs""2xs""xs""sm""md""lg""xl""2xl""3xl""4xl""5xl""6xl""7xl""8xl""9xl""10xl""11xl""full" undefined Border radius for each item's Panel. Inherited by all items unless overridden per-item.
passThrough { root?: { style?: SystemStyleObject; props?: Record<string, unknown> }; item?: { style?: SystemStyleObject; props?: Record<string, unknown> }; trigger?: { style?: SystemStyleObject; props?: Record<string, unknown> }; indicator?: { style?: SystemStyleObject; props?: Record<string, unknown> }; content?: { style?: SystemStyleObject; props?: Record<string, unknown> } } undefined Custom styling and props for accordion slots. Applies to all items.
...rest HTMLAttributes<HTMLDivElement> - Standard HTML div attributes.

AccordionItem

props · 21 total
prop type default req description
value string - Unique identifier for this item within the accordion. Used to track expansion state.
title string undefined Plain-text label rendered in the trigger. Use the trigger snippet (Svelte) or named slot (Astro) for fully custom content.
subtitle string undefined Secondary text rendered below the title in the trigger.
headingLeading Snippet undefined Snippet (Svelte) or heading-leading slot (Astro) rendered inline before the title text.
headingTrailing Snippet undefined Snippet (Svelte) or heading-trailing slot (Astro) rendered inline after the title text — ideal for counts or status badges.
subheadingLeading Snippet undefined Snippet (Svelte) or subheading-leading slot (Astro) rendered inline before the subtitle.
subheadingTrailing Snippet undefined Snippet (Svelte) or subheading-trailing slot (Astro) rendered inline after the subtitle.
leading Snippet undefined Snippet (Svelte) or leading slot (Astro) placed at the far left of the trigger row.
trailing Snippet undefined Snippet (Svelte) or trailing slot (Astro) placed at the far right of the trigger row, before the expand indicator.
bannerPassThrough BannerProps['passThrough'] undefined passThrough forwarded to the internal Banner that renders the trigger title area.
disabled boolean false Disable this individual item, preventing interaction.
open boolean false Initial open state. In Svelte this is controlled via the root accordion's value prop; in Astro it sets the native details open attribute directly.
size "sm""md""lg" undefined Override the size for this item only. Falls back to the root accordion's size.
feedback "neutral""primary""success""warning""danger" undefined Override the feedback color for this item only. Falls back to the root accordion's feedback.
emphasis "primary""secondary""tertiary" undefined Override the emphasis for this item only. Falls back to the root accordion's emphasis.
background "surface.soft""surface.step.1""surface.step.2""surface.step.3""surface.deep""transparent" undefined Override the background for this item only.
border "none""default""bold""muted" undefined Override the border for this item only.
padding "none""5xs""4xs""3xs""2xs""xs""sm""md""lg""xl""2xl""3xl""4xl""5xl""6xl""7xl""8xl""9xl""10xl""11xl" undefined Override the padding for this item only.
radius "none""5xs""4xs""3xs""2xs""xs""sm""md""lg""xl""2xl""3xl""4xl""5xl""6xl""7xl""8xl""9xl""10xl""11xl""full" undefined Override the border radius for this item only.
passThrough { item?: { style?: SystemStyleObject; props?: Record<string, unknown> }; trigger?: { style?: SystemStyleObject; props?: Record<string, unknown> }; indicator?: { style?: SystemStyleObject; props?: Record<string, unknown> }; content?: { style?: SystemStyleObject; props?: Record<string, unknown> } } undefined Custom styling and props for this item's slots. Takes precedence over the root accordion's passThrough.
...rest HTMLAttributes<HTMLDetailsElement> - Standard HTML details attributes.