Collapsible
ui-collapsible wraps a native <details> element. Its ui-collapsible-trigger becomes the <summary>, and its
ui-collapsible-content is shown when it opens. The trigger lays out its content in a row with the ends pushed
apart, so a label and an icon need no extra markup. For a group of sections where only one is open at a time, use
Accordion.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Collapsible demo</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/dist/theme.css">
<script type="module" src="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.js"></script>
<style>
.demo-narrow {
width: min(100%, calc(var(--spacing) * 88));
}
</style>
</head>
<body>
<import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/collapsible.html"></import-element>
<import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/item.html"></import-element>
<div class="demo-narrow">
<ui-collapsible>
<ui-collapsible-trigger>
3 starred repositories
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="m7 15 5 5 5-5M7 9l5-5 5 5" /></svg>
</ui-collapsible-trigger>
<ui-collapsible-content>
<ui-item variant="outline" size="sm">realm/core</ui-item>
<ui-item variant="outline" size="sm">realm/ui</ui-item>
<ui-item variant="outline" size="sm">realm/site</ui-item>
</ui-collapsible-content>
</ui-collapsible>
</div>
</body>
</html>Examples
Open by default
Add open to start expanded. The attribute reflects, so it also tracks the current state.
Faster startup, smaller bundle and a new sidebar.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Collapsible demo</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/dist/theme.css">
<script type="module" src="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.js"></script>
<style>
.demo-narrow {
width: min(100%, calc(var(--spacing) * 88));
}
.demo-muted {
margin: 0;
font-size: var(--text-sm);
color: var(--muted-foreground);
}
</style>
</head>
<body>
<import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/collapsible.html"></import-element>
<div class="demo-narrow">
<ui-collapsible open>
<ui-collapsible-trigger>Release notes</ui-collapsible-trigger>
<ui-collapsible-content>
<p class="demo-muted">Faster startup, smaller bundle and a new sidebar.</p>
</ui-collapsible-content>
</ui-collapsible>
</div>
</body>
</html>Disabled
disabled stops the user from toggling it. The trigger is dimmed.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Collapsible demo</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/dist/theme.css">
<script type="module" src="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.js"></script>
<style>
.demo-narrow {
width: min(100%, calc(var(--spacing) * 88));
}
</style>
</head>
<body>
<import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/collapsible.html"></import-element>
<div class="demo-narrow">
<ui-collapsible disabled>
<ui-collapsible-trigger>Advanced options (locked)</ui-collapsible-trigger>
<ui-collapsible-content>Only administrators can change these.</ui-collapsible-content>
</ui-collapsible>
</div>
</body>
</html>Controlled from state
Bind open with _open and listen for toggle to keep state in sync.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Collapsible demo</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/dist/theme.css">
<script type="module" src="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.js"></script>
</head>
<body>
<import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/button.html"></import-element>
<import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/collapsible.html"></import-element>
<import-element from="./collapsible-state-demo.html"></import-element>
<collapsible-state-demo></collapsible-state-demo>
</body>
</html><custom-element name="collapsible-state-demo">
<script>
const panel = useState({ open: false });
function toggled(event) {
panel.open = event.target.open;
}
function flip() {
panel.open = !panel.open;
}
</script>
<style>
:host {
display: grid;
gap: calc(var(--spacing) * 3);
width: min(100%, calc(var(--spacing) * 80));
}
</style>
<ui-button variant="outline" size="sm" onclick="flip()">Toggle from outside</ui-button>
<ui-collapsible _open="#panel.open" ontoggle="toggled(event)">
<ui-collapsible-trigger>Filters</ui-collapsible-trigger>
<ui-collapsible-content>Status, owner and date range.</ui-collapsible-content>
</ui-collapsible>
</custom-element>API
Parts
| Element | Fills | Renders |
|---|---|---|
ui-collapsible |
A native <details>. Fills its container's width. |
|
ui-collapsible-trigger |
the <summary> of ui-collapsible |
A row with its content spread to both ends, in small semibold text. Icons are sized to calc(var(--spacing) * 4). |
ui-collapsible-content |
the body of ui-collapsible |
A column with calc(var(--spacing) * 2) gaps, shown when open. |
Attributes
ui-collapsible
| Attribute | Type | Default | Description |
|---|---|---|---|
open |
boolean | false |
Whether the content is shown. Reflects. |
disabled |
boolean | false |
Stops the user from toggling. Setting open from script still works. |
ui-collapsible-trigger and ui-collapsible-content have no attributes.
Events
| Event | Element | Description |
|---|---|---|
toggle |
ui-collapsible |
Fires when the user opens or closes it. Bubbles. Read event.target.open. Not fired when open is set from script. |
CSS parts
| Part | Element | Description |
|---|---|---|
trigger |
ui-collapsible |
The native <summary>. |
Accessibility
- The trigger is a native
<summary>, announced as a button with its expanded state. - Tab focuses the trigger. Enter or Space toggles it.
- Do not put other interactive elements in the trigger. The summary is already the button.