Skip to content

Accordion

Experimental Alpha

This library is a work-in-progress. We are releasing it early to gather feedback, but it is not ready for production.

An accordion is a vertically stacked set of interactive headings that each reveal a section of content. Accordions are ideal for presenting FAQs, feature lists, and other content that benefits from progressive disclosure.

Examples

Vue
Lit
React
Live Preview

Basic Accordion (Default)

By default, the Accordion provides a chevron which points down when closed, then rotates 180° to point up when open. See below for how to opt out or use different indicators.

Chevron Section 1

Default chevron indicator with smooth rotation

Chevron Section 2

Click to see the 180° rotation animation

Chevron Section 3

Classic accordion indicator style

X Indicator

Plus rotated 180° (upside down) when closed, rotates to 45° forming an X when open.

X Indicator Section 1

Plus transforms into X when opened

X Indicator Section 2

Smooth transition from plus to X

X Indicator Section 3

Modern accordion indicator style

Plus/Minus Indicator

Plus transitions to minus when open with smooth animation.

Plus/Minus Section 1

Plus changes to minus when opened

Plus/Minus Section 2

Classic expand/collapse indicator

Plus/Minus Section 3

Clear visual indication of state

No Indicator

Accordion items without any visual indicator.

No Indicator Section 1

Clean header without indicator icon

No Indicator Section 2

Minimal design focused on content

No Indicator Section 3

Simple accordion without visual clutter

Bordered

Bordered Item 1

This accordion has borders on the headers

Bordered Item 2

Another bordered item

Bordered Item 3

Third bordered item

With Background

Background Item 1

This accordion has background color on headers

Background Item 2

Another item with background

Background Item 3

Third item with background

One Item Open

Closed Item

This item starts closed

Open Item

This item starts open

Another Closed Item

This item also starts closed

Disabled State

Enabled Item

This item can be toggled

Disabled Item

This item cannot be toggled

Another Enabled Item

This item can also be toggled

Rich Content

Features
  • Accessible by default with ARIA attributes
  • Keyboard navigation support
  • Customizable heading levels
  • Multiple styling options
Code Example
<VueAccordionItem use-chevron>
  <VueAccordionHeader>Title</VueAccordionHeader>
  <VueAccordionContent>Content</VueAccordionContent>
</VueAccordionItem>
More Information

Accordions are great for:

  • FAQ sections
  • Feature lists
  • Documentation
  • Progressive disclosure

CSS Parts Customization

Customize accordion appearance using CSS Shadow Parts without breaking encapsulation.

Minimal Border Style

This variant uses a minimal border-left design with subtle styling.

Another Minimal Item

Clean and simple styling focused on content hierarchy.

