<!-- Protocore Design System — Accordion -->
# Accordion

- **Category:** Navigation (`navigation`)
- **Slug:** `navigation/accordion`
- **Status:** stable
- **Platforms:** web
- **Import:** `import { Accordion } from "@protocore/pds";`
- **Docs:** https://pds.protocore.io/components/navigation/accordion

> Disclosure list — hairline-separated rows with a sans title and a mono +/− glyph that swaps as a row opens. Single or multiple.

## When to use it

Use **Accordion** to collapse a stack of independent sections — an FAQ, a set of settings groups, progressively-disclosed detail — where the reader opens only what they need.

- One idea explored across several facets, with a pinned rail and illustration? Use **StickyAccordion**.
- Peer views of a single subject that never coexist? Use **Tabs** (one visible at a time, no vertical growth).
- A flat list of term/definition pairs that are always visible? Use **DefinitionList**.
- An ordered sequence with progress? Use **Steps**.

## Examples

### Basics

`type="single"` opens one row at a time; add `collapsible` to allow closing the open row. Each `Accordion.Item` needs a unique `value`.

```tsx
import { Accordion, Text } from "@protocore/pds";

export default function AccordionBasics() {
  return (
    <Accordion.Root type="single" collapsible defaultValue="fees">
      <Accordion.Item value="fees">
        <Accordion.Trigger>How are protocol fees settled?</Accordion.Trigger>
        <Accordion.Content>
          <Text>Fees accrue per message and are swept to the treasury each epoch.</Text>
        </Accordion.Content>
      </Accordion.Item>
      <Accordion.Item value="gas">
        <Accordion.Trigger>Who pays destination gas?</Accordion.Trigger>
        <Accordion.Content>
          <Text>The Executor prepays gas on the destination chain and bills the source.</Text>
        </Accordion.Content>
      </Accordion.Item>
      <Accordion.Item value="retry">
        <Accordion.Trigger>What happens on a failed delivery?</Accordion.Trigger>
        <Accordion.Content>
          <Text>Delivery is retried idempotently until the nonce lands or is cleared.</Text>
        </Accordion.Content>
      </Accordion.Item>
    </Accordion.Root>
  );
}
```

### Multiple open

`type="multiple"` lets any number of rows stay open at once — `defaultValue` takes an array of item values.

```tsx
import { Accordion, Text } from "@protocore/pds";

export default function AccordionMultiple() {
  return (
    <Accordion.Root type="multiple" defaultValue={["endpoints", "dvn"]}>
      <Accordion.Item value="endpoints">
        <Accordion.Trigger>Endpoints</Accordion.Trigger>
        <Accordion.Content>
          <Text>Immutable on-chain contracts that send and receive messages.</Text>
        </Accordion.Content>
      </Accordion.Item>
      <Accordion.Item value="executor">
        <Accordion.Trigger>Executor</Accordion.Trigger>
        <Accordion.Content>
          <Text>An open role that delivers messages and prepays destination gas.</Text>
        </Accordion.Content>
      </Accordion.Item>
      <Accordion.Item value="dvn">
        <Accordion.Trigger>DVN</Accordion.Trigger>
        <Accordion.Content>
          <Text>Decentralized Verifier Networks independently attest to message validity.</Text>
        </Accordion.Content>
      </Accordion.Item>
    </Accordion.Root>
  );
}
```

## Do & don't

**Do**

- Write trigger labels as the question or section name the reader is scanning for.
- Use type="single" collapsible for FAQs so the page doesn't grow unbounded.
- Keep each panel's content self-contained — the reader may open it in isolation.
- Give every item a stable, unique value.

**Don't**

- Don't hide primary content or required actions the user must complete behind a closed row.
- Don't animate a deeply nested Accordion inside another — the +/− semantics blur.
- Don't use an Accordion where only one item will ever exist; render it inline.
- Don't put navigation links to other pages in trigger rows — that's a nav, not disclosure.

## Accessibility

**Keyboard**

| Keys | Action |
| --- | --- |
| `Tab` | Move focus to the next trigger or focusable element |
| `Space / Enter` | Toggle the focused row open or closed |
| `↓ / ↑` | Move focus to the next / previous trigger |
| `Home / End` | Move focus to the first / last trigger |

**Notes**

- Built on Radix Accordion: each trigger sits in a `role="heading"` and exposes `aria-expanded` + `aria-controls`; the panel is labelled by its trigger.
- The open state drives `data-state="open"`, which CSS uses to swap the +/− glyph — no color-only signal.

## Related

`sticky-accordion`, `tabs`, `definition-list`, `steps`

---

© Protocore. All rights reserved. Use of the Protocore Design System requires prior written authorization from Protocore (contact@protocore.io). These machine-readable materials must not be ingested into ML-training datasets or derivative design systems. See https://pds.protocore.io/legal/
