CSS Toggles

Unofficial Proposal Draft,

This version:
http://tabatkins.github.io/css-toggle/
Issue Tracking:
CSSWG Issues Repository
Inline In Spec
Editors:
Tab Atkins Jr. (Google)
Miriam E. Suzanne (Invited Expert)
Suggest an Edit for this Spec:
GitHub Editor

Abstract

This specification defines a way to associate a toggleable state with an element which can be used in Selectors to select an element, and declarative ways to set and modify the state on the element.

CSS is a language for describing the rendering of structured documents (such as HTML and XML) on screen, on paper, etc.

Status of this document

This section describes the status of this document at the time of its publication. Other documents may supersede this document. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at https://www.w3.org/TR/.

Please send feedback by filing issues in GitHub (preferred), including the spec code “css-toggle” in the title, like this: “[css-toggle] …summary of comment…”. All issues and comments are archived. Alternately, feedback can be sent to the (archived) public mailing list www-style@w3.org.

This document is governed by the 15 September 2020 W3C Process Document.

This document was produced by a group operating under the W3C Patent Policy. W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy.

1. Introduction

This section is not normative.

Some user-interface languages define elements which can have "toggleable state", which can be modified by user interaction and selected using CSS Selectors. For example, in HTML, the <input type=checkbox> has a "checked" state which toggles between true and false when the user activates the element, and which is selected by the :checked pseudoclass.

The following markup example shows how to lightly abuse HTML semantics to declaratively use toggleable state:
<ul class='ingredients'>
  <li><label><input type=checkbox><span>1 banana</span></label>
  <li><label><input type=checkbox><span>1 cup blueberries</span></label>
  ...
</ul>
<style>
input[type='checkbox'] {
  display: none;
}
input[type='checkbox']:checked + span {
  color: silver;
  text-decoration: line-through;
}
</style>

In this markup, one can cross out ingredients as they’re used in the recipe by simply clicking on them.

This module generalizes this ability and allows it to be applied to any element via CSS. Elements can be declared to have toggleable state, with any number of states that can be toggled between. Multiple elements can share access to the same toggleable state, similar to HTML’s <input type=radio> element. This state can be manipulated by activating the element or other specified elements, or by other user interactions.

2. Toggle Concepts

A toggle is a struct associated with an element, which represents something that can be toggled on or off by user action, and matched with Selectors. Toggles have the following items:

name

A string.

In CSS, this name is provided as a <toggle-name>, which is either a <custom-ident> or as a <string>; in either case, the item’s value is the name.

<toggle-name> = <custom-ident> | <string>
For example, foo and "foo" are both valid ways to refer to the same toggle name.

However, foo and FOO are two different names, since they’re not identical to each other.

state

A non-negative integer: either 0 (the inactive state) or a value 1 or higher (the active states).

state names

A list of state names, each of which are strings.

Like the toggle’s name, in CSS they are <toggle-name>s, with the value of the item giving the state name.

group

A boolean indicating whether the toggle is part of a toggle group (of the same name) or not.

scope

A string enum indicating what sort of scope the toggle uses. It can have two values:

  • "wide", indicating the toggle has wide scope (it’s visible to the element, its descendants, and its following siblings and their descendants).

  • "narrow", indicating the toggle has narrow scope (it’s visible to the element and its descendants only).

Toggles are persistent state on an element, and are not directly affected by any CSS properties. An element can have any number of toggles.


A toggle group is a struct associated with an element, which groups together toggles of the same name so that only one can be in an active state at a time. Toggle groups have the following items:

name

A string, starting with two dashes (U+002D HYPHEN-MINUS).

Like a toggle’s name, in CSS they are given by a <toggle-name>, with the value of the item giving the name.

scope

A string enum indicating what sort of scope the toggle group uses. It can have two values:

  • "wide", indicating the toggle has wide scope (it’s visible to the element, its descendants, and its following siblings and their descendants).

  • "narrow", indicating the toggle has narrow scope (it’s visible to the element and its descendants only).

Toggle groups are created by the toggle-group property; they are not persistent state on an element. An element can have any number of toggle groups.

A toggle is in a toggle group if its group boolean is true; if the element is in scope for a toggle group with the same name as the toggle, it’s in that group; otherwise, it’s in a document-wide implicit toggle group with the same name.