View Vue Code
<template>
  <section>
    <div class="mbe4">
      <h2>Basic Accordion (Default)</h2>
      <p
        class="mbe2"
        style="color: var(--ag-text-secondary); font-size: 0.875rem;"
      >
        By default, the Accordion provides a chevron which points down when closed, then rotates 180° to point up when open. See below for how to opt out or use different indicators.
      </p>
    </div>
    <div class="stacked mbe4">
      <VueAccordion>
        <VueAccordionItem use-chevron>
          <VueAccordionHeader>Chevron Section 1</VueAccordionHeader>
          <VueAccordionContent>
            <p>Default chevron indicator with smooth rotation</p>
          </VueAccordionContent>
        </VueAccordionItem>
        <VueAccordionItem use-chevron>
          <VueAccordionHeader>Chevron Section 2</VueAccordionHeader>
          <VueAccordionContent>
            <p>Click to see the 180° rotation animation</p>
          </VueAccordionContent>
        </VueAccordionItem>
        <VueAccordionItem use-chevron>
          <VueAccordionHeader>Chevron Section 3</VueAccordionHeader>
          <VueAccordionContent>
            <p>Classic accordion indicator style</p>
          </VueAccordionContent>
        </VueAccordionItem>
      </VueAccordion>
    </div>

    <div class="mbe4">
      <h2>X Indicator</h2>
      <p
        class="mbe2"
        style="color: var(--ag-text-secondary); font-size: 0.875rem;"
      >
        Plus rotated 180° (upside down) when closed, rotates to 45° forming an X when open.
      </p>
    </div>
    <div class="stacked mbe4">
      <VueAccordion>
        <VueAccordionItem use-x>
          <VueAccordionHeader>X Indicator Section 1</VueAccordionHeader>
          <VueAccordionContent>
            <p>Plus transforms into X when opened</p>
          </VueAccordionContent>
        </VueAccordionItem>
        <VueAccordionItem use-x>
          <VueAccordionHeader>X Indicator Section 2</VueAccordionHeader>
          <VueAccordionContent>
            <p>Smooth transition from plus to X</p>
          </VueAccordionContent>
        </VueAccordionItem>
        <VueAccordionItem use-x>
          <VueAccordionHeader>X Indicator Section 3</VueAccordionHeader>
          <VueAccordionContent>
            <p>Modern accordion indicator style</p>
          </VueAccordionContent>
        </VueAccordionItem>
      </VueAccordion>
    </div>

    <div class="mbe4">
      <h2>Plus/Minus Indicator</h2>
      <p
        class="mbe2"
        style="color: var(--ag-text-secondary); font-size: 0.875rem;"
      >
        Plus transitions to minus when open with smooth animation.
      </p>
    </div>
    <div class="stacked mbe4">
      <VueAccordion>
        <VueAccordionItem use-minus>
          <VueAccordionHeader>Plus/Minus Section 1</VueAccordionHeader>
          <VueAccordionContent>
            <p>Plus changes to minus when opened</p>
          </VueAccordionContent>
        </VueAccordionItem>
        <VueAccordionItem use-minus>
          <VueAccordionHeader>Plus/Minus Section 2</VueAccordionHeader>
          <VueAccordionContent>
            <p>Classic expand/collapse indicator</p>
          </VueAccordionContent>
        </VueAccordionItem>
        <VueAccordionItem use-minus>
          <VueAccordionHeader>Plus/Minus Section 3</VueAccordionHeader>
          <VueAccordionContent>
            <p>Clear visual indication of state</p>
          </VueAccordionContent>
        </VueAccordionItem>
      </VueAccordion>
    </div>

    <div class="mbe4">
      <h2>No Indicator</h2>
      <p
        class="mbe2"
        style="color: var(--ag-text-secondary); font-size: 0.875rem;"
      >
        Accordion items without any visual indicator.
      </p>
    </div>
    <div class="stacked mbe4">
      <VueAccordion>
        <VueAccordionItem no-indicator>
          <VueAccordionHeader>No Indicator Section 1</VueAccordionHeader>
          <VueAccordionContent>
            <p>Clean header without indicator icon</p>
          </VueAccordionContent>
        </VueAccordionItem>
        <VueAccordionItem no-indicator>
          <VueAccordionHeader>No Indicator Section 2</VueAccordionHeader>
          <VueAccordionContent>
            <p>Minimal design focused on content</p>
          </VueAccordionContent>
        </VueAccordionItem>
        <VueAccordionItem no-indicator>
          <VueAccordionHeader>No Indicator Section 3</VueAccordionHeader>
          <VueAccordionContent>
            <p>Simple accordion without visual clutter</p>
          </VueAccordionContent>
        </VueAccordionItem>
      </VueAccordion>
    </div>

    <div class="mbe4">
      <h2>Bordered</h2>
    </div>
    <div class="stacked mbe4">
      <VueAccordion>
        <VueAccordionItem
          bordered
          use-chevron
        >
          <VueAccordionHeader>Bordered Item 1</VueAccordionHeader>
          <VueAccordionContent>
            <p>This accordion has borders on the headers</p>
          </VueAccordionContent>
        </VueAccordionItem>
        <VueAccordionItem
          bordered
          use-chevron
        >
          <VueAccordionHeader>Bordered Item 2</VueAccordionHeader>
          <VueAccordionContent>
            <p>Another bordered item</p>
          </VueAccordionContent>
        </VueAccordionItem>
        <VueAccordionItem
          bordered
          use-chevron
        >
          <VueAccordionHeader>Bordered Item 3</VueAccordionHeader>
          <VueAccordionContent>
            <p>Third bordered item</p>
          </VueAccordionContent>
        </VueAccordionItem>
      </VueAccordion>
    </div>

    <div class="mbe4">
      <h2>With Background</h2>
    </div>
    <div class="stacked mbe4">
      <VueAccordion>
        <VueAccordionItem
          background
          use-chevron
        >
          <VueAccordionHeader>Background Item 1</VueAccordionHeader>
          <VueAccordionContent>
            <p>This accordion has background color on headers</p>
          </VueAccordionContent>
        </VueAccordionItem>
        <VueAccordionItem
          background
          use-chevron
        >
          <VueAccordionHeader>Background Item 2</VueAccordionHeader>
          <VueAccordionContent>
            <p>Another item with background</p>
          </VueAccordionContent>
        </VueAccordionItem>
        <VueAccordionItem
          background
          use-chevron
        >
          <VueAccordionHeader>Background Item 3</VueAccordionHeader>
          <VueAccordionContent>
            <p>Third item with background</p>
          </VueAccordionContent>
        </VueAccordionItem>
      </VueAccordion>
    </div>

    <div class="mbe4">
      <h2>One Item Open</h2>
    </div>
    <div class="stacked mbe4">
      <VueAccordion>
        <VueAccordionItem use-chevron>
          <VueAccordionHeader>Closed Item</VueAccordionHeader>
          <VueAccordionContent>
            <p>This item starts closed</p>
          </VueAccordionContent>
        </VueAccordionItem>
        <VueAccordionItem
          use-chevron
          open
        >
          <VueAccordionHeader>Open Item</VueAccordionHeader>
          <VueAccordionContent>
            <p>This item starts open</p>
          </VueAccordionContent>
        </VueAccordionItem>
        <VueAccordionItem use-chevron>
          <VueAccordionHeader>Another Closed Item</VueAccordionHeader>
          <VueAccordionContent>
            <p>This item also starts closed</p>
          </VueAccordionContent>
        </VueAccordionItem>
      </VueAccordion>
    </div>

    <div class="mbe4">
      <h2>Disabled State</h2>
    </div>
    <div class="stacked mbe4">
      <VueAccordion>
        <VueAccordionItem use-chevron>
          <VueAccordionHeader>Enabled Item</VueAccordionHeader>
          <VueAccordionContent>
            <p>This item can be toggled</p>
          </VueAccordionContent>
        </VueAccordionItem>
        <VueAccordionItem
          use-chevron
          disabled
        >
          <VueAccordionHeader>Disabled Item</VueAccordionHeader>
          <VueAccordionContent>
            <p>This item cannot be toggled</p>
          </VueAccordionContent>
        </VueAccordionItem>
        <VueAccordionItem use-chevron>
          <VueAccordionHeader>Another Enabled Item</VueAccordionHeader>
          <VueAccordionContent>
            <p>This item can also be toggled</p>
          </VueAccordionContent>
        </VueAccordionItem>
      </VueAccordion>
    </div>

    <div class="mbe4">
      <h2>Rich Content</h2>
    </div>
    <div class="stacked mbe4">
      <VueAccordion>
        <VueAccordionItem
          use-chevron
          bordered
        >
          <VueAccordionHeader>
            <div class="flex-inline items-center">
              <Info
                color="var(--ag-primary)"
                :size="18"
                class="mie2"
              />
              Features
            </div>
          </VueAccordionHeader>
          <VueAccordionContent>
            <ul>
              <li>Accessible by default with ARIA attributes</li>
              <li>Keyboard navigation support</li>
              <li>Customizable heading levels</li>
              <li>Multiple styling options</li>
            </ul>
          </VueAccordionContent>
        </VueAccordionItem>
        <VueAccordionItem
          use-chevron
          bordered
        >
          <VueAccordionHeader>
            <div class="flex-inline items-center">
              <Code
                color="var(--ag-secondary)"
                :size="18"
                class="mie2"
              />
              Code Example
            </div>
          </VueAccordionHeader>
          <VueAccordionContent>
            <pre style="background: var(--ag-background-secondary); padding: 1rem; border-radius: 4px; overflow-x: auto;">
&lt;VueAccordionItem use-chevron&gt;
  &lt;VueAccordionHeader&gt;Title&lt;/VueAccordionHeader&gt;
  &lt;VueAccordionContent&gt;Content&lt;/VueAccordionContent&gt;
