<div class=checkbox></div>
<style>
.checkbox {
toggle: checked;
}
.checkbox:toggle(checked)::before {
content: "✔";
}
</style>
<div class=checkbox></div>
<div class=checkbox></div>
<div class=checkbox></div>
<div class=checkbox></div>
<div class=checkbox></div>
<style>
.checkbox {
toggle: checked;
}
.checkbox:toggle(checked)::before {
content: "✔";
}
</style>
<div class=radio-group>
<div class=radio></div>
<div class=radio></div>
<div class=radio></div>
<div class=radio></div>
<div class=radio></div>
</div>
<style>
.radio-group {
toggle-group: radio;
}
.radio {
toggle: radio group;
}
.radio:toggle(radio 1)::before {
content: "•";
}
.radio:toggle(radio 0)::before {
content: "◦";
}
</style>
<div class=details>
<div class=summary>...</div>
<div class=contents>...</div>
</div>
<style>
.details {
toggle-root: disclosure;
}
.summary {
toggle-trigger: disclosure;
}
.summary:toggle(disclosure 0)::before {
content: "▶";
}
.summary:toggle(disclosure 1)::before {
content: "▼";
}
.contents {
toggle-visibility: toggle disclosure;
}
</style>
<div class=tab-group>
<div class=tab>one</div>
<div class=tab-panel>one content</div>
<div class=tab>two</div>
<div class=tab-panel>two content</div>
</div>
<style>
.tab-group {
toggle-group: tab;
}
.tab {
toggle: tab group;
}
.tab:toggle(tab) {
font-weight: bold;
}
.tab-panel {
toggle-visibility: tab;
}
.tab-group {
display: grid;
grid-template-rows: min-content auto;
grid-template-columns: auto auto; /* match the number of tabs */
}
.tab {
grid-row: 1;
}
.tab-panel {
grid-row: 2;
grid-column: 1 / -1;
}
</style>
At the moment, this is the only markup pattern that works with the design, and comes with some limitations. It will be improved somewhat with some planned CSS updates: one that lets you flow multiple elements into the same grid cell (so you can make a single-column grid, rather than predicting the number of tabs), and another that uses grid order for the a11y/focus/etc trees (rather than markup order).
I'm also considering an upgrade to Toggle that lets you set up a single toggle with N states, automatically associate a set of toggle-trigger elements with a distinct state, and then also associate another set of elements with each of the states, so this example would use a single toggle (rather than one per tab, all in a group) and could be written in the "all tabs first, followed by all panels" pattern that is sometimes preferred. The CSS might then look like:
.tab-group {
toggle: tab auto-number;
}
.tab {
toggle-auto-number: tab trigger;
toggle-trigger: tab set auto-number;
}
.tab-panel {
toggle-auto-number: tab use;
toggle-visiblity: toggle tab auto-number;
}
Here, toggle-auto-number
will associate the element + toggle name with an auto-incrementing integer,
which can then be used by the toggle properties.
The second keyword is a freeform tag used to set up multiple auto-numberings for the same toggle name,
so here the .tab and .tab-panel elements don't interfere with each other;
the Nth tab and the Nth tab-panel get the same integer,
and thus associate with each other,
regardless of whether the markup is written tabs-first or tabs-interspersed.
<div class=accordion-group>
<div class=accordion-header>one</div>
<div class=accordion-panel>one content</div>
<div class=accordion-header>two</div>
<div class=accordion-panel>two content</div>
</div>
<style>
.accordion-group {
toggle-group: accordion;
}
.accordion-header {
toggle: accordion group;
}
.accordion-header:toggle(accordion 0)::before {
content: "▶";
}
.accordion-header:toggle(accordion 1)::before {
content: "▼";
}
.accordion-panel {
toggle-visibility: accordion;
}
</style>
This implements a "one open at a time" accordion.
If you want the opening states to be independent,
just remove the toggle-group
from .accordion-group
and the group
keyword from .accordion-header
.
<ul>
<li class=tree-node>
<button class=tree-toggle><span class=to-open>[+]</span><span class=to-close>[-]</span></button>
<div class=tree-content>...</div>
<li class=tree-node>
<button class=tree-toggle><span class=to-open>[+]</span><span class=to-close>[-]</span></button>
<div class=tree-content>
<ul>
<li class=tree-node>
<button class=tree-toggle><span class=to-open>[+]</span><span class=to-close>[-]</span></button>
<div class=tree-content>...</div>
<li class=tree-node>
<button class=tree-toggle><span class=to-open>[+]</span><span class=to-close>[-]</span></button>
<div class=tree-content>...</div>
</ul>
</div>
</ul>
<style>
.tree-node {
toggle-root: tree;
}
.tree-toggle {
toggle-trigger: tree;
}
.tree-toggle:toggle(tree 0) > .to-close,
.tree-toggle:toggle(tree 1) > .to-open {
display: none;
}
.tree-content {
toggle-visiblity: toggle tree;
}
</style>
n/a, this is only tangentially related to Toggle. (Might be useful to hook up a toggle to scroll-snap state, so it can be used for styling purposes.)
But talk to Nicole Sullivan about this; we're planning work on this exact pattern right now.
<button class=color-change>
<span class=red>red</span>
<span class=green>green</span>
<span class=blue>blue</span>
</button>
<style>
.color-change {
toggle: color [red green blue];
}
.red:not(:toggle(color red)),
.green:not(:toggle(color green)),
.blue:not(:toggle(color blue)) {
display: none;
}
</style>
Again, somewhat annoying since you have to manually annotate the sub-elements with each state. Like the Tabs example, this will be improved by letting a set of elements automatically associate themselves with unique states from a toggle, so it might look something like:
.color-change {
toggle: color auto-number;
}
.color-change > span {
toggle-auto-number: color;
toggle-visibility: toggle color auto-number;
/* depends on toggle-visiblity being able to link to a specific toggle value
rather than just "is any active state",
which is planned but not yet in the spec */
}
Identical to Disclosure.
Can potentially be identical to Disclosure, but more likely should be JS-driven to use the Popup API.