Toggles and toggle groups have a scope, defining what additional elements (beyond the element the toggle/toggle group is on) can see and interact with the toggle/toggle group.

If the toggle (toggle group) has wide scope, it’s visible to the element it’s defined on, its descendants its following siblings, and their descendants.

If the toggle (toggle group) has narrow scope, it’s visible to the element it’s defined on and its descendants.

Toggles of the same name "shadow" earlier ones; if multiple toggles of a given name would have overlapping scopes, an element is only in scope for the toggle created by the nearest preceding element in tree order. The same applies to toggle groups. However, toggles and toggle groups do not interfere with each other’s scopes; an element can "see past" a toggle to find a toggle group of the same name it’s in scope for, and vice versa.


A toggle specifier is a struct associated with an element, defining the initial state of a toggle if one needs to be created on the element, and how to respond to a toggle activation. It has the following items:

name

A string specifying the toggle’s name.

initial state

A non-negative integer specifying the toggle’s initial state upon creation.

state names

A list of state names, each of which are strings, assigned to the toggle initially upon creation.

group

A boolean, specifying the toggle’s initial group boolean upon creation.

scope

A string (either "wide" or "narrow"), specifying the toggle’s initial scope upon creation.

maximum state

A positive integer specifying the highest active state the toggle can reach.

sticky

A boolean specifying how to react when a toggle activation would push the state past the specified maximum state: the state either stays within the active states and returns to 1 (if true) or cycles back to the inactive state (if false).

Toggle specifiers are created by the toggle-create property; they are not persistent state on an element. An element can have any number of toggle specifiers.

A default toggle specifier for a given name is a toggle specifier with a name of name, an initial state of 0, a state names of an empty list, a false group, a scope of "wide", a maximum state of 1, and a false sticky.

Note: This produces behavior similar to a checkbox.

2.1. Toggles and CSS Properties

To allow for toggles to be responded to by Selectors without causing any circularity issues, toggles themselves are invisible state on an element, separate from any CSS properties that might apply. The CSS properties merely define which elements can activate a toggle, and which elements can respond to a toggle activation (and how they do so).

For example, while an element needs toggle-create to establish a toggle, once a toggle is created, removing the toggle-create property does not affect the toggle.
.toggleable {
  toggle-create: foo 1;
  toggle-set: foo;
}
.toggleable:toggle(foo) {
  toggle-create: none;
  toggle-set: none;
}

In this example, the toggleable element declares that it can establish a foo toggle, and activate it. During a rendering update, the foo toggle is created on the element (initially with a value of 0, its inactive state); when the element is clicked, it’s incremented to its active state (1).

At this point, the :toggle(foo) rule begins to match, and removes the toggle-* properties. This does not remove the foo toggle or affect its value, however; it still exists and is still set to 1, so the :toggle() pseudo-class will continue matching. However, further activations of the element will no longer affect the foo toggle, since toggle-set was changed to none.

The foo toggle is thus "frozen" in the activated state (unless the author has other elements in the toggle’s scope that can also affect it, or tweaks the value manually via JS).

3. Creating a Toggle: the toggle-create property

Name: toggle-create
Value: none | <toggle-specifier>#
Initial: none
Applies to: all elements
Inherited: no
Percentages: n/a
Computed value: as specified
Canonical order: per grammar
Media: interactive
Animatable: no
<toggle-specifier> =
  <toggle-name>
  [
    [ <integer [0,∞]> / ]? <integer [1,∞]> ||
    sticky ||
    group ||
    self
  ]?

The toggle-create property causes toggles to be created on an element, and controls how the toggles are updated when they are activated.

none
The element has no toggle specifiers.

(This does not remove any toggles that have already been established on the element.)

<toggle-specifier>#
The element has one or more toggle specifiers, one per <toggle-specifier>, which determine how toggles will be initially created, and how they react to being activated.

Each <toggle-specifier> is composed of several parts, most of which are optional, corresponding to the items of a toggle specifier:

  • The initial <toggle-name> specifies the name, as the item’s value.

  • The first <integer>, if specified, specifies the initial state. If omitted, it’s set to 0.

    It must be less than or equal to the second <integer>, or else the declaration is invalid.

  • The second <integer>, if specified, specifies the maximum state. If omitted, it’s set to 1.

  • The sticky keyword, if specified, sets the sticky boolean to true. If omitted, it’s set to false.

  • The group keyword, if specified, sets the group boolean to true. If omitted, it’s set to false.

  • The self keyword, if specified, sets the scope enum to "narrow". If omitted, it’s set to "wide".

