Collapsible
stimeo--collapsible
Opens and closes one region in place, and hands its height to CSS so you can animate it.
Opens and closes a single region from one button. Whether it is open is announced to screen readers. Animating a height usually fails because the content's height is unknown, so this measures the real height and hands it to CSS for you to animate. On closing, the region is hidden only after the animation finishes, so the movement is never cut short.
Orders placed before 2pm ship the same business day. Standard delivery takes 3–5 business days; express options are shown at checkout.
Keyboard
| Key | Action |
|---|---|
| Enter / Space | Toggle the region open or closed (native button). |
<%# Markup for the collapsible (APG Disclosure) demo.
The trigger opens/closes a single region inline. The library syncs aria-expanded /
hidden / data-state and the content's measured-height variable; the look (the
height transition) lives in demo.css. %>
<div class="collapsible" data-controller="stimeo--collapsible">
<button
class="collapsible__trigger"
type="button"
aria-expanded="false"
aria-controls="collapsible-demo-content"
data-stimeo--collapsible-target="trigger"
data-action="click->stimeo--collapsible#toggle">
<span class="collapsible__chevron" aria-hidden="true"></span>
<%= t("components.collapsible.demo.trigger") %>
</button>
<div
class="collapsible__content"
id="collapsible-demo-content"
data-state="closed"
hidden
data-stimeo--collapsible-target="content">
<p class="collapsible__body"><%= t("components.collapsible.demo.body") %></p>
</div>
</div>
/*
* Presentation-only styles for the collapsible demo.
* The open/close animation uses the data-state the library sets on the content
* target and --stimeo--collapsible-content-height (the content's measured height).
*/
.collapsible {
max-width: 32rem;
border: 1px solid var(--border-default);
border-radius: 0.5rem;
overflow: hidden;
}
.collapsible__trigger {
display: flex;
align-items: center;
gap: 0.5rem;
width: 100%;
padding: 0.75rem 1rem;
background: var(--surface-subtle);
border: 0;
font: inherit;
font-weight: 600;
color: var(--fg);
cursor: pointer;
text-align: left;
}
.collapsible__chevron {
width: 0.5rem;
height: 0.5rem;
border-right: 2px solid currentColor;
border-bottom: 2px solid currentColor;
transform: rotate(-45deg);
transition: transform 0.2s ease;
}
.collapsible__trigger[aria-expanded="true"] .collapsible__chevron {
transform: rotate(45deg);
}
/* Transition the height while opening/closing or open (i.e. once hidden is removed). */
.collapsible__content {
height: 0;
overflow: hidden;
transition: height 0.2s ease;
}
.collapsible__content[data-state="open"] {
height: var(--stimeo--collapsible-content-height);
}
.collapsible__body {
margin: 0;
padding: 1rem;
}
/* Disable the transition under reduced motion (fall back to instant open/close). */
@media (prefers-reduced-motion: reduce) {
.collapsible__content,
.collapsible__chevron {
transition: none;
}
}
This demo needs no consumer-side JS (the controller handles the behavior).
These demo styles use shared design tokens (light + dark). Copy the shared styles too, then toggle data-theme on your root element for dark mode.
The data-* attributes you add to your own HTML to wire this component. Put the data-controller below on a root element, then place its targets / values / actions inside that element.
On the root element
data-controller="stimeo--collapsible"
Targets
| Name | Description | Attribute |
|---|---|---|
trigger
required
|
The button that toggles the single disclosure region; carries aria-expanded. |
data-stimeo--collapsible-target="trigger" |
content
required
|
The inline region that expands/collapses; its data-state, hidden, and height variable are driven by the controller. |
data-stimeo--collapsible-target="content" |
Values
| Name | Description | Attribute |
|---|---|---|
open
|
Initial open state reflected onto the DOM on connect without animating (default false). | data-stimeo--collapsible-open-value |
Actions
| Name | Description | Action |
|---|---|---|
toggle
|
Toggles the region open/closed (animated), ordering hidden/data-state/height so the transition can run. |
stimeo--collapsible#toggle |
State hooks
The library only manages these ARIA/data attributes and custom properties. Your CSS reads them to render the look — selectors like [aria-selected], [aria-expanded], or var(--stimeo--…) hook into this state.
| Hook | Target | Meaning |
|---|---|---|
aria-expanded |
Trigger | "true" when open, "false" when closed. |
hidden |
Content | Present when closed (added after the close transition). |
data-state |
Content | "open" / "closed" — the height-animation starting point. |
--stimeo--collapsible-content-height |
Content | The content's measured height (px) for the height transition. |