&lt;/VueAccordionItem&gt;</pre>
          </VueAccordionContent>
        </VueAccordionItem>
        <VueAccordionItem
          use-chevron
          bordered
        >
          <VueAccordionHeader>
            <div class="flex-inline items-center">
              <HelpCircle
                color="var(--ag-success)"
                :size="18"
                class="mie2"
              />
              More Information
            </div>
          </VueAccordionHeader>
          <VueAccordionContent>
            <p>Accordions are great for:</p>
            <ul>
              <li>FAQ sections</li>
              <li>Feature lists</li>
              <li>Documentation</li>
              <li>Progressive disclosure</li>
            </ul>
          </VueAccordionContent>
        </VueAccordionItem>
      </VueAccordion>
    </div>

    <div class="mbe4">
      <h2>CSS Parts Customization</h2>
      <p
        class="mbe2"
        style="color: var(--ag-text-secondary); font-size: 0.875rem;"
      >
        Customize accordion appearance using CSS Shadow Parts without breaking encapsulation.
      </p>
    </div>
    <div class="stacked mbe4">
      <VueAccordion>
        <VueAccordionItem
          class="custom-minimal-accordion"
          use-chevron
        >
          <VueAccordionHeader>Minimal Border Style</VueAccordionHeader>
          <VueAccordionContent>
            <p>This variant uses a minimal border-left design with subtle styling.</p>
          </VueAccordionContent>
        </VueAccordionItem>
        <VueAccordionItem
          class="custom-minimal-accordion"
          use-chevron
        >
          <VueAccordionHeader>Another Minimal Item</VueAccordionHeader>
          <VueAccordionContent>
            <p>Clean and simple styling focused on content hierarchy.</p>
          </VueAccordionContent>
        </VueAccordionItem>
      </VueAccordion>
    </div>
  </section>
</template>

<script>
import VueAccordion, {
  VueAccordionItem,
  VueAccordionHeader,
  VueAccordionContent,
} from "agnosticui-core/accordion/vue";
import { Info, Code, HelpCircle } from "lucide-vue-next";

export default {
  name: "AccordionExamples",
  components: {
    VueAccordion,
    VueAccordionItem,
    VueAccordionHeader,
    VueAccordionContent,
    Info,
    Code,
    HelpCircle,
  },
};
</script>

<style scoped>
/* CSS Parts customization examples */
.custom-minimal-accordion::part(ag-accordion-header-wrapper) {
  border-left: 4px solid var(--ag-primary);
  padding-left: 12px;
}

.custom-minimal-accordion::part(ag-accordion-header) {
  font-weight: 500;
  color: var(--ag-text-primary);
}

.custom-minimal-accordion::part(ag-accordion-content) {
  padding-left: 16px;
  border-left: 2px solid #e5e7eb;
  margin-left: 2px;
}

.custom-minimal-accordion::part(ag-accordion-indicator) {
  color: var(--ag-primary);
}
</style>
Live Preview
View Lit / Web Component Code
import { LitElement, html } from 'lit';
import 'agnosticui-core/accordion';

export class AccordionLitExamples extends LitElement {
  // Render in light DOM to access global utility classes
  createRenderRoot() {
    return this;
  }

