Accordion & tree
Two components, one element. <details> is a button with an expanded state, keyboard handling and find-in-page support already attached, which is why neither of these ships a line of JavaScript.
Reference
sk-accordion
A group of <details>. Giving every item the same name attribute makes the group exclusive - opening one closes the others - which is a platform feature, not state the application holds. The panel animates open through ::details-content; where that is unimplemented the panel simply appears, which is what every <details> has always done.
<div class="sk-accordion">
<details class="sk-accordion-item" name="faq">
<summary class="sk-accordion-summary">
<span class="sk-accordion-label">…</span>
<span class="sk-accordion-marker">…</span>
</summary>
<div class="sk-accordion-panel">…</div>
</details>
</div>| Attribute | Type | Default | Notes |
|---|---|---|---|
name | string | - | Shared by every item in an exclusive group. Leave it off when sections should open independently, which is better for anything the reader might compare. |
open | boolean | - | On at most one item in a named group. Two open items with the same name is a contradiction, and the browser resolves it by closing all but the last. |
sk-accordion | wrapper | - | Only chrome - the border and the rules between items. A lone sk-accordion-item is a complete disclosure. |
sk-tree
Nested lists of disclosures. Deliberately NOT role="tree": that role promises arrow-key navigation, expand and collapse on the horizontal arrows, Home and End, and a single tab stop for the whole widget - all of which needs script. Announcing it without implementing it tells a screen reader user to press keys that do nothing, so this stays a nested list, the same call Tabs makes.
<ul class="sk-tree">
<li>
<details class="sk-tree-branch" open>
<summary class="sk-tree-summary">…</summary>
<ul class="sk-tree-group">…</ul>
</details>
</li>
<li><a class="sk-tree-leaf" href="…">…</a></li>
</ul>| Attribute | Type | Default | Notes |
|---|---|---|---|
sk-tree-group | nested ul | - | Carries the indent and the guide line. The line is a border on the list, so it runs the height of the branch and stops exactly where it ends. |
aria-current | "page" | - | On the open file. Same attribute as the sidebar nav, for the same reason. |
Examples
Accordion
Exclusive: every item shares a name, so opening one closes the rest. No script and nothing holding the state.
How do refunds work?
Can I move my save between machines?
Which platforms are supported?
Show markup
<div class="sk-accordion">
<details class="sk-accordion-item" name="faq" open>
<summary class="sk-accordion-summary">
<span class="sk-accordion-label">
How do refunds work?
</span>
<span class="sk-accordion-marker">
<svg class="sk-icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
<path d="m6 9 6 6 6-6">
</path>
</svg>
</span>
</summary>
<div class="sk-accordion-panel">
Within 14 days of purchase, in full, no questions asked. After that it depends on how much of the season pass has been played.
</div>
</details>
<details class="sk-accordion-item" name="faq">
<summary class="sk-accordion-summary">
<span class="sk-accordion-label">
Can I move my save between machines?
</span>
<span class="sk-accordion-marker">
<svg class="sk-icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
<path d="m6 9 6 6 6-6">
</path>
</svg>
</span>
</summary>
<div class="sk-accordion-panel">
Saves sync automatically when you are signed in. A local save can be exported from the pause menu and imported anywhere.
</div>
</details>
<details class="sk-accordion-item" name="faq">
<summary class="sk-accordion-summary">
<span class="sk-accordion-label">
Which platforms are supported?
</span>
<span class="sk-accordion-marker">
<svg class="sk-icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
<path d="m6 9 6 6 6-6">
</path>
</svg>
</span>
</summary>
<div class="sk-accordion-panel">
Windows, macOS and Linux. Console builds are not planned.
</div>
</details>
</div>Independent
The same markup without a name. Both can be open at once, which is what you want when the sections are meant to be compared.
Free
Team
Show markup
<div class="sk-accordion">
<details class="sk-accordion-item">
<summary class="sk-accordion-summary">
<span class="sk-accordion-label">
Free
</span>
<span class="sk-accordion-marker">
<svg class="sk-icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
<path d="m6 9 6 6 6-6">
</path>
</svg>
</span>
</summary>
<div class="sk-accordion-panel">
One project, community support.
</div>
</details>
<details class="sk-accordion-item">
<summary class="sk-accordion-summary">
<span class="sk-accordion-label">
Team
</span>
<span class="sk-accordion-marker">
<svg class="sk-icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
<path d="m6 9 6 6 6-6">
</path>
</svg>
</span>
</summary>
<div class="sk-accordion-panel">
Unlimited projects, shared billing, priority support.
</div>
</details>
</div>Standalone disclosure
One item, no group wrapper. The "show details" toggle.
The build failed during the asset pipeline step.
Show the full log
> dsbuild dsbuild: wrote css/dist/sk.css error: unexpected token at line 41
Show markup
<div class="sk-flex sk-flex-col sk-gap-3">
<p class="sk-page-subtitle">
The build failed during the asset pipeline step.
</p>
<details class="sk-accordion-item">
<summary class="sk-accordion-summary">
<span class="sk-accordion-label">
Show the full log
</span>
<span class="sk-accordion-marker">
<svg class="sk-icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
<path d="m6 9 6 6 6-6">
</path>
</svg>
</span>
</summary>
<div class="sk-accordion-panel">
<pre>
> dsbuild
dsbuild: wrote css/dist/sk.css
error: unexpected token at line 41
</pre>
</div>
</details>
</div>Tree
Tab through it: every node is reachable, and a closed branch opens to find-in-page.
css
dist
components
- README.md
Show markup
<ul class="sk-tree" aria-label="Repository">
<li>
<details class="sk-tree-branch" open>
<summary class="sk-tree-summary">
<span class="sk-tree-marker">
<svg class="sk-icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
<path d="m9 18 6-6-6-6">
</path>
</svg>
</span>
css
</summary>
<ul class="sk-tree-group">
<li>
<details class="sk-tree-branch" open>
<summary class="sk-tree-summary">
<span class="sk-tree-marker">
<svg class="sk-icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
<path d="m9 18 6-6-6-6">
</path>
</svg>
</span>
src
</summary>
<ul class="sk-tree-group">
<li>
<a class="sk-tree-leaf" href="#tree">
index.css
</a>
</li>
<li>
<a class="sk-tree-leaf" href="#tree" aria-current="page">
accordion.css
</a>
</li>
<li>
<a class="sk-tree-leaf" href="#tree">
tree.css
</a>
</li>
</ul>
</details>
</li>
<li>
<details class="sk-tree-branch">
<summary class="sk-tree-summary">
<span class="sk-tree-marker">
<svg class="sk-icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
<path d="m9 18 6-6-6-6">
</path>
</svg>
</span>
dist
</summary>
<ul class="sk-tree-group">
<li>
<a class="sk-tree-leaf" href="#tree">
sk.css
</a>
</li>
</ul>
</details>
</li>
</ul>
</details>
</li>
<li>
<details class="sk-tree-branch">
<summary class="sk-tree-summary">
<span class="sk-tree-marker">
<svg class="sk-icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
<path d="m9 18 6-6-6-6">
</path>
</svg>
</span>
components
</summary>
<ul class="sk-tree-group">
<li>
<a class="sk-tree-leaf" href="#tree">
button.templ
</a>
</li>
</ul>
</details>
</li>
<li>
<a class="sk-tree-leaf" href="#tree">
README.md
</a>
</li>
</ul>