Layout · astro-ui · Collapsible

CollapsibleJS

Expand/collapse region with a dedicated trigger button.

Collapsible is an expand/collapse region whose trigger is a separate button that can live anywhere in the markup, and whose panel is arbitrary composed content — unlike Accordion, which uses native <details> with content authored as data. The scoped script toggles hidden + aria-expanded and closes on Escape. Closed panels use hidden=“until-found”: find-in-page, #hash deep links, and :~:text= fragments can still match and reveal collapsed content (the browser fires beforematch and removes the attribute; aria-expanded stays in sync). Multiple collapsibles on one page are supported — each root is wired independently by its data attribute.

Features

  • Trigger button with aria-expanded / aria-controls + rotating chevron
  • Arbitrary composed panel content (slot, not data)
  • hidden=until-found: find-in-page + deep links reveal closed panels
  • Escape closes the panel and returns focus to the trigger
  • Multiple independent instances per page (data-attribute wiring)

Usage

---
import { Collapsible } from "astro-ui";
---

<Collapsible id="filters" open>
  <span slot="trigger">Filters</span>
  <p>Any composed content…</p>
</Collapsible>

Demos

Basic

<Collapsible id="filters">
  <span slot="trigger">Filters</span>
  <p>Composed content…</p>
</Collapsible>

Searchable collapsed content

Keep this panel closed and press Ctrl/Cmd+F, then search forkyoto reservation code — the browser finds it inside the closed panel and reveals it (hidden="until-found"). Navigating to #dm-collapsible-searchable-panel works too.

{/* Closed panels keep hidden="until-found": press Ctrl/Cmd+F and */}
{/* search "kyoto reservation code" — the browser reveals this panel. */}
<Collapsible id="booking">
  <span slot="trigger">Booking details</span>
  <p>Your kyoto reservation code is AOK-2291.</p>
</Collapsible>

{/* #booking-panel deep links and #:~:text= fragments reveal it too. */}
{/* A beforematch listener keeps aria-expanded=true when that happens. */}

Open by default

The open prop renders the panel expanded on first paint.

<Collapsible id="advanced" open>
  <span slot="trigger">Advanced</span>
  <p>Panel starts visible via the open prop.</p>
</Collapsible>

API

Props

PropTypeDefaultDescription
openbooleanfalseOpen on first render (SSR).
disabledbooleanfalseDisables the trigger.
idstring—Recommended: stable prefix for trigger/panel ids.
classstring—Merged via cn(); Tailwind classes welcome.
idstring—Element id.

Slots

SlotDescription
triggerTrigger button content (chevron is added).
defaultThe collapsible panel content.

Accessibility

Implemented accessibility features — semantics, ARIA wiring, and keyboard behavior that ship with the component.

  • aria-expanded + aria-controls wire the trigger to the panel state
  • Panel is a role="region" labelled by the trigger
  • hidden="until-found" keeps closed content reachable by find-in-page and deep links (beforematch keeps aria-expanded honest)
  • Escape closes and returns focus to the trigger

FAQ

Collapsible or Accordion?

Accordion = data-driven items in a group (native <details>, optional single-open via name). Collapsible = arbitrary composed content with a trigger you position yourself.

Can users find text inside a closed panel?

Yes. Closed panels use hidden="until-found", so Ctrl/Cmd+F, #hash links, and :~:text= fragments match collapsed content and the browser reveals it (firing beforematch — the component keeps aria-expanded in sync). Native <details> accordions get the same behavior from the platform. Falls back to display: none where unsupported.

Changelog

Version history mentioning Collapsible.

v0.1.0 — 2026-11-11
added
  • Layout (7): Card, AspectRatio, ScrollArea, Separator, Accordion, Collapsible, StickySurface.
  • Native-first interactive behavior: Dialog, AlertDialog, and Sheet on <dialog>; Accordion and Collapsible on <details>; Tabs, Menu, Tree, and Combobox with WAI-ARIA roles and scoped keyboard scripts.