  render() {
    return html`
      <section>
        <div class="mbe4">
          <h2>Basic Accordion (Default)</h2>
          <p class="mbe2" style="color: var(--ag-text-secondary); font-size: 0.875rem;">
            By default, the Accordion provides a chevron which points down when
            closed, then rotates 180° to point up when open. See below for how to
            opt out or use different indicators.
          </p>
        </div>
        <div class="stacked mbe4">
          <ag-accordion>
            <ag-accordion-item use-chevron>
              <span slot="header">Chevron Section 1</span>
              <div slot="content">
                <p>Default chevron indicator with smooth rotation</p>
              </div>
            </ag-accordion-item>
            <ag-accordion-item use-chevron>
              <span slot="header">Chevron Section 2</span>
              <div slot="content">
                <p>Click to see the 180° rotation animation</p>
              </div>
            </ag-accordion-item>
            <ag-accordion-item use-chevron>
              <span slot="header">Chevron Section 3</span>
              <div slot="content">
                <p>Classic accordion indicator style</p>
              </div>
            </ag-accordion-item>
          </ag-accordion>
        </div>

        <div class="mbe4">
          <h2>X Indicator</h2>
          <p class="mbe2" style="color: var(--ag-text-secondary); font-size: 0.875rem;">
            Plus rotated 180° (upside down) when closed, rotates to 45° forming
            an X when open.
          </p>
        </div>
        <div class="stacked mbe4">
          <ag-accordion>
            <ag-accordion-item use-x>
              <span slot="header">X Indicator Section 1</span>
              <div slot="content">
                <p>Plus transforms into X when opened</p>
              </div>
            </ag-accordion-item>
            <ag-accordion-item use-x>
              <span slot="header">X Indicator Section 2</span>
              <div slot="content">
                <p>Smooth transition from plus to X</p>
              </div>
            </ag-accordion-item>
            <ag-accordion-item use-x>
              <span slot="header">X Indicator Section 3</span>
              <div slot="content">
                <p>Modern accordion indicator style</p>
              </div>
            </ag-accordion-item>
          </ag-accordion>
        </div>

        <div class="mbe4">
          <h2>Plus/Minus Indicator</h2>
          <p class="mbe2" style="color: var(--ag-text-secondary); font-size: 0.875rem;">
            Plus transitions to minus when open with smooth animation.
          </p>
        </div>
        <div class="stacked mbe4">
          <ag-accordion>
            <ag-accordion-item use-minus>
              <span slot="header">Plus/Minus Section 1</span>
              <div slot="content">
                <p>Plus changes to minus when opened</p>
              </div>
            </ag-accordion-item>
            <ag-accordion-item use-minus>
              <span slot="header">Plus/Minus Section 2</span>
              <div slot="content">
                <p>Classic expand/collapse indicator</p>
              </div>
            </ag-accordion-item>
            <ag-accordion-item use-minus>
              <span slot="header">Plus/Minus Section 3</span>
              <div slot="content">
                <p>Clear visual indication of state</p>
              </div>
            </ag-accordion-item>
          </ag-accordion>
        </div>

        <div class="mbe4">
          <h2>No Indicator</h2>
          <p class="mbe2" style="color: var(--ag-text-secondary); font-size: 0.875rem;">
            Accordion items without any visual indicator.
          </p>
        </div>
        <div class="stacked mbe4">
          <ag-accordion>
            <ag-accordion-item no-indicator>
              <span slot="header">No Indicator Section 1</span>
              <div slot="content">
                <p>Clean header without indicator icon</p>
              </div>
            </ag-accordion-item>
            <ag-accordion-item no-indicator>
              <span slot="header">No Indicator Section 2</span>
              <div slot="content">
                <p>Minimal design focused on content</p>
              </div>
            </ag-accordion-item>
            <ag-accordion-item no-indicator>
              <span slot="header">No Indicator Section 3</span>
              <div slot="content">
                <p>Simple accordion without visual clutter</p>
              </div>
            </ag-accordion-item>
          </ag-accordion>
        </div>

        <div class="mbe4">
          <h2>Bordered</h2>
        </div>
        <div class="stacked mbe4">
          <ag-accordion>
            <ag-accordion-item bordered use-chevron>
              <span slot="header">Bordered Item 1</span>
              <div slot="content">
                <p>This accordion has borders on the headers</p>
              </div>
            </ag-accordion-item>
            <ag-accordion-item bordered use-chevron>
              <span slot="header">Bordered Item 2</span>
              <div slot="content">
                <p>Another bordered item</p>
              </div>
            </ag-accordion-item>
            <ag-accordion-item bordered use-chevron>
              <span slot="header">Bordered Item 3</span>
              <div slot="content">
                <p>Third bordered item</p>
              </div>
            </ag-accordion-item>
          </ag-accordion>
        </div>

        <div class="mbe4">
          <h2>With Background</h2>
        </div>
        <div class="stacked mbe4">
          <ag-accordion>
            <ag-accordion-item background use-chevron>
              <span slot="header">Background Item 1</span>
              <div slot="content">
                <p>This accordion has background color on headers</p>
              </div>
            </ag-accordion-item>
            <ag-accordion-item background use-chevron>
              <span slot="header">Background Item 2</span>
              <div slot="content">
                <p>Another item with background</p>
              </div>
            </ag-accordion-item>
            <ag-accordion-item background use-chevron>
              <span slot="header">Background Item 3</span>
              <div slot="content">
                <p>Third item with background</p>
              </div>
            </ag-accordion-item>
          </ag-accordion>
        </div>

        <div class="mbe4">
          <h2>One Item Open</h2>
        </div>
        <div class="stacked mbe4">
          <ag-accordion>
            <ag-accordion-item use-chevron>
              <span slot="header">Closed Item</span>
              <div slot="content">
                <p>This item starts closed</p>
              </div>
            </ag-accordion-item>
            <ag-accordion-item use-chevron open>
              <span slot="header">Open Item</span>
              <div slot="content">
                <p>This item starts open</p>
              </div>
            </ag-accordion-item>
            <ag-accordion-item use-chevron>
              <span slot="header">Another Closed Item</span>
              <div slot="content">
                <p>This item also starts closed</p>
              </div>
            </ag-accordion-item>
          </ag-accordion>
        </div>

        <div class="mbe4">
          <h2>Disabled State</h2>
        </div>
        <div class="stacked mbe4">
          <ag-accordion>
            <ag-accordion-item use-chevron>
              <span slot="header">Enabled Item</span>
              <div slot="content">
                <p>This item can be toggled</p>
              </div>
            </ag-accordion-item>
            <ag-accordion-item use-chevron disabled>
              <span slot="header">Disabled Item</span>
              <div slot="content">
                <p>This item cannot be toggled</p>
              </div>
            </ag-accordion-item>
            <ag-accordion-item use-chevron>
              <span slot="header">Another Enabled Item</span>
              <div slot="content">
                <p>This item can also be toggled</p>
              </div>
            </ag-accordion-item>
          </ag-accordion>
        </div>

        <div class="mbe4">
          <h2>Rich Content</h2>
        </div>
        <div class="stacked mbe4">
          <ag-accordion>
            <ag-accordion-item use-chevron bordered>
              <span slot="header">
                <div class="flex-inline items-center">
                  <svg
                    class="mie2"
                    width="18"
                    height="18"
                    viewBox="0 0 24 24"
                    fill="none"
                    stroke="var(--ag-primary)"
                    stroke-width="2"
                    stroke-linecap="round"
                    stroke-linejoin="round"
                  >
                    <circle cx="12" cy="12" r="10" />
                    <path d="M12 16v-4" />
                    <path d="M12 8h.01" />
                  </svg>
                  Features
                </div>
              </span>
              <div slot="content">
                <ul>
                  <li>Accessible by default with ARIA attributes</li>
                  <li>Keyboard navigation support</li>
                  <li>Customizable heading levels</li>
                  <li>Multiple styling options</li>
                </ul>
              </div>
            </ag-accordion-item>
            <ag-accordion-item use-chevron bordered>
              <span slot="header">
                <div class="flex-inline items-center">
                  <svg
                    class="mie2"
                    width="18"
                    height="18"
                    viewBox="0 0 24 24"
                    fill="none"
                    stroke="var(--ag-secondary)"
                    stroke-width="2"
                    stroke-linecap="round"
                    stroke-linejoin="round"
                  >
                    <polyline points="16 18 22 12 16 6" />
                    <polyline points="8 6 2 12 8 18" />
                  </svg>
                  Code Example
                </div>
              </span>
              <div slot="content">
                <pre style="background: var(--ag-background-secondary); padding: 1rem; border-radius: 4px; overflow-x: auto;">
&lt;ag-accordion-item use-chevron&gt;
  &lt;span slot="header"&gt;Title&lt;/span&gt;
  &lt;div slot="content"&gt;Content&lt;/div&gt;
&lt;/ag-accordion-item&gt;</pre>
              </div>
            </ag-accordion-item>
            <ag-accordion-item use-chevron bordered>
              <span slot="header">
                <div class="flex-inline items-center">
                  <svg
                    class="mie2"
                    width="18"
                    height="18"
                    viewBox="0 0 24 24"
                    fill="none"
                    stroke="var(--ag-success)"
                    stroke-width="2"
                    stroke-linecap="round"
                    stroke-linejoin="round"
                  >
                    <circle cx="12" cy="12" r="10" />
                    <path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3" />
                    <path d="M12 17h.01" />
                  </svg>
                  More Information
                </div>
              </span>
              <div slot="content">
                <p>Accordions are great for:</p>
                <ul>
                  <li>FAQ sections</li>
                  <li>Feature lists</li>
                  <li>Documentation</li>
                  <li>Progressive disclosure</li>
                </ul>
              </div>
            </ag-accordion-item>
          </ag-accordion>
        </div>

        <div class="mbe4">
          <h2>CSS Parts Customization</h2>
          <p class="mbe2" style="color: var(--ag-text-secondary); font-size: 0.875rem;">
            Customize accordion appearance using CSS Shadow Parts without
            breaking encapsulation.
          </p>
        </div>
        <div class="stacked mbe4">
          <ag-accordion>
            <ag-accordion-item class="custom-minimal-accordion" use-chevron>
              <span slot="header">Minimal Border Style</span>
              <div slot="content">
                <p>
                  This variant uses a minimal border-left design with subtle
                  styling.
                </p>
              </div>
            </ag-accordion-item>
            <ag-accordion-item class="custom-minimal-accordion" use-chevron>
              <span slot="header">Another Minimal Item</span>
              <div slot="content">
                <p>Clean and simple styling focused on content hierarchy.</p>
              </div>
            </ag-accordion-item>
          </ag-accordion>
        </div>

        <style>
          /* CSS Parts customization examples */
          .custom-minimal-accordion::part(ag-accordion-header-wrapper) {
            border-left: 4px solid var(--ag-primary);
            padding-left: 12px;
          }

          .custom-minimal-accordion::part(ag-accordion-header) {
            font-weight: 500;
            color: var(--ag-text-primary);
          }

          .custom-minimal-accordion::part(ag-accordion-content) {
            padding-left: 16px;
            border-left: 2px solid #e5e7eb;
            margin-left: 2px;
          }

          .custom-minimal-accordion::part(ag-accordion-indicator) {
            color: var(--ag-primary);
          }
        </style>
      </section>
    `;
  }
}

