Every order ships with tracking.
Collapsible
A trigger that shows and hides a region, with its height animated.
Order details
A header row holds the title and an icon trigger; the status stays visible, the rest opens below.
Order #4189
Status: Shipped
Ships to 221B Baker St, London
2 items, $48.00
Code
<Collapsible class="card">
<div class="row">
<h4>Order #4189</h4>
<CollapsibleTrigger>
<Button variant="ghost" icon size="sm" label="Toggle details">
<Icon name="chevrons-up-down" />
</Button>
</CollapsibleTrigger>
</div>
<p>Status: Shipped</p>
<CollapsibleContent>
<p>Ships to 221B Baker St, London</p>
<p>2 items, $48.00</p>
</CollapsibleContent>
</Collapsible>Usage
import { Collapsible, CollapsibleTrigger, CollapsibleContent } from "@elements/ui/collapsible";
<Collapsible>
<div class="row">
<h4>Order #4189</h4>
<CollapsibleTrigger>
<Button variant="ghost" icon size="sm" label="Toggle details"><Icon name="chevrons-up-down" /></Button>
</CollapsibleTrigger>
</div>
<p>Status: Shipped</p>
<CollapsibleContent>
<p>Shipping address and items</p>
</CollapsibleContent>
</Collapsible>Examples
Controlled
Bind open to state. The trigger writes the value back; onOpenChange fires only for its own toggles.
Content.
Code
<Collapsible open={state.open} onOpenChange={(open) => state.last = String(open)}>
<CollapsibleTrigger><Button>Toggle</Button></CollapsibleTrigger>
<CollapsibleContent>Content.</CollapsibleContent>
</Collapsible>
<Button onclick={() => state.open = !state.open}>Toggle from outside</Button>Guarded
onOpenChange runs before the change with event details (reason, event, cancel). details.cancel() keeps it closed until the guard is off.
sk_live_4f9a2c
Code
<Collapsible open={state.open} onOpenChange={(open, details) => {
if (open && !state.allowed) details.cancel();
}}>
<CollapsibleTrigger><Button>Show the API key</Button></CollapsibleTrigger>
<CollapsibleContent>sk_live_4f9a...</CollapsibleContent>
</Collapsible>Open by default
Rendered open on the server: visible on load, no animation.
Canvas tote, 40 x 38 cm
Organic cotton, made in Portugal
Code
<Collapsible open>
<CollapsibleTrigger>
<Button variant="ghost">
Product details <Icon name="chevron-down" class="collapsible-chevron" />
</Button>
</CollapsibleTrigger>
<CollapsibleContent>...</CollapsibleContent>
</Collapsible>Trigger with a tooltip
A Tooltip around the trigger button is looked through: aria-expanded and data-state land on the button.
Version 2.4
Faster builds and a new theme picker.
Code
<Collapsible>
<CollapsibleTrigger>
<Tooltip content="Show the release notes">
<Button slot="trigger" variant="ghost" icon label="Release notes"><Icon name="chevrons-up-down" /></Button>
</Tooltip>
</CollapsibleTrigger>
<CollapsibleContent>...</CollapsibleContent>
</Collapsible>Settings panel
Fields inside closed content leave the tab order.
Code
<Collapsible>
<CollapsibleTrigger><Button variant="outline">Radius settings</Button></CollapsibleTrigger>
<CollapsibleContent>
<label>Radius <input type="number" value={8}></label>
...
</CollapsibleContent>
</Collapsible>File tree
Collapsibles nest; each folder toggles on its own.
Code
<Collapsible>
<CollapsibleTrigger>
<button class="node"><Icon name="chevron-right" class="collapsible-chevron is-right" /> components</button>
</CollapsibleTrigger>
<CollapsibleContent>
<Collapsible>...a nested folder...</Collapsible>
<span class="node">button.tsx</span>
</CollapsibleContent>
</Collapsible>Right to left
Content and chevrons follow the text direction: a closed folder's chevron is mirrored to point left.
Code
<div dir="rtl">
<Collapsible>
<CollapsibleTrigger>
<button class="node"><Icon name="chevron-right" class="collapsible-chevron is-right" /> المستندات</button>
</CollapsibleTrigger>
<CollapsibleContent>...</CollapsibleContent>
</Collapsible>
</div>Frequently asked questions
APG's FAQ: each answer is its own disclosure, so several can be open at once.
Yes, within 30 days of delivery, in the original packaging.
Anywhere in the EU, the UK and North America.
Code
<Collapsible>
<CollapsibleTrigger><Button variant="ghost">Can I return an order?</Button></CollapsibleTrigger>
<CollapsibleContent>Yes, within 30 days.</CollapsibleContent>
</Collapsible>
<Collapsible>...</Collapsible>Image description
APG's image description: a long text alternative under a figure, shown on request.
Sales rose each quarter: 12, 17, 22 and 31 thousand.
Code
<figure>
<img src="./sales.png" alt="Quarterly sales">
<Collapsible>
<CollapsibleTrigger><Button variant="link">Image description</Button></CollapsibleTrigger>
<CollapsibleContent>Sales rose each quarter, from 12 to 31 thousand.</CollapsibleContent>
</Collapsible>
</figure>Find in page
hiddenUntilFound keeps the closed content searchable: find in page, or a link to its text, opens it.
Orders over fifty dollars ship overnight at no charge.
Code
<Collapsible>
<CollapsibleTrigger><Button variant="ghost">Shipping policy</Button></CollapsibleTrigger>
<CollapsibleContent hiddenUntilFound>
Orders over $50 ship overnight at no charge.
</CollapsibleContent>
</Collapsible>Text trigger
Plain text in CollapsibleTrigger becomes a button, so the keyboard reaches it.
Code
<Collapsible>
<CollapsibleTrigger>Show more</CollapsibleTrigger>
<CollapsibleContent>Every order ships with tracking.</CollapsibleContent>
</Collapsible>Disabled
The trigger is disabled and the content stays closed.
Yes. It is MIT licensed.
Code
<Collapsible disabled={state.disabled}>
<CollapsibleTrigger><Button>Can I use this in my project?</Button></CollapsibleTrigger>
<CollapsibleContent>Yes. It is MIT licensed.</CollapsibleContent>
</Collapsible>In a form
Closed content stays mounted, so its fields submit. A required field left empty inside opens it on submit, so the browser can point at the field.
Code
<form onsubmit={() => save(state)}>
<Collapsible>
<CollapsibleTrigger><Button variant="ghost">Billing address</Button></CollapsibleTrigger>
<CollapsibleContent><input name="street" required></CollapsibleContent>
</Collapsible>
<Button type="submit">Save</Button>
</form>