Collapsible
Draft Base Collapsible ownership, keyboard activation, content presence, and authoring examples.
Base Collapsible is one disclosure, not an Accordion. Root owns expansion, Trigger requests changes, and Content projects visibility and presence. It does not prescribe a visual language.
The standalone demo includes default detached content, initially open retained content, disabled-but-open content, and controlled requests. In the controlled example, activate the Trigger, then Accept pending controlled request: requesting alone does not change expansion.
Parts and ownership
Section titled “Parts and ownership”One base-collapsible-root contains exactly one base-collapsible-trigger and one base-collapsible-content in its own Anatomy domain. Duplicate parts are rejected immediately; missing required parts are checked after host readiness has settled, not while a host is still mounting children.
| Part | Props | Public projection |
|---|---|---|
| Root | open?, defaultOpen?, disabled? | Canonical open; openCollapsible, close, and toggle request methods; openChange event |
| Trigger | disabled? | Derived expanded and effective disabled; interaction/focus states and guarded focusSelf |
| Content | keepMounted? | Derived open and hidden; no extra semantic role |
Without open, Root is uncontrolled. defaultOpen initializes expansion at creation only; changing it later does not reset the disclosure. With open, Root is controlled: openChange carries { open, reason }, where reason is pointer, keyboard, or programmatic. The owner accepts a request by supplying a new open prop. Ignoring a request leaves open, Trigger expanded, and Content visibility unchanged—there is no optimistic controlled update. Prop synchronization and lifecycle reconciliation do not emit change requests.
Root disabled or Trigger disabled makes the Trigger effectively disabled and suppresses activation. Root-disabled also suppresses imperative open/close requests. Disabling an already open disclosure does not close it or rewrite canonical expansion; owner-supplied open still controls the value.
Keyboard and accessibility
Section titled “Keyboard and accessibility”Trigger has button semantics and takes its accessible name from its content. It participates in natural Tab order and activates on Enter or Space; an effectively disabled Trigger is not sequentially focusable. There is no roving focus, arrow navigation, orientation, or heading requirement. Content is role-neutral: no automatic region landmark, focus stop, autofocus, focus scope, overlay, or focus-return behavior.
Trigger declares a same-domain controls relationship to Content using the explicit protocol key content. This key is logical identity, not a DOM ID. The reusable relationship service and Web Adapter own host identity and aria-controls projection. When Content has no materialized host view, the logical relationship can remain while its Web IDREF is absent. Rematerialization restores a valid host relation; terminal owner disposal cleans up reservations and relations. Do not cache generated IDs or treat detached content as a second portable presence/ID registry. Separate and nested Root domains do not cross-link.
Content lifetime
Section titled “Content lifetime”Closed Content defaults to L1 host-view detach. Reopening rematerializes the view while preserving the logical owner; it is not terminal disposal. keepMounted retains the host view and marks closed content hidden, including its accessibility projection. It changes retention, not expansion ownership or automatic focus behavior. Terminal Root disposal still wins over retention.
Authoring and CLI
Section titled “Authoring and CLI”The current workspace exports collapsibleRoot, collapsibleTrigger, collapsibleContent and the composition hooks asCollapsibleRoot, asCollapsibleTrigger, asCollapsibleContent from @proto.ui/prototypes-base/collapsible. Direct prototype names are base-collapsible-{root,trigger,content}.
After initializing a project with the matching workspace CLI, choose one host:
proto-ui add react base-collapsible# Or: proto-ui add vue base-collapsible# Or: proto-ui add vue2 base-collapsible# Or: proto-ui add wc base-collapsibleReact/Vue/Vue 2 facades are BaseCollapsibleRoot, BaseCollapsibleTrigger, and BaseCollapsibleContent. Web Component facades add the Element suffix and register proto-ui-base-collapsible-{root,trigger,content}. Preview-only wc-base-* tags are not CLI tag names.
This complete React example adapts the real public prototypes directly; the generated facade provides the same three components:
import * as React from 'react';import { createReactAdapter } from '@proto.ui/adapter-react';import { collapsibleRoot, collapsibleTrigger, collapsibleContent,} from '@proto.ui/prototypes-base/collapsible';
const adapt = createReactAdapter(React);const BaseCollapsibleRoot = adapt(collapsibleRoot);const BaseCollapsibleTrigger = adapt(collapsibleTrigger);const BaseCollapsibleContent = adapt(collapsibleContent);
export function ControlledDisclosure() { const [open, setOpen] = React.useState(false); return ( <BaseCollapsibleRoot open={open} onOpenChange={(request) => setOpen(request.open)}> <BaseCollapsibleTrigger>Details</BaseCollapsibleTrigger> <BaseCollapsibleContent keepMounted>Additional details</BaseCollapsibleContent> </BaseCollapsibleRoot> );}
export function UncontrolledDisclosure() { return ( <BaseCollapsibleRoot defaultOpen> <BaseCollapsibleTrigger>Details</BaseCollapsibleTrigger> <BaseCollapsibleContent>Additional details</BaseCollapsibleContent> </BaseCollapsibleRoot> );}An owner may instead reject or defer onOpenChange; until it supplies a changed open, the disclosure stays at the supplied value. The live demo deliberately defers acceptance to make that boundary visible.
Draft boundary and sources
Section titled “Draft boundary and sources”P-BASE-COLLAPSIBLE, P-BASE-COLLAPSIBLE-TRIGGER, P-BASE-COLLAPSIBLE-CONTENT, and T-BASE-COLLAPSIBLE-0001 remain draft at 0.3.0-alpha.1. This is a current workspace implementation surface, not a claim that published 0.3.0-alpha.1 artifacts already contain it, a stable compatibility commitment, native-platform proof, or lifecycle promotion. The preview offers four Web adapters; an available runtime selector alone is not conformance evidence.