Skip to content

Collapsible

Overview

Intent-oriented alias of the Disclosure primitive.

Pattern: Disclosure. Status: stable.

When to use

  • A product-language alias for a single Disclosure-powered expandable region.
  • Teams that prefer “collapsible” naming while sharing the Disclosure contract and tests.

When not to use

  • Grouped collapsibles; use Accordion.
  • Complex overlays or animated drawers that need focus trapping.

Import

ts
import { createCollapsible } from 'ui-headless-runtime';

Controller creation

Create Collapsible during component mount or setup, subscribe before rendering derived UI, and keep every cleanup returned by registrations or DOM binding.

Options

  • Public options: disabled, id, defaultValue, getValue, onValueChange, subscribeValue.
  • Collapsible accepts DisclosureOptions; the state name is expanded, not open.

Snapshot

  • Snapshot fields: controlled, disabled, expanded, panel, trigger.
  • trigger and panel contain the stable IDs, relationship metadata, disabled state, role, and visibility required by consumer markup.

Commands

  • Component commands: collapse, expand, handleTriggerClick, handleTriggerKeyDown, setDisabled, toggle.
  • Collapsible is a type alias of DisclosureController; it has no DOM bind method.

Events

  • Events: beforeClose, beforeOpen, close, open, afterClose, afterOpen, stateChange.
  • The before-events are cancellable; all payloads use DisclosureChangeEvent.

Change reasons

  • Change reasons: programmatic, trigger, keyboard.

Controlled mode

Controlled Collapsible exists for naming consistency while delegating ownership semantics to Disclosure.

Uncontrolled mode

Uncontrolled Collapsible owns a single boolean open state.

DOM binding

  • Bind a trigger and content region, or manually apply snapshot IDs and expanded state.

Required markup

  • Use a button trigger and a panel/region connected with aria-controls.

ARIA contract

  • Apply the same aria-expanded and aria-controls contract as Disclosure.

Keyboard interaction

  • Enter / Space: Toggle content.

Focus behavior

  • Enter and Space toggle; focus otherwise follows normal document order.

Nested behavior

  • Nested collapsibles should use separate controllers and IDs.

Cleanup

  • Release the Disclosure binding and destroy the controller during unmount.

Minimal lifecycle example

ts
import { createCollapsible } from 'ui-headless-runtime';

const controller = createCollapsible();
const unsubscribe = controller.subscribe((snapshot) => {
  console.log(snapshot);
});

console.log(controller.getSnapshot());
unsubscribe();
controller.destroy();

The production demo loads the exact executable module from apps/demo/src/examples/collapsible.ts.

Edge cases

  • basic: Simple expandable content.
  • controlled: External ownership with the same contract.

Limitations

  • It intentionally adds no state model beyond Disclosure.

API reference

See createCollapsible.

Headless behavior; consumer-owned rendering and styling.