---
title: Collapsible
description: "A disclosure component for showing and hiding content, with optional accordion behavior."
order: 8
tags: [components]
---

import { Preview } from "$lib/components/preview";
import { Collapsible } from "areia";

# Collapsible

A composable disclosure component for showing and hiding content.

[Source Code](https://github.com/ilhajs/areia/blob/main/packages/areia/src/components/collapsible/index.ts)

`Collapsible` is backed by `@areia/slots`. Single disclosure mode uses the collapsible primitive, while accordion mode uses the accordion primitive for grouped items, keyboard navigation, and single or multiple expanded panels.

<Preview
  code={
    'import ilha from "ilha";\nimport { Collapsible } from "areia";\n\nexport default ilha.render(() => (\n  <div class="w-full max-w-md">\n    <Collapsible\n      defaultOpen\n      trigger="What is Areia?"\n      panel="Areia is a vanilla TypeScript component library for building application interfaces."\n    />\n  </div>\n));'
  }
  lang="tsx"
>
  <div class="w-full max-w-md">
    <Collapsible
      defaultOpen
      trigger="What is Areia?"
      panel="Areia is a vanilla TypeScript component library for building application interfaces."
    />
  </div>
</Preview>

## Import

```ts
import { Collapsible } from "areia";
```

## Usage

Use the high-level `trigger` and `panel` props for a single disclosure.

<Preview
  code={
    'import ilha from "ilha";\nimport { Collapsible } from "areia";\n\nexport default ilha.render(() => (\n  <Collapsible\n    trigger="Show details"\n    panel="Content revealed when the trigger is activated."\n  />\n));'
  }
  lang="tsx"
>
  <Collapsible
    trigger="Show details"
    panel="Content revealed when the trigger is activated."
  />
</Preview>

Use `items` for accordion behavior.

<Preview
  code={
    'import ilha from "ilha";\nimport { Collapsible } from "areia";\n\nexport default ilha.render(() => (\n  <Collapsible\n    defaultValue="overview"\n    items={[\n      {\n        value: "overview",\n        label: "Overview",\n        content: "A quick summary of the project.",\n      },\n      {\n        value: "settings",\n        label: "Settings",\n        content: "Controls and preferences for this workspace.",\n      },\n    ]}\n  />\n));'
  }
  lang="tsx"
  codeOnly
/>

Use `Collapsible.Static(...)` for static markup or when you want to initialize behavior yourself. For most application usage, call `Collapsible(...)`.

## Examples

### Basic

<Preview
  code={
    'import ilha from "ilha";\nimport { Collapsible } from "areia";\n\nexport default ilha.render(() => (\n  <Collapsible\n    trigger="What is Areia?"\n    panel="Areia provides accessible primitives and styled components for application UIs."\n  />\n));'
  }
  lang="tsx"
>
  <Collapsible
    trigger="What is Areia?"
    panel="Areia provides accessible primitives and styled components for application UIs."
  />
</Preview>

### Default Open

<Preview
  code={
    'import ilha from "ilha";\nimport { Collapsible } from "areia";\n\nexport default ilha.render(() => (\n  <Collapsible\n    defaultOpen\n    trigger="Deployment details"\n    panel="The latest deployment completed successfully."\n  />\n));'
  }
  lang="tsx"
>
  <Collapsible
    defaultOpen
    trigger="Deployment details"
    panel="The latest deployment completed successfully."
  />
</Preview>

### Multiple Independent Items

Render multiple single disclosures when each item should manage its own open state.

<Preview
  code={
    'import ilha from "ilha";\nimport { Collapsible } from "areia";\n\nexport default ilha.render(() => (\n  <div class="w-full max-w-md space-y-3">\n    <Collapsible\n      trigger="What is Areia?"\n      panel="A component library for application interfaces."\n    />\n    <Collapsible\n      trigger="How do I use it?"\n      panel="Install the package and import the components you need."\n    />\n    <Collapsible\n      trigger="Does it include primitives?"\n      panel="Yes. Interactive components are backed by @areia/slots."\n    />\n  </div>\n));'
  }
  lang="tsx"
  codeOnly
/>

### Custom Trigger And Panel

Use the compound helpers when you need custom layout.

<Preview
  code={
    'import ilha from "ilha";\nimport { Collapsible } from "areia";\n\nexport default ilha.render(() => (\n  <Collapsible>\n    <Collapsible.Trigger class="rounded-md bg-areia-control-background px-3 py-2 text-sm font-medium ring ring-areia-control-border">\n      Show release notes\n    </Collapsible.Trigger>\n    <Collapsible.Panel class="mt-3 rounded-lg bg-areia-surface-muted p-4 text-sm text-areia-default">\n      This panel uses custom styling instead of the default\n      border-left accent.\n    </Collapsible.Panel>\n  </Collapsible>\n));'
  }
  lang="tsx"
>
  <Collapsible>
    <Collapsible.Trigger class="rounded-md bg-areia-control-background px-3 py-2 text-sm font-medium ring ring-areia-control-border">
      Show release notes
    </Collapsible.Trigger>
    <Collapsible.Panel class="mt-3 rounded-lg bg-areia-surface-muted p-4 text-sm text-areia-default">
      This panel uses custom styling instead of the default
      border-left accent.
    </Collapsible.Panel>
  </Collapsible>
</Preview>

### Accordion

Pass `items` to render an accordion where one item is open at a time by default.

<Preview
  code={
    'import ilha from "ilha";\nimport { Collapsible } from "areia";\n\nconst items = [\n  {\n    value: "project",\n    label: "Project",\n    content: "Configure project metadata and visibility.",\n  },\n  {\n    value: "team",\n    label: "Team",\n    content: "Invite teammates and manage roles.",\n  },\n  {\n    value: "billing",\n    label: "Billing",\n    content: "Update payment method and invoices.",\n  },\n];\n\nexport default ilha.render(() => (\n  <div class="w-full max-w-md">\n    <Collapsible defaultValue="project" items={items} />\n  </div>\n));'
  }
  lang="tsx"
  codeOnly
/>

### Multiple Accordion Items

Use `multiple: true` when more than one item can be open.

<Preview
  code={
    'import ilha from "ilha";\nimport { Collapsible } from "areia";\n\nexport default ilha.render(() => (\n  <Collapsible\n    multiple\n    defaultValue={["filters", "columns"]}\n    items={[\n      {\n        value: "filters",\n        label: "Filters",\n        content:\n          "Status, owner, and date range filters are active.",\n      },\n      {\n        value: "columns",\n        label: "Columns",\n        content: "Choose which table columns are visible.",\n      },\n      {\n        value: "exports",\n        label: "Exports",\n        content: "Download visible rows as CSV.",\n      },\n    ]}\n  />\n));'
  }
  lang="tsx"
  codeOnly
/>

### Change Events

Use Ilha state to respond to accordion value changes.

<Preview
  code={
    'import ilha from "ilha";\nimport { Collapsible } from "areia";\n\nexport default ilha\n  .state("openItem", "account")\n  .render(({ state }) => (\n    <div class="space-y-4">\n      <Collapsible\n        defaultValue={state.openItem()}\n        items={[\n          {\n            value: "account",\n            label: "Account",\n            content: "Account settings are expanded.",\n          },\n          {\n            value: "security",\n            label: "Security",\n            content: "Security settings are expanded.",\n          },\n        ]}\n        onValueChange={(value) => {\n          state.openItem(value[0] ?? "");\n        }}\n      />\n      <p class="text-sm text-areia-subtle">\n        Open item: <code>{state.openItem}</code>\n      </p>\n    </div>\n  ));'
  }
  lang="tsx"
  codeOnly
/>

## Compound Components

Use compound helpers when the high-level props are not enough.

| Component                      | Description                              |
| ------------------------------ | ---------------------------------------- |
| `Collapsible.Root`             | Static single disclosure root markup.    |
| `Collapsible.Trigger`          | Unstyled trigger slot.                   |
| `Collapsible.Panel`            | Unstyled content slot.                   |
| `Collapsible.DefaultTrigger`   | Styled trigger with an animated chevron. |
| `Collapsible.DefaultPanel`     | Styled panel with a left border accent.  |
| `Collapsible.Accordion`        | Static accordion root markup.            |
| `Collapsible.AccordionItem`    | Accordion item wrapper.                  |
| `Collapsible.AccordionTrigger` | Accordion trigger slot.                  |
| `Collapsible.AccordionPanel`   | Accordion content slot.                  |

## API

### `Collapsible(input)`

| Prop               | Type                      | Default | Description                                        |
| ------------------ | ------------------------- | ------- | -------------------------------------------------- |
| `trigger`          | `unknown`                 | —       | Trigger content for single disclosure mode.        |
| `panel`            | `unknown`                 | —       | Panel content for single disclosure mode.          |
| `children`         | `unknown`                 | —       | Custom compound markup.                            |
| `open`             | `boolean`                 | —       | Initial open state for single disclosure mode.     |
| `defaultOpen`      | `boolean`                 | `false` | Initial open state for single disclosure mode.     |
| `hiddenUntilFound` | `boolean`                 | `false` | Use `hidden="until-found"` when content is closed. |
| `class`            | `string`                  | —       | Additional classes for the root.                   |
| `className`        | `string`                  | —       | Alias for `class`.                                 |
| `onOpenChange`     | `(open: boolean) => void` | —       | Called when single disclosure state changes.       |

### Accordion Props

These props apply when `items` are provided or `accordion: true` is set.

| Prop            | Type                         | Default      | Description                                          |
| --------------- | ---------------------------- | ------------ | ---------------------------------------------------- |
| `items`         | `CollapsibleItem[]`          | `[]`         | Items rendered as accordion sections.                |
| `accordion`     | `boolean`                    | `false`      | Forces accordion mode for custom accordion children. |
| `multiple`      | `boolean`                    | `false`      | Allows multiple items to be open.                    |
| `value`         | `string \| string[]`         | —            | Initial expanded item value or values.               |
| `defaultValue`  | `string \| string[]`         | —            | Initial expanded item value or values.               |
| `disabled`      | `boolean`                    | `false`      | Disables the accordion.                              |
| `orientation`   | `"vertical" \| "horizontal"` | `"vertical"` | Keyboard navigation orientation.                     |
| `loopFocus`     | `boolean`                    | `true`       | Whether arrow-key focus wraps at the ends.           |
| `onValueChange` | `(value: string[]) => void`  | —            | Called when expanded accordion items change.         |

### `CollapsibleItem`

| Property       | Type      | Required | Description                         |
| -------------- | --------- | -------- | ----------------------------------- |
| `value`        | `string`  | Yes      | Unique item value.                  |
| `label`        | `unknown` | No       | Trigger label.                      |
| `trigger`      | `unknown` | No       | Custom trigger content.             |
| `content`      | `unknown` | No       | Panel content.                      |
| `children`     | `unknown` | No       | Alias for panel content.            |
| `disabled`     | `boolean` | No       | Disables the item.                  |
| `class`        | `string`  | No       | Additional classes for the item.    |
| `triggerClass` | `string`  | No       | Additional classes for the trigger. |
| `panelClass`   | `string`  | No       | Additional classes for the panel.   |

## Slots

Single disclosure mode renders:

- `collapsible`
- `collapsible-trigger`
- `collapsible-content`

Accordion mode renders:

- `accordion`
- `accordion-item`
- `accordion-trigger`
- `accordion-content`
