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

- **Category:** Layout (`layout`)
- **Slug:** `layout/collapse`
- **Status:** stable
- **Platforms:** web
- **Import:** `import { Collapse } from "@protocore/pds";`
- **Docs:** https://pds.protocore.io/components/layout/collapse

> A single animated collapsible region, opened via open/defaultOpen, with an animated height and reduced-motion support.

## Collapse vs Accordion

`Collapse` is the **single-region** primitive: one block of content that expands and collapses under your control. `Accordion` generalizes it into a set of mutually-aware disclosure rows with built-in triggers and single/multiple modes. Use `Collapse` when you own the trigger and just need one region to animate — a 'show more' block, an inline detail panel, an advanced-settings drawer. The height animates off the region's natural size and honors the reader's reduced-motion preference automatically.

## Props

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `children` | `ReactNode` | no | — | Region contents. |
| `className` | `string` | no | — | — |
| `defaultOpen` | `boolean` | no | `false` | Uncontrolled initial open state. |
| `onOpenChange` | `((open: boolean) => void)` | no | — | Fires when the open state changes. |
| `open` | `boolean` | no | — | Controlled open state. |
| `style` | `CSSProperties` | no | — | — |
| `unmountOnExit` | `boolean` | no | `true` | Remove the region from the DOM once its collapse animation finishes. When `false` the content stays mounted (just visually hidden) so it remains available to find-in-page and the accessibility tree. |

## Examples

### Basics

`Collapse` shows or hides a region with an animated height, driven by the `open` prop. Pair it with your own trigger — a button, a row header — that toggles the state you pass in.

```tsx
import { useState } from "react";
import { Collapse, Button, Panel, Stack, Text } from "@protocore/pds";

export default function CollapseBasics() {
  const [open, setOpen] = useState(false);
  return (
    <Stack gap={3}>
      <Button
        variant="secondary"
        size="sm"
        aria-expanded={open}
        aria-controls="collapse-advanced"
        onClick={() => setOpen((o) => !o)}
        style={{ alignSelf: "flex-start" }}
      >
        {open ? "Hide advanced config" : "Show advanced config"}
      </Button>
      <Collapse id="collapse-advanced" open={open}>
        <Panel>
          <Stack gap={2}>
            <Text weight={500}>Executor</Text>
            <Text size="sm" color="secondary">
              Prepays destination gas and retries idempotently. DVN threshold defaults to 2 of 3
              attestations before a message is delivered.
            </Text>
          </Stack>
        </Panel>
      </Collapse>
    </Stack>
  );
}
```

### Keep mounted

By default the region is removed from the DOM once collapsed. Set `unmountOnExit={false}` to keep it mounted (just hidden) so its content stays available to find-in-page and the accessibility tree.

```tsx
import { useState } from "react";
import { Collapse, Switch, Stack, Text } from "@protocore/pds";

export default function CollapseUnmount() {
  const [open, setOpen] = useState(true);
  return (
    <Stack gap={3}>
      <Switch
        checked={open}
        onCheckedChange={setOpen}
        label={open ? "Region visible" : "Region collapsed (still mounted)"}
      />
      <Collapse open={open} unmountOnExit={false}>
        <Text size="sm" color="secondary">
          This paragraph stays in the DOM even while collapsed, so browser find-in-page and
          assistive tech can still reach the text: eu-central-1 relay settling in a single hop.
        </Text>
      </Collapse>
    </Stack>
  );
}
```

## Do & don't

**Do**

- Pair Collapse with a button trigger that toggles the open state you pass in.
- Use `unmountOnExit={false}` when the hidden content must stay findable in search.
- Use Accordion for several coordinated disclosure rows.

**Don't**

- Animate a fixed-height region — Collapse measures the content's natural height.
- Use Collapse for a set of exclusive panels — that is Accordion.
- Omit `aria-expanded` / `aria-controls` on your own trigger (see a11y).

## Accessibility

**Notes**

- Collapse renders only the region; provide your own trigger and link them with `aria-expanded` and `aria-controls` pointing at the region's `id`.
- When collapsed and unmounted, the content leaves the accessibility tree; use unmountOnExit={false} if it must remain discoverable.
- The height animation is neutralized under prefers-reduced-motion by the global motion policy.

## Related

`accordion`, `scroll-area`, `panel`

---

© 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/