customElements.define('accordion-lit-examples', AccordionLitExamples);

Interactive Preview: Click the "Open in StackBlitz" button below to see this example running live in an interactive playground.

View React Code
import {
  ReactAccordion,
  AccordionItem,
  ItemHeader,
  ItemContent,
} from "agnosticui-core/accordion/react";

export default function AccordionReactExamples() {
  return (
    <section>
      <div className="mbe4">
        <h2>Basic Accordion (Default)</h2>
        <p
          className="mbe2"
          style={{ color: "var(--ag-text-secondary)", fontSize: "0.875rem" }}
        >
          By default, the Accordion provides a chevron which points down when
          closed, then rotates 180° to point up when open. See below for how to
          opt out or use different indicators.
        </p>
      </div>
      <div className="stacked mbe4">
        <ReactAccordion>
          <AccordionItem useChevron>
            <ItemHeader>Chevron Section 1</ItemHeader>
            <ItemContent>
              <p>Default chevron indicator with smooth rotation</p>
            </ItemContent>
          </AccordionItem>
          <AccordionItem useChevron>
            <ItemHeader>Chevron Section 2</ItemHeader>
            <ItemContent>
              <p>Click to see the 180° rotation animation</p>
            </ItemContent>
          </AccordionItem>
          <AccordionItem useChevron>
            <ItemHeader>Chevron Section 3</ItemHeader>
            <ItemContent>
              <p>Classic accordion indicator style</p>
            </ItemContent>
          </AccordionItem>
        </ReactAccordion>
      </div>

      <div className="mbe4">
        <h2>X Indicator</h2>
        <p
          className="mbe2"
          style={{ color: "var(--ag-text-secondary)", fontSize: "0.875rem" }}
        >
          Plus rotated 180° (upside down) when closed, rotates to 45° forming
          an X when open.
        </p>
      </div>
      <div className="stacked mbe4">
        <ReactAccordion>
          <AccordionItem useX>
            <ItemHeader>X Indicator Section 1</ItemHeader>
            <ItemContent>
              <p>Plus transforms into X when opened</p>
            </ItemContent>
          </AccordionItem>
          <AccordionItem useX>
            <ItemHeader>X Indicator Section 2</ItemHeader>
            <ItemContent>
              <p>Smooth transition from plus to X</p>
            </ItemContent>
          </AccordionItem>
          <AccordionItem useX>
            <ItemHeader>X Indicator Section 3</ItemHeader>
            <ItemContent>
              <p>Modern accordion indicator style</p>
            </ItemContent>
          </AccordionItem>
        </ReactAccordion>
      </div>

      <div className="mbe4">
        <h2>Plus/Minus Indicator</h2>
        <p
          className="mbe2"
          style={{ color: "var(--ag-text-secondary)", fontSize: "0.875rem" }}
        >
          Plus transitions to minus when open with smooth animation.
        </p>
      </div>
      <div className="stacked mbe4">
        <ReactAccordion>
          <AccordionItem useMinus>
            <ItemHeader>Plus/Minus Section 1</ItemHeader>
            <ItemContent>
              <p>Plus changes to minus when opened</p>
            </ItemContent>
          </AccordionItem>
          <AccordionItem useMinus>
            <ItemHeader>Plus/Minus Section 2</ItemHeader>
            <ItemContent>
              <p>Classic expand/collapse indicator</p>
            </ItemContent>
          </AccordionItem>
          <AccordionItem useMinus>
            <ItemHeader>Plus/Minus Section 3</ItemHeader>
            <ItemContent>
              <p>Clear visual indication of state</p>
            </ItemContent>
          </AccordionItem>
        </ReactAccordion>
      </div>

      <div className="mbe4">
        <h2>No Indicator</h2>
        <p
          className="mbe2"
          style={{ color: "var(--ag-text-secondary)", fontSize: "0.875rem" }}
        >
          Accordion items without any visual indicator.
        </p>
      </div>
      <div className="stacked mbe4">
        <ReactAccordion>
          <AccordionItem noIndicator>
            <ItemHeader>No Indicator Section 1</ItemHeader>
            <ItemContent>
              <p>Clean header without indicator icon</p>
            </ItemContent>
          </AccordionItem>
          <AccordionItem noIndicator>
            <ItemHeader>No Indicator Section 2</ItemHeader>
            <ItemContent>
              <p>Minimal design focused on content</p>
            </ItemContent>
          </AccordionItem>
          <AccordionItem noIndicator>
            <ItemHeader>No Indicator Section 3</ItemHeader>
            <ItemContent>
              <p>Simple accordion without visual clutter</p>
            </ItemContent>
          </AccordionItem>
        </ReactAccordion>
      </div>

      <div className="mbe4">
        <h2>Bordered</h2>
      </div>
      <div className="stacked mbe4">
        <ReactAccordion>
          <AccordionItem bordered useChevron>
            <ItemHeader>Bordered Item 1</ItemHeader>
            <ItemContent>
              <p>This accordion has borders on the headers</p>
            </ItemContent>
          </AccordionItem>
          <AccordionItem bordered useChevron>
            <ItemHeader>Bordered Item 2</ItemHeader>
            <ItemContent>
              <p>Another bordered item</p>
            </ItemContent>
          </AccordionItem>
          <AccordionItem bordered useChevron>
            <ItemHeader>Bordered Item 3</ItemHeader>
            <ItemContent>
              <p>Third bordered item</p>
            </ItemContent>
          </AccordionItem>
        </ReactAccordion>
      </div>

      <div className="mbe4">
        <h2>With Background</h2>
      </div>
      <div className="stacked mbe4">
        <ReactAccordion>
          <AccordionItem background useChevron>
            <ItemHeader>Background Item 1</ItemHeader>
            <ItemContent>
              <p>This accordion has background color on headers</p>
            </ItemContent>
          </AccordionItem>
          <AccordionItem background useChevron>
            <ItemHeader>Background Item 2</ItemHeader>
            <ItemContent>
              <p>Another item with background</p>
            </ItemContent>
          </AccordionItem>
          <AccordionItem background useChevron>
            <ItemHeader>Background Item 3</ItemHeader>
            <ItemContent>
              <p>Third item with background</p>
            </ItemContent>
          </AccordionItem>
        </ReactAccordion>
      </div>

      <div className="mbe4">
        <h2>One Item Open</h2>
      </div>
      <div className="stacked mbe4">
        <ReactAccordion>
          <AccordionItem useChevron>
            <ItemHeader>Closed Item</ItemHeader>
            <ItemContent>
              <p>This item starts closed</p>
            </ItemContent>
          </AccordionItem>
          <AccordionItem useChevron open>
            <ItemHeader>Open Item</ItemHeader>
            <ItemContent>
              <p>This item starts open</p>
            </ItemContent>
          </AccordionItem>
          <AccordionItem useChevron>
            <ItemHeader>Another Closed Item</ItemHeader>
            <ItemContent>
              <p>This item also starts closed</p>
            </ItemContent>
          </AccordionItem>
        </ReactAccordion>
      </div>

      <div className="mbe4">
        <h2>Disabled State</h2>
      </div>
      <div className="stacked mbe4">
        <ReactAccordion>
          <AccordionItem useChevron>
            <ItemHeader>Enabled Item</ItemHeader>
            <ItemContent>
              <p>This item can be toggled</p>
            </ItemContent>
          </AccordionItem>
          <AccordionItem useChevron disabled>
            <ItemHeader>Disabled Item</ItemHeader>
            <ItemContent>
              <p>This item cannot be toggled</p>
            </ItemContent>
          </AccordionItem>
          <AccordionItem useChevron>
            <ItemHeader>Another Enabled Item</ItemHeader>
            <ItemContent>
              <p>This item can also be toggled</p>
            </ItemContent>
          </AccordionItem>
        </ReactAccordion>
      </div>

      <div className="mbe4">
        <h2>Rich Content</h2>
      </div>
      <div className="stacked mbe4">
        <ReactAccordion>
          <AccordionItem useChevron bordered>
            <ItemHeader>
              <div className="flex-inline items-center">
                <svg
                  className="mie2"
                  width="18"
                  height="18"
                  viewBox="0 0 24 24"
                  fill="none"
                  stroke="var(--ag-primary)"
                  strokeWidth="2"
                  strokeLinecap="round"
                  strokeLinejoin="round"
                >
                  <circle cx="12" cy="12" r="10" />
                  <path d="M12 16v-4" />
                  <path d="M12 8h.01" />
                </svg>
                Features
              </div>
            </ItemHeader>
            <ItemContent>
              <ul>
                <li>Accessible by default with ARIA attributes</li>
                <li>Keyboard navigation support</li>
                <li>Customizable heading levels</li>
                <li>Multiple styling options</li>
              </ul>
            </ItemContent>
          </AccordionItem>
          <AccordionItem useChevron bordered>
            <ItemHeader>
              <div className="flex-inline items-center">
                <svg
                  className="mie2"
                  width="18"
                  height="18"
                  viewBox="0 0 24 24"
                  fill="none"
                  stroke="var(--ag-secondary)"
                  strokeWidth="2"
                  strokeLinecap="round"
                  strokeLinejoin="round"
                >
                  <polyline points="16 18 22 12 16 6" />
                  <polyline points="8 6 2 12 8 18" />
                </svg>
                Code Example
              </div>
            </ItemHeader>
            <ItemContent>
              <pre
                style={{
                  background: "var(--ag-background-secondary)",
                  padding: "1rem",
                  borderRadius: "4px",
                  overflowX: "auto",
                }}
              >
                {`<AccordionItem useChevron>
  <ItemHeader>Title</ItemHeader>
  <ItemContent>Content</ItemContent>
</AccordionItem>`}
              </pre>
            </ItemContent>
          </AccordionItem>
          <AccordionItem useChevron bordered>
            <ItemHeader>
              <div className="flex-inline items-center">
                <svg
                  className="mie2"
                  width="18"
                  height="18"
                  viewBox="0 0 24 24"
                  fill="none"
                  stroke="var(--ag-success)"
                  strokeWidth="2"
                  strokeLinecap="round"
                  strokeLinejoin="round"
                >
                  <circle cx="12" cy="12" r="10" />
                  <path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3" />
                  <path d="M12 17h.01" />
                </svg>
                More Information
              </div>
            </ItemHeader>
            <ItemContent>
              <p>Accordions are great for:</p>
              <ul>
                <li>FAQ sections</li>
                <li>Feature lists</li>
                <li>Documentation</li>
                <li>Progressive disclosure</li>
              </ul>
            </ItemContent>
          </AccordionItem>
        </ReactAccordion>
      </div>

      <div className="mbe4">
        <h2>CSS Parts Customization</h2>
        <p
          className="mbe2"
          style={{ color: "var(--ag-text-secondary)", fontSize: "0.875rem" }}
        >
          Customize accordion appearance using CSS Shadow Parts without
          breaking encapsulation.
        </p>
      </div>
      <div className="stacked mbe4">
        <ReactAccordion>
          <AccordionItem className="custom-minimal-accordion" useChevron>
            <ItemHeader>Minimal Border Style</ItemHeader>
            <ItemContent>
              <p>
                This variant uses a minimal border-left design with subtle
                styling.
              </p>
            </ItemContent>
          </AccordionItem>
          <AccordionItem className="custom-minimal-accordion" useChevron>
            <ItemHeader>Another Minimal Item</ItemHeader>
            <ItemContent>
              <p>Clean and simple styling focused on content hierarchy.</p>
            </ItemContent>
          </AccordionItem>
        </ReactAccordion>
      </div>

      {/* CSS Parts customization styles */}
      <style>{`
        .custom-minimal-accordion::part(ag-accordion-header-wrapper) {
          border-left: 4px solid var(--ag-primary);
          padding-left: 12px;
        }

        .custom-minimal-accordion::part(ag-accordion-header) {
          font-weight: 500;
          color: var(--ag-text-primary);
        }

        .custom-minimal-accordion::part(ag-accordion-content) {
          padding-left: 16px;
          border-left: 2px solid #e5e7eb;
          margin-left: 2px;
        }

        .custom-minimal-accordion::part(ag-accordion-indicator) {
          color: var(--ag-primary);
        }
      `}</style>
    </section>
  );
}
Open in StackBlitz

Usage

TIP

The framework examples below import AgnosticUI as an npm package. Alternatively, you can use the CLI for complete control, AI/LLM visibility, and full code ownership:

bash
npx ag init --framework FRAMEWORK # react, vue, lit, svelte, etc.
npx ag add Accordion

The CLI copies source code directly into your project, giving you full visibility and control. After running npx ag add, you'll receive exact import instructions.

Vue
vue
<template>
  <section>
    <VueAccordion>
      <VueAccordionItem>
        <VueAccordionHeader>Accordion Item 1</VueAccordionHeader>
        <VueAccordionContent>
          <p>This is the content of the first accordion item.</p>
        </VueAccordionContent>
      </VueAccordionItem>
      <VueAccordionItem>
        <VueAccordionHeader>Accordion Item 2</VueAccordionHeader>
        <VueAccordionContent>
          <p>This is the content of the second accordion item.</p>
        </VueAccordionContent>
      </VueAccordionItem>
      <VueAccordionItem>
        <VueAccordionHeader>Accordion Item 3</VueAccordionHeader>
        <VueAccordionContent>
          <p>This is the content of the third accordion item.</p>
        </VueAccordionContent>
      </VueAccordionItem>
    </VueAccordion>

    <VueAccordion>
      <VueAccordionItem use-chevron bordered>
        <VueAccordionHeader>Features</VueAccordionHeader>
        <VueAccordionContent>
          <ul>
            <li>Accessible by default</li>
            <li>Keyboard navigation support</li>
            <li>Customizable heading levels</li>
          </ul>
        </VueAccordionContent>
      </VueAccordionItem>
      <VueAccordionItem use-chevron bordered open>
        <VueAccordionHeader>Open by Default</VueAccordionHeader>
        <VueAccordionContent>
          <p>This item starts in the open state.</p>
        </VueAccordionContent>
      </VueAccordionItem>
    </VueAccordion>

    <VueAccordion>
      <VueAccordionItem use-x @toggle="handleToggle">
        <VueAccordionHeader>X Indicator</VueAccordionHeader>
        <VueAccordionContent>
          <p>Plus icon that transforms into an X when opened</p>
        </VueAccordionContent>
      </VueAccordionItem>
    </VueAccordion>

    <VueAccordion>
      <VueAccordionItem use-minus @toggle="handleToggle">
        <VueAccordionHeader>Plus/Minus Indicator</VueAccordionHeader>
        <VueAccordionContent>
          <p>Plus icon that changes to minus when opened</p>
        </VueAccordionContent>
      </VueAccordionItem>
    </VueAccordion>
  </section>