Revisiting the example in the Introduction, the same ingredient list can be specified in simple HTML and CSS:
<ul class='ingredients'>
   <li>1 banana
   <li>1 cup blueberries
  ...
</ul>
<style>
li {
  toggle-create: check self;
}
li:toggle(check) {
  color: silver;
  text-decoration: line-through;
}
</style>

The effect is identical to what was specified in the Introduction example, except the markup is much simpler and more semantic.

TODO create the toggle-states property that defines state names for a toggle, and amend the various properties to allow them to take a <toggle-name> instead of an <integer>.

Define the precise point in update the rendering when toggles are created if toggle-create names a toggle that doesn’t exist on the element yet.

3.1. Linking Toggle States: the toggle-group property

Name: toggle-group
Value: none | [ <toggle-name> self? ]#
Initial: none
Applies to: all elements
Inherited: no
Percentages: n/a
Computed value: as specified
Canonical order: per grammar
Media: interactive
Animatable: no

By default, each toggle’s state is independent; incrementing one has no effect an any other. The toggle-group property allows elements to link their toggles together: all toggles with the same name as the toggle group that are on elements in scope for the toggle group are linked, such that only one can be in an active state at a time, similar to HTML’s <input type=radio> element.

none
The element does not define a toggle group.
[<toggle-name> self?]#
The element defines one or more toggle groups, one per comma-separated item:
  • The <toggle-name> specifies the name, as the item’s value.

  • The self keyword, if specified, sets the scope enum to "narrow". If omitted, it’s set to "wide".

Only one toggle in a toggle group can be in an active state at a time; see toggle-set for details.

For example, toggle-group can be used to control a tabbed display, so that only one panel is displayed at a time:
<panel-set>
  <panel-tab>first tab</panel-tab>
  <panel-card>first panel</panel-card>
  <panel-tab>second tab</panel-tab>
  <panel-card>second card</panel-card>
  ...
</panel-set>
<style>
panel-set {
  /* The common ancestor sets up a group */
  toggle-group: tab;
}
panel-tab {
  /* Each tab creates a sticky toggle
    (so once it’s open, clicking again won’t close it),
    opts into the group,
    and declares itself a toggle activator */
  toggle: tab 1 group sticky;
}
panel-tab:first-of-type {
  /* The first tab also sets its initial state
    to be active */
  toggle: tab 1/1 group sticky;
}
panel-tab:toggle(tab) {
  /* styling for the active tab */
}
panel-card {
  /* cards are hidden by default */
  display: none;
}
panel-card:toggle(tab) {
  display: block;
}
</style>

Clicking on any tab will increment its corresponding toggle’s state from 0 to 1 (and the sticky keyword will keep it at 1 if activated multiple times), while resetting the rest of the tabs' states to 0. Each panel is in scope for the toggle defined by its preceding tab, so it can respond to the state as well.

Radio buttons have one particular tabbing/switching/activation behavior (they occupy a single tabindex spot; once reached you can move between them with arrow keys; moving to one auto-activates it), but not all groups will want that behavior. Accordions, in particular, probably don’t, and instead just want to effectively be independent checkboxes that happen to only have one active at a time.

We probably want to add a bool to toggle groups dictating this; are there more than these two behaviors to deal with?

3.2. Activating a Toggle: the toggle-set property

Name: toggle-set
Value: none | [ <toggle-name> <integer [0,∞]>? ]#
Initial: none
Applies to: elements without existing activation behavior (see prose)
Inherited: no
Percentages: n/a
Computed value: as specified
Canonical order: per grammar
Media: interactive
Animatable: no

The toggle-set property specifies that an element can be activated to change the state of one or more toggles. It has the following values:

none

The element does not manipulated any toggles.

<toggle-name> <integer [0,∞]>?

If the element already has existing activation behavior from the host language, this value does nothing.

Otherwise, the element becomes activatable, and when activated, for each comma-separated entry in the list, fires a toggle activation with the given <toggle-name> and, if an <integer> is specified, a target state of that integer.

A toggle activation is a struct with the following items:

name

The name of the toggle this is intended activate.

target state

An optional non-negative integer.

If specified, gives the state that this activation will attempt to put the toggle into. If unspecified, indicates that this activation will increment the toggle’s current state.

To fire a toggle activation on an element initial element with a toggle activation activation:
  1. Let el initially be initial element.

  2. If el has a toggle with the same name as activation, and initial element is in scope for the toggle, then:

    1. Let toggle be the toggle.

    2. If el has a toggle specifier with the same name, let specifier be it.

      Otherwise, let specifier be a new default toggle specifier for activation’s name.

    3. If activation’s target state is specified, set toggle’s state to the smaller of the target state and specifier’s maximum state.

      Otherwise, increment toggle’s state by 1. If the state is now higher than specifier’s maximum state, then set the state to 1 if specifier’s sticky flag is true, and to 0 if it’s false.

    4. If toggle’s state is now greater than zero and toggle is in a toggle group, then for each other toggle in the same toggle group, set their state to 0.

    5. Return from this algorithm.

  3. Otherwise, continue searching for a toggle:

    • If el has a previous sibling, set el to that element and return to step 2.

    • Otherwise, if el has a parent element, set el to that element and return to step 2.

    • Otherwise, return. (No toggle was found, so nothing happens.)

Define in much greater precision what it means to "become activatable". The element must become focusable (with a default spot in the focus order) and become capable of being activated by mouse/keyboard/etc. Similarly define the "already activatable" prose in more detail; we want to exclude things like text inputs, which would confuse a11y tooling, but include buttons that aren’t, like, submit buttons.

3.3. Creating and Activating Toggles Simultaneously: the toggle shorthand

Name: toggle
Value: <'toggle-create'>
Initial: see individual properties
Applies to: see individual properties
Inherited: see individual properties
Percentages: see individual properties
Computed value: see individual properties
Animation type: see individual properties
Canonical order: per grammar

While some cases require setting up a toggle on an ancestor of the elements that will activate and respond to the toggle, in many cases the scope rules for toggles are such that it’s fine to create the toggle on the element intended to activate the toggle as well.

The toggle shorthand sets both the toggle-create and toggle-set properties on an element together. The entire value of the property is assigned to toggle-create, while toggle-set is assigned to just the <toggle-name>s specified in the list, if any.

For example, in the following code for an spoiler-text element, the show/hide button precedes the content it will show and hide, so we can just create the toggle on it as well:
<spoiler-text>
  <summary>...</summary>
  <content>...</content>
</spoiler-text>
<style>
  spoiler-text > summary {
    toggle: show;
  }
  spoiler-text > content {
    toggle-visibility: toggle show;
  }
</style>

3.4. Accessibility Implications of Toggles

TODO

4. Selecting Elements Based on Toggle State: the :toggle() pseudo-class

[SELECTORS-4] defines the :checked pseudo-class, which allows author to match certain elements (as defined by the host language) depending on their "checked" state.

Toggles provides a very similar functionality, allowing elements to be selected based on their toggle state, the :toggle() pseudo-class:

:toggle( <toggle-name> <integer>? )

An element matches :toggle() if the element is in scope for a toggle with the name given by <toggle-name>, and either the toggle’s state matches the provided <integer>, or the <integer> is omitted and the toggle is in any active state.

For example, if a toggle named "used" is defined on each element in an recipe’s ingredient list, the ingredients can respond to being clicked on easily:
.ingredient {
  toggle: used;
}
.ingredient:toggle(used) {
  color: silver;
  text-decoration: line-through;
}
A checkbox that can represent an "indeterminate" value might have two active states.
.tristate-check {
  toggle: check 0/2;
}
.tristate-check:toggle(check 1) {
  /* "checked" styles */
}
.tristate-check:toggle(check 2) {
  /* "indeterminate" styles */
}
While :not(:toggle(foo)) will correctly match an element whose "foo" toggle is in an inactive state, it will also match any element that doesn’t see a "foo" toggle at all.

If this is inconvenient, only elements that actually know about a particular toggle can be targeted by specifying the inactive state specifically:

.card:toggle(show 0) {
  /* Definitely *not* shown */
}

5. Automatically Hiding With A Toggle

The content-visibility property allows an element to suppress the layout and rendering of its contents, similar to display: none; however, its auto value allows the contents to still be visible to various searching and accessibility features, like find-in-page, hash-navigation, or tab order, and then to automatically become visible when the element becomes relevant to the user.

A common use-case for toggles is also to control whether an element is shown or hidden, and in many cases it would also be useful to allow the contents of elements "hidden" in this way to be accessible in the same ways. To allow for this, the toggle-visibility property allows an element to both respond to and control a toggle with its visibility.

Name: toggle-visibility
Value: normal | toggle <toggle-name>
Initial: normal
Applies to: all elements
Inherited: no
Percentages: n/a
Computed value: as specified
Canonical order: per grammar
Animation type: not animatable

The toggle-visibility property allows an element to automatically tie its display to a particular toggle bi-directionally, while still exposing its contents to be focused, found-in-page, etc., automatically showing itself when relevant.

normal

The property has no effect.

toggle <toggle-name>

If the element is in scope for a toggle of the given <toggle-name>, and that toggle is in the inactive state, the element and its descendants generate no boxes or text runs, similar to display: none, but must still be available to user-agent features such as find-in-page, tab order navigation, etc., and must be focusable as normal, similar to content-visibility: auto.

If the element starts being relevant to the user, it fires a toggle activation, with a name of the given <toggle-name> and a target state of 1.

Note: If the toggle is currently in an inactive state and thus not generating any boxes, it can’t become relevant to the user due to being "on-screen" but the other options are still possible.

Note: If the toggle is in an active state, or the element can’t see the specified toggle at all, the element renders normally.

For example, an "accordion" display, such as used for a page of FAQs, can use toggle-visibility to hide the answers by default, but still make them accessible to find-in-page:
<dl class=accordion>
  <dt>Question 1?
  <dd>Long answer......
  <dt>Question 2?
  <dd>Another long answer.....
</dl>
<style>
  .accordion > dt {
    toggle: show;
  }
  .accordion > dd {
    toggle-visibility: toggle show;
  }
</style>

Each dt establishes a separate "show" toggle, with all the defaults filling in to produce a standard "checkbox"-like behavior, all initially in the inactive state. Each dt can be activated to show or hide the following answer.

Each dd can see the toggle established by its preceding dt, and will start out not rendering. If the user searches on the page for a term, or visits the page from a link with an #anchor linking into one of the answers, the relevant answer will automatically activate the toggle, causing the dd to become visible.

Define ordering of activations, so if multiple elements become relevant at the same time and they’re all part of a toggle group, which one "wins" is well-defined.

6. Scripting API

TODO

Conformance

Document conventions

Conformance requirements are expressed with a combination of descriptive assertions and RFC 2119 terminology. The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in the normative parts of this document are to be interpreted as described in RFC 2119. However, for readability, these words do not appear in all uppercase letters in this specification.

All of the text of this specification is normative except sections explicitly marked as non-normative, examples, and notes. [RFC2119]

Examples in this specification are introduced with the words “for example” or are set apart from the normative text with class="example", like this:

This is an example of an informative example.

Informative notes begin with the word “Note” and are set apart from the normative text with class="note", like this:

Note, this is an informative note.

Advisements are normative sections styled to evoke special attention and are set apart from other normative text with <strong class="advisement">, like this: UAs MUST provide an accessible alternative.

Conformance classes

Conformance to this specification is defined for three conformance classes:

style sheet
A CSS style sheet.
renderer
A UA that interprets the semantics of a style sheet and renders documents that use them.
authoring tool
A UA that writes a style sheet.

A style sheet is conformant to this specification if all of its statements that use syntax defined in this module are valid according to the generic CSS grammar and the individual grammars of each feature defined in this module.

A renderer is conformant to this specification if, in addition to interpreting the style sheet as defined by the appropriate specifications, it supports all the features defined by this specification by parsing them correctly and rendering the document accordingly. However, the inability of a UA to correctly render a document due to limitations of the device does not make the UA non-conformant. (For example, a UA is not required to render color on a monochrome monitor.)

An authoring tool is conformant to this specification if it writes style sheets that are syntactically correct according to the generic CSS grammar and the individual grammars of each feature in this module, and meet all other conformance requirements of style sheets as described in this module.

Partial implementations

So that authors can exploit the forward-compatible parsing rules to assign fallback values, CSS renderers must treat as invalid (and ignore as appropriate) any at-rules, properties, property values, keywords, and other syntactic constructs for which they have no usable level of support. In particular, user agents must not selectively ignore unsupported component values and honor supported values in a single multi-value property declaration: if any value is considered invalid (as unsupported values must be), CSS requires that the entire declaration be ignored.

Implementations of Unstable and Proprietary Features

To avoid clashes with future stable CSS features, the CSSWG recommends following best practices for the implementation of unstable features and proprietary extensions to CSS.

Non-experimental implementations

Once a specification reaches the Candidate Recommendation stage, non-experimental implementations are possible, and implementors should release an unprefixed implementation of any CR-level feature they can demonstrate to be correctly implemented according to spec.

To establish and maintain the interoperability of CSS across implementations, the CSS Working Group requests that non-experimental CSS renderers submit an implementation report (and, if necessary, the testcases used for that implementation report) to the W3C before releasing an unprefixed implementation of any CSS features. Testcases submitted to W3C are subject to review and correction by the CSS Working Group.

Further information on submitting testcases and implementation reports can be found from on the CSS Working Group’s website at http://www.w3.org/Style/CSS/Test/. Questions should be directed to the public-css-testsuite@w3.org mailing list.

Index

Terms defined by this specification

Terms defined by reference

References

Normative References

[CSS-CONTAIN-2]
Tab Atkins Jr.; Florian Rivoal; Vladimir Levin. CSS Containment Module Level 2. 16 December 2020. WD. URL: https://www.w3.org/TR/css-contain-2/
[CSS-DISPLAY-3]
Tab Atkins Jr.; Elika Etemad. CSS Display Module Level 3. 18 December 2020. CR. URL: https://www.w3.org/TR/css-display-3/
[CSS-VALUES-3]
Tab Atkins Jr.; Elika Etemad. CSS Values and Units Module Level 3. 6 June 2019. CR. URL: https://www.w3.org/TR/css-values-3/
[CSS-VALUES-4]
Tab Atkins Jr.; Elika Etemad. CSS Values and Units Module Level 4. 11 November 2020. WD. URL: https://www.w3.org/TR/css-values-4/
[DOM]
Anne van Kesteren. DOM Standard. Living Standard. URL: https://dom.spec.whatwg.org/
[HTML]
Anne van Kesteren; et al. HTML Standard. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[INFRA]
Anne van Kesteren; Domenic Denicola. Infra Standard. Living Standard. URL: https://infra.spec.whatwg.org/
[RFC2119]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. March 1997. Best Current Practice. URL: https://datatracker.ietf.org/doc/html/rfc2119
[SELECTORS-4]
Elika Etemad; Tab Atkins Jr.. Selectors Level 4. 21 November 2018. WD. URL: https://www.w3.org/TR/selectors-4/

Property Index

Name Value Initial Applies to Inh. %ages Ani­mat­able Anim­ation type Canonical order Com­puted value Media
toggle <'toggle-create'> see individual properties see individual properties see individual properties see individual properties see individual properties per grammar see individual properties
toggle-create none | <toggle-specifier># none all elements no n/a no per grammar as specified interactive
toggle-group none | [ <toggle-name> self? ]# none all elements no n/a no per grammar as specified interactive
toggle-set none | [ <toggle-name> <integer [0,∞]>? ]# none elements without existing activation behavior (see prose) no n/a no per grammar as specified interactive
toggle-visibility normal | toggle <toggle-name> normal all elements no n/a not animatable per grammar as specified

Issues Index

TODO create the toggle-states property that defines state names for a toggle, and amend the various properties to allow them to take a <toggle-name> instead of an <integer>.
Define the precise point in update the rendering when toggles are created if toggle-create names a toggle that doesn’t exist on the element yet.
Radio buttons have one particular tabbing/switching/activation behavior (they occupy a single tabindex spot; once reached you can move between them with arrow keys; moving to one auto-activates it), but not all groups will want that behavior. Accordions, in particular, probably don’t, and instead just want to effectively be independent checkboxes that happen to only have one active at a time.

We probably want to add a bool to toggle groups dictating this; are there more than these two behaviors to deal with?

Define in much greater precision what it means to "become activatable". The element must become focusable (with a default spot in the focus order) and become capable of being activated by mouse/keyboard/etc. Similarly define the "already activatable" prose in more detail; we want to exclude things like text inputs, which would confuse a11y tooling, but include buttons that aren’t, like, submit buttons.
TODO
Define ordering of activations, so if multiple elements become relevant at the same time and they’re all part of a toggle group, which one "wins" is well-defined.
TODO