Collapsible#

A disclosure built on the native <details> element: the root is the <details>, the trigger is its <summary>, and the panel is the content it reveals. The platform gives keyboard interaction, semantics and zero-JS toggling of server-rendered markup; zero keeps one model in charge by intercepting the summary click and rendering open from state.

Import#

TSX
import { Collapsible } from '@sigx/zero/collapsible';

Collapsible is a compound: Collapsible.Root, Collapsible.Trigger, Collapsible.Panel. It is also re-exported from the @sigx/zero root, together with collapsibleAnatomy and useCollapsibleContext.

Usage#

TSX
import { component } from 'sigx';
import { Collapsible } from '@sigx/zero/collapsible';

const Advanced = component(({ signal }) => {
    const state = signal({ open: false });

    return () => (
        <Collapsible.Root model={() => state.open}>
            <Collapsible.Trigger>Advanced options</Collapsible.Trigger>
            <Collapsible.Panel>…</Collapsible.Panel>
        </Collapsible.Root>
    );
});

model={() => state.open} binds the open state both ways — activating the trigger writes state.open, and writing state.open opens or closes the details. Leave the model off and pass defaultOpen to keep the state inside the component; openChange fires either way. See Models.

Uncontrolled, open by default#

TSX
<Collapsible.Root defaultOpen>
    <Collapsible.Trigger>Show less</Collapsible.Trigger>
    <Collapsible.Panel>…</Collapsible.Panel>
</Collapsible.Root>

Disabled#

TSX
<Collapsible.Root defaultOpen disabled>

disabled on the root freezes the current state: the trigger's click is ignored and every part renders data-disabled. A <summary> has no disabled attribute of its own, so the trigger announces it through aria-disabled="true" and stays a tab stop.

Anatomy#

PartElementStatesFlagsNotes
rootdetailsopen | closeddisabledThe native open attribute is rendered from the model. Carries the variant axes.
triggersummaryopen | closeddisabled, focus-visible, pressed, press-animatingaria-expanded, aria-controls → the panel, aria-disabled. Publishes press feedback. Inside root.
paneldivopen | closedCarries the id the trigger controls. Inside root.

Every part carries data-scope="collapsible" and data-part="<part>". The <summary> conveys expansion natively in most assistive technology; the explicit aria-expanded / aria-controls pair covers the rest. A closed <details> hides everything after its summary, so a closed rule on the panel never paints — a design system animates the open transition on panel and styles the trigger's open / closed states (the chevron). Ids are SSR-safe and stable across hydration. See The anatomy contract.

Props#

Collapsible.Root#

PropTypeDefaultDescription
modelbooleanTwo-way binding of the open state.
defaultOpenbooleanfalseInitial state when uncontrolled.
openChangeevent (open: boolean)Fires whenever the open state changes.
disabledbooleanfalseThe trigger ignores activation; renders data-disabled on root and trigger.
color / size / variant / axes / modsdesign-system vocabularyThe variant axes, rendered as data-* on root.
classstringExtra classes on the <details>.

Collapsible.Trigger#

Only class. Renders the summary part around its children.

Collapsible.Panel#

Only class. Renders the panel part around its children.

Keyboard#

KeyAction
Enter / SpaceToggle the disclosure (native <summary> activation, routed through the model).
TabThe trigger is an ordinary tab stop; the panel's content follows while open.

In the shipped design systems#

Both @sigx/zero-basic and @sigx/zero-daisyui wire color (all eight recommended roles) and size (xsxl) on collapsible, so <Collapsible.Root color="neutral" size="sm"> is styled in both. Neither wires a variant or any mods on the scope; under a design system's /register import those props are therefore absent. See Typed vocabulary.

Accordion for several disclosures under one model, with exclusive or multiple opening.