</template>

<script>
import VueAccordion, {
  VueAccordionItem,
  VueAccordionHeader,
  VueAccordionContent,
} from "agnosticui-core/accordion/vue";

export default {
  components: {
    VueAccordion,
    VueAccordionItem,
    VueAccordionHeader,
    VueAccordionContent,
  },
  methods: {
    handleToggle(detail) {
      console.log("Accordion toggled:", detail.open);
    },
  },
};
</script>
React
tsx
import {
  ReactAccordion,
  AccordionItem,
  ItemHeader,
  ItemContent,
} from "agnosticui-core/accordion/react";

export default function AccordionExample() {
  const handleToggle = (event: CustomEvent) => {
    console.log("Accordion toggled:", event.detail.open);
  };

  return (
    <section>
      <ReactAccordion>
        <AccordionItem>
          <ItemHeader>Accordion Item 1</ItemHeader>
          <ItemContent>
            <p>This is the content of the first accordion item.</p>
          </ItemContent>
        </AccordionItem>
        <AccordionItem>
          <ItemHeader>Accordion Item 2</ItemHeader>
          <ItemContent>
            <p>This is the content of the second accordion item.</p>
          </ItemContent>
        </AccordionItem>
        <AccordionItem>
          <ItemHeader>Accordion Item 3</ItemHeader>
          <ItemContent>
            <p>This is the content of the third accordion item.</p>
          </ItemContent>
        </AccordionItem>
      </ReactAccordion>

      <ReactAccordion>
        <AccordionItem useChevron bordered>
          <ItemHeader>Features</ItemHeader>
          <ItemContent>
            <ul>
              <li>Accessible by default</li>
              <li>Keyboard navigation support</li>
              <li>Customizable heading levels</li>
            </ul>
          </ItemContent>
        </AccordionItem>
        <AccordionItem useChevron bordered open={true}>
          <ItemHeader>Open by Default</ItemHeader>
          <ItemContent>
            <p>This item starts in the open state.</p>
          </ItemContent>
        </AccordionItem>
      </ReactAccordion>

      <ReactAccordion>
        <AccordionItem useX onToggle={handleToggle}>
          <ItemHeader>X Indicator</ItemHeader>
          <ItemContent>
            <p>Plus icon that transforms into an X when opened</p>
          </ItemContent>
        </AccordionItem>
      </ReactAccordion>

      <ReactAccordion>
        <AccordionItem useMinus onToggle={handleToggle}>
          <ItemHeader>Plus/Minus Indicator</ItemHeader>
          <ItemContent>
            <p>Plus icon that changes to minus when opened</p>
          </ItemContent>
        </AccordionItem>
      </ReactAccordion>
    </section>
  );
}
Lit (Web Components)
typescript
import { LitElement, html, css } from 'lit';
import { customElement } from 'lit/decorators.js';
import 'agnosticui-core/accordion';

@customElement('accordion-example')
export class AccordionExample extends LitElement {
  static styles = css`
    :host {
      display: block;
    }
    section {
      display: flex;
      flex-direction: column;
      gap: 2rem;
    }
  `;

  firstUpdated() {
    // Set up event listeners for accordion items in the shadow DOM
    const items = this.shadowRoot?.querySelectorAll('ag-accordion-item');
    items?.forEach((item) => {
      item.addEventListener('toggle', (event: Event) => {
        const customEvent = event as CustomEvent;
        console.log('Accordion toggled:', customEvent.detail.open);
      });
    });
  }

  render() {
    return html`
      <section>
        <ag-accordion>
          <ag-accordion-item>
            <span slot="header">Accordion Item 1</span>
            <div slot="content">
              <p>This is the content of the first accordion item.</p>
            </div>
          </ag-accordion-item>
          <ag-accordion-item>
            <span slot="header">Accordion Item 2</span>
            <div slot="content">
              <p>This is the content of the second accordion item.</p>
            </div>
          </ag-accordion-item>
          <ag-accordion-item>
            <span slot="header">Accordion Item 3</span>
            <div slot="content">
              <p>This is the content of the third accordion item.</p>
            </div>
          </ag-accordion-item>
        </ag-accordion>

        <ag-accordion>
          <ag-accordion-item use-chevron bordered>
            <span slot="header">Features</span>
            <div slot="content">
              <ul>
                <li>Accessible by default</li>
                <li>Keyboard navigation support</li>
                <li>Customizable heading levels</li>
              </ul>
            </div>
          </ag-accordion-item>
          <ag-accordion-item use-chevron bordered open>
            <span slot="header">Open by Default</span>
            <div slot="content">
              <p>This item starts in the open state.</p>
            </div>
          </ag-accordion-item>
        </ag-accordion>

        <ag-accordion>
          <ag-accordion-item id="x-indicator-item" use-x>
            <span slot="header">X Indicator</span>
            <div slot="content">
              <p>Plus icon that transforms into an X when opened</p>
            </div>
          </ag-accordion-item>
        </ag-accordion>

        <ag-accordion>
          <ag-accordion-item id="minus-indicator-item" use-minus>
            <span slot="header">Plus/Minus Indicator</span>
            <div slot="content">
              <p>Plus icon that changes to minus when opened</p>
            </div>
          </ag-accordion-item>
        </ag-accordion>
      </section>
    `;
  }
}

Note: When using accordion components within a custom element's shadow DOM, set up event listeners in the component's lifecycle (e.g., firstUpdated()) using this.shadowRoot.querySelectorAll() instead of document.addEventListener('DOMContentLoaded', ...).

Props

Accordion (Container)

The Accordion component is a simple container with no specific props. It wraps multiple AccordionItem components.

AccordionItem

PropTypeDefaultDescription
openbooleanfalseWhether the accordion item is expanded
headingLevelnumber3Heading level for semantic HTML (1-6, renders as h1-h6)
disabledbooleanfalseWhether the accordion item is disabled
useChevronbooleantrueUse chevron indicator (default) - rotates 180° when open
useXbooleanfalseUse X indicator - plus rotated 180° initially, becomes X at 45° when open
useMinusbooleanfalseUse plus/minus indicator - plus transitions to minus when open
noIndicatorbooleanfalseHide the indicator completely
borderedbooleanfalseWhether to apply border styling to the header
backgroundbooleanfalseWhether to apply background color to the header

Note: Indicator props are mutually exclusive with priority: noIndicator > useX > useMinus > useChevron (default)

Events

The AccordionItem component follows AgnosticUI v2 event conventions with dual-dispatch for the toggle custom event - you can use either addEventListener or callback props (e.g., onToggle).

EventFrameworkDetailDescription
toggleVue: @toggle
React: onToggle
Lit: @toggle or .onToggle
{ open: boolean }Fired when the accordion item is toggled between open and closed states.

Event Handling Examples

Vue
vue
<template>
  <VueAccordionItem @toggle="handleToggle">
    <template #header>Toggle me</template>
    <template #content>Content here</template>
  </VueAccordionItem>

  <VueAccordionItem v-model:open="isOpen">
    <template #header>Controlled accordion</template>
    <template #content>Content here</template>
  </VueAccordionItem>

  <VueAccordionItem v-model:open="isOpen" @toggle="handleToggle">
    <template #header>Both patterns</template>
    <template #content>Content here</template>
  </VueAccordionItem>
</template>

<script setup>
import { ref } from "vue";
import { VueAccordionItem } from "agnosticui-core/accordion/vue";

const isOpen = ref(false);

const handleToggle = (detail) => {
  console.log("Toggle event:", detail);
};
</script>
React
tsx
import { useState } from "react";
import {
  AccordionItem,
  ItemHeader,
  ItemContent,
} from "agnosticui-core/accordion/react";

export default function AccordionExample() {
  const [isOpen, setIsOpen] = useState(false);

  const handleToggle = (event) => {
    console.log("Toggle event:", event.detail);
    setIsOpen(event.detail.open);
  };

  return (
    <AccordionItem open={isOpen} onToggle={handleToggle}>
      <ItemHeader>Click to toggle</ItemHeader>
      <ItemContent>Accordion content here</ItemContent>
    </AccordionItem>
  );
}
Lit (Web Components)
html
<script type="module">
  import "agnosticui-core/accordion";

  const item = document.querySelector("#my-accordion");

  item.addEventListener("toggle", (event) => {
    console.log("Toggle event:", event.detail);
  });

  item.onToggle = (event) => {
    console.log("Toggle event (callback):", event.detail);
  };
</script>

<ag-accordion-item id="my-accordion">
  <span slot="header">Click to toggle</span>
  <div slot="content">Accordion content here</div>
</ag-accordion-item>

CSS Shadow Parts

The Accordion exposes CSS Shadow Parts that allow you to customize internal elements without breaking encapsulation:

PartDescriptionElement
ag-accordion-wrapperThe main wrapper container<div>
ag-accordion-header-wrapperThe header wrapper containing the heading and button<div>
ag-accordion-headingThe semantic heading element (h1-h6)<h1>-<h6>
ag-accordion-headerThe interactive button inside the heading<button>
ag-accordion-indicatorThe expand/collapse indicator icon wrapper<span>
ag-accordion-contentThe collapsible content region<div>

Example Usage

css
ag-accordion-item::part(ag-accordion-header-wrapper) {
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  border-radius: 8px;
  padding: 4px;
}

ag-accordion-item::part(ag-accordion-header) {
  color: white;
  padding: 16px 20px;
}

ag-accordion-item::part(ag-accordion-content) {
  background: #f9fafb;
  padding: 20px;
  border: 2px solid #e5e7eb;
}

ag-accordion-item::part(ag-accordion-indicator) {
  color: #12623e;
}

Accessibility

The Accordion implements the WAI-ARIA Accordion Pattern:

  • Uses semantic heading elements (h1-h6) with customizable headingLevel prop
  • Buttons have aria-expanded to communicate state
  • Content panels have role="region" and are labeled via aria-labelledby
  • Keyboard accessible:
    • Space/Enter: Toggle the focused accordion item
    • Arrow Down: Move focus to next accordion item
    • Arrow Up: Move focus to previous accordion item
    • Home: Move focus to first accordion item
    • End: Move focus to last accordion item
  • Using TAB works as well
  • Screen readers announce the current state (expanded/collapsed)
  • Clear focus indicators for keyboard navigation
  • Disabled items cannot be interacted with and are communicated via aria-disabled

Progressive Enhancement

The Accordion is designed with progressive enhancement in mind:

  • Content is visible by default before JavaScript loads
  • Once the web component is defined, expand/collapse functionality is enhanced
  • If JavaScript fails to load, users can still access all content
  • Uses the data-enhanced attribute to apply hide/show logic only after JavaScript initialization