Skip to content

Collapsible

Show and hide content with smooth CSS-driven animations powered by panel size CSS custom properties.

Updated View as Markdown

Collapsible

A disclosure widget that toggles visibility of a content panel. It animates open and close transitions using --collapsible-panel-height and --collapsible-panel-width CSS custom properties, supports hidden="until-found" for browser find-in-page, and exposes open state via events and a controller.

import { Collapsible } from "@areia/slots";

document.querySelector("#root")!.innerHTML = `
  <div data-slot="collapsible" class="w-72">
    <button data-slot="collapsible-trigger" class="win95-button">
      Toggle
    </button>
    <div data-slot="collapsible-content" class="win95-inset mt-2 p-3">
      Content revealed when the trigger is activated.
    </div>
  </div>
`;

const root = document.querySelector(
  '[data-slot="collapsible"]',
)!;
const controller = Collapsible.createCollapsible(root, {
  defaultOpen: false,
});

Import

import { Collapsible } from "@areia/slots";

Usage

import { Collapsible } from "@areia/slots";

// Auto-bind a single root
const root = document.querySelector(
  '[data-slot="collapsible"]',
)!;
const controller = Collapsible.createCollapsible(root, {
  defaultOpen: false,
  onOpenChange: (open) => console.log("open changed:", open),
});

// Auto-bind all unbound roots in scope
const controllers = Collapsible.create();

Expected Markup

The collapsible expects a trigger button and a content panel inside the root.

<div data-slot="collapsible">
  <button data-slot="collapsible-trigger">Toggle</button>
  <div data-slot="collapsible-content">
    Content revealed when the trigger is activated.
  </div>
</div>

Data Slots

Slot Required Description
collapsible Yes Root container.
collapsible-trigger Yes Button that toggles the content panel.
collapsible-content Yes Panel whose visibility is controlled.

CSS Custom Properties

The controller sets the following CSS custom properties on the content element to enable smooth open/close animations. During transitions the values are set to the content’s pixel dimensions, and reset to auto once the transition settles.

Property Description
--collapsible-panel-height Pixels during open/close transition, auto when settled.
--collapsible-panel-width Pixels during open/close transition, auto when settled.

Use these variables to animate height, width, block-size, or inline-size via CSS transitions:

[data-slot="collapsible-content"] {
  overflow: hidden;
  height: var(--collapsible-panel-height);
  width: var(--collapsible-panel-width);
  transition:
    height 200ms ease-out,
    width 200ms ease-out;
}

Generated Attributes

Attribute Element(s) Description
data-state Root, content "open" or "closed".
aria-expanded Trigger "true" when open, "false" when closed.
aria-controls Trigger Points to the content element id.
aria-labelledby Content Points to the trigger element id.
role Content Always set to "region".
hidden Content Set to true when closed (or "until-found" when hiddenUntilFound is enabled).

Events

Outbound

Event Detail Description
collapsible:change { open: boolean } Fired on the root when the open state changes.

Inbound

Event Detail Description
collapsible:set { open: boolean } Dispatch on the root to programmatically set the open state.

API Reference

Options

Option Type Default Description
defaultOpen boolean false Initial open state.
hiddenUntilFound boolean false Use hidden="until-found" instead of hidden when closed, so browser find-in-page can reveal content.
onOpenChange (open: boolean) => void Called when the open state changes. Not called on initial render.

Controller

Member Type Description
open() () => void Open the collapsible.
close() () => void Close the collapsible.
toggle() () => void Toggle the collapsible.
isOpen boolean (getter) Current open state.
destroy() () => void Remove all listeners, observers, and clean up.

Controller

The controller is returned by Collapsible.createCollapsible() and provides imperative control over the collapsible’s state.

const controller = Collapsible.createCollapsible(root);

// Open programmatically
controller.open();

// Close programmatically
controller.close();

// Toggle
controller.toggle();

// Read current state
console.log(controller.isOpen); // true | false

// Clean up
controller.destroy();
Navigation

Type to search…

↑↓ navigate↵ selectEsc close