diff --git a/site/public/styles/global.css b/site/public/styles/global.css index 49d57c91f..f0dbd7569 100644 --- a/site/public/styles/global.css +++ b/site/public/styles/global.css @@ -45,12 +45,10 @@ h1 { border-bottom: 1px solid rgba(0, 0, 0, 0.2); } h2 { - margin-top: 1.5rem; padding-bottom: 0; padding-left: 0; padding-right: 0; padding-top: 0; - margin-bottom: 0.75rem; color: inherit; font-family: 'Cabin', 'Helvetica Neue', 'Segoe UI', 'Helvetica', 'Arial', sans-serif; font-weight: 500; @@ -63,7 +61,6 @@ h3 { padding-left: 0; padding-right: 0; padding-top: 0; - margin-bottom: 1.125rem; color: inherit; font-family: 'Cabin', 'Helvetica Neue', 'Segoe UI', 'Helvetica', 'Arial', sans-serif; font-weight: 500; @@ -76,7 +73,6 @@ h4 { padding-left: 0; padding-right: 0; padding-top: 0; - margin-bottom: 1.125rem; color: inherit; font-family: 'Cabin', 'Helvetica Neue', 'Segoe UI', 'Helvetica', 'Arial', sans-serif; font-weight: 500; @@ -89,7 +85,6 @@ h5 { padding-left: 0; padding-right: 0; padding-top: 0; - margin-bottom: 1.125rem; color: inherit; font-family: 'Cabin', 'Helvetica Neue', 'Segoe UI', 'Helvetica', 'Arial', sans-serif; font-weight: 500; @@ -102,7 +97,6 @@ h6 { padding-left: 0; padding-right: 0; padding-top: 0; - margin-bottom: 1.125rem; color: inherit; font-family: 'Cabin', 'Helvetica Neue', 'Segoe UI', 'Helvetica', 'Arial', sans-serif; font-weight: 500; @@ -111,18 +105,33 @@ h6 { line-height: 1.1; } +:is(h1, h2, h3, h4, h5, h6) { + text-wrap: balance; + margin-block: 2em 0.5em; + + /* Prevent excessive space between direct heading siblings. */ + & + & { + margin-block-start: 0; + } +} + +/* First heading on the page should neatly align to the top */ +h1:first-of-type { + margin-block-start: 0; +} + ul, ol { margin-left: 0; margin-right: 0; margin-top: 0; padding-bottom: 0; - padding-left: 0; padding-right: 0; padding-top: 0; margin-bottom: 1.125rem; - list-style-position: outside; - list-style-image: none; + + /* https://piccalil.li/blog/an-in-depth-guide-to-customising-lists-with-css/ */ + padding-left: 1lh; } p { @@ -131,6 +140,7 @@ p { padding-right: 0; padding-top: 0; margin-bottom: 1.125rem; + text-wrap: pretty; } figure { padding-bottom: 0; @@ -202,12 +212,10 @@ li { ol li, ul li { padding-left: 0; - list-style-position: inside; } li > ul, li > ol { - margin-left: 1.5rem; margin-bottom: calc(1.125rem / 2); margin-top: calc(1.125rem / 2); } diff --git a/site/src/pages/components/switch.explainer.mdx b/site/src/pages/components/switch.explainer.mdx index 1361618e0..460a9dab3 100644 --- a/site/src/pages/components/switch.explainer.mdx +++ b/site/src/pages/components/switch.explainer.mdx @@ -1,11 +1,59 @@ --- -menu: Active Proposals +menu: Non-active Proposals name: Switch (Explainer) path: /components/switch.explainer pathToResearch: /components/switch layout: ../../layouts/ComponentLayout.astro --- +
+
Author
+
[Philipp Gfeller](https://github.com/gfellerph)
+
Last update
+
2026-02-20
+
+ +{/* START doctoc generated TOC please keep comment here to allow auto update */} +{/* DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE */} + +## Table of contents + +
+Show / Hide Table of Contents + +- [Table of contents](#table-of-contents) +- [Overview](#overview) + - [Dictionary](#dictionary) + - [Previous proposal](#previous-proposal) + - [Design system analysis](#design-system-analysis) + - [Background](#background) + - [Use Cases](#use-cases) + - [Pattern differentiation](#pattern-differentiation) + - [Comparison switch attribute vs. switch element](#comparison-switch-attribute-vs-switch-element) + - [Usage recommendations](#usage-recommendations) + - [Binary states](#binary-states) + - [Immediate action](#immediate-action) + - [Features](#features) + - [Animation](#animation) + - [Background fade](#background-fade) + - [Track slide](#track-slide) + - [Prior Art/Examples](#prior-artexamples) + - [Styleability](#styleability) + - [Anatomy](#anatomy) + - [Switch with moving track](#switch-with-moving-track) + - [Switch with static track](#switch-with-static-track) + - [Accessibility](#accessibility) + - [Form Input](#form-input) + - [Use with Assistive Technology](#use-with-assistive-technology) + - [Accessibility resources](#accessibility-resources) + - [Globalization](#globalization) + - [Security](#security) +- [Related issues](#related-issues) +- [Resources](#resources) + +{/* END doctoc generated TOC please keep comment here to allow auto update */} +
+ ## Overview A switch toggles a binary state on or off. Other names include "toggle", "lightswitch", "toggle switch" or "toggle button". [^1] @@ -21,11 +69,27 @@ A switch toggles a binary state on or off. Other names include "toggle", "lights
Refers to the "off" position of the switch.
-### Alternative proposal -There is a [switch proposal at WHATWG](https://github.com/whatwg/html/pull/9546) (also see the original issue at https://github.com/whatwg/html/issues/4180) that would re-use the input element (``) to implement a switch component. This explainer here is focusing on a different approach, using a standalone `` element. See the [comparison section](#comparison) for a list of differences between the switch attribute proposal and the switch element explained here. +### Previous proposal + +Initially, this explainer proposed the introduction of a new `` element. However, after the introduction of the switch attribute proposal at WHATWG, the Open UI community group resolved to support the switch attribute proposal (see [resolution of issue #1282](https://github.com/openui/open-ui/issues/1282#issuecomment-3929622950)). The main reasoning behind this decision is: + +1. The switch attribute proposal is backwards compatible with browsers that don't support it by rendering a checkbox +2. Safari has already implemented this proposal ([WebKit blog post introducing the switch control](https://webkit.org/blog/15054/an-html-switch-control/)) +3. A majority of the switch examples inspected during the research phase can be implemented with the switch attribute proposal because they don't require content on the track or thumb + +This explainer lists the key differences between both implementations and serves as a reference, but will no longer be actively maintained. The switch attribute proposal is being tracked in the [switch attribute explainer](https://github.com/whatwg/html/issues/4180) and the linked [switch attribute pull request](https://github.com/whatwg/html/pull/9546). + +#### Design system analysis + +During research, 44 [Design Systems](/design-systems) were analyzed to understand the current state of the art in switch implementations. The results support the decision to support the switch attribute proposal, as the majority of implementations do not require content on the track or thumb and can be implemented with the switch attribute proposal. The key findings are: + +- 70% of Design Systems don't display any content inside their switches +- 30% display content on the track +- 18% display content on the thumb +- 88% use the background color transition animation +- 16% use a track slide animation -An implementation of this specification was already introduced by Safari Technology preview and Safari Beta (https://github.com/whatwg/html/pull/9546#issuecomment-1865357407). ### Background @@ -46,7 +110,7 @@ The word "toggle" is a reference to a kind of mechanism or joint consisting of t {/* _Primary use cases for this component._ */} -A switch can be used to toggle a binary state. Popular use-cases inlcude switching dark mode on or off, switching WiFi or other settings on or off and extends to any situation where a user is limited to a binary state - true or false, on or off. +A switch can be used to toggle a binary state. Popular use-cases include switching dark mode on or off, switching WiFi or other settings on or off, and extends to any situation where a user is limited to a binary state - true or false, on or off.
![Switch example by Material Design, Google Inc.](/images/switch/material-design-switch.png) @@ -55,9 +119,27 @@ A switch can be used to toggle a binary state. Popular use-cases inlcude switchi Toggling a switch always has an immediate effect. -### Comparison switch attribute vs. switch element +### Pattern differentiation -
Are these examples valid?
+The switch differs subtly from other related form controls. + +A switch differs from a checkbox because: + +- It has no indeterminate state +- It requires an immediate action, no confirmation is needed for the state to take effect + +A switch differs from a radio button because: + +- It always has an initial state, either on or off. A radio button group can be in an initial "nothing selected" state +- Switches cannot be grouped together like radio buttons with the same `name` attribute. Two switches cannot have the same `name` attribute. +- It requires an immediate action, no confirmation is needed for the state to take effect + +A switch differs from a toggle button (with aria-pressed) because: + +- A switch has a binary state, while a toggle button is tri-state (on, off, indeterminate) [^12] +- A toggle button can have an undefined initial state, while a switch always has an initial state of either on or off + +### Comparison switch attribute vs. switch element @@ -123,7 +205,7 @@ Toggling a switch always has an immediate effect. } ``` - - Can't use svg with `currentColor` + Can't use svg with `currentColor` @@ -157,7 +239,7 @@ Toggling a switch always has an immediate effect. } ``` - - Localization in CSS is not practical + Localization in CSS is not practical -
```html @@ -134,7 +216,7 @@ Toggling a switch always has an immediate effect. ``` - - Ability to use inline svg with `currentColor` + Ability to use inline svg with `currentColor`
```html @@ -169,32 +251,25 @@ Toggling a switch always has an immediate effect. ``` - - Any localization technique can be used to define slotted text + Any localization technique can be used to define slotted text
-### Non-goals +With the switch attribute and the `::track` pseudo-element, it's not possible to style the active and inactive track side separately which makes adding text or icons to either side more difficult. -{/* _A list of use cases, features, or functionality which are **not** goals for the component._ */} -#### Non-binary states -It's not recommended to use a switch to toggle between two opposite states[^4]. This could include a list vs. map view or switching between light and dark mode. Light mode can be switched on or off, but don't toggle between light and dark - two opposing states. +### Usage recommendations -#### Non-immediate action +#### Binary states -
- Should the "switch" be used to trigger immediate actions only? A majority of [analyzed Design - Systems](https://open-ui.org/design-systems/) recommend this behavior. This decision can have - influence on the API in regards to form association and validation. -
+It's recommended to use a switch to toggle a binary state. This means a switch should not be used to toggle between two opposite states[^4]. Examples of opposed states include a list vs. map view or switching between light and dark mode. Light mode can be switched on or off, but don't toggle between light and dark. -Don’t use a switch to select one or more options from a list. Switches should provide an immediate noticeable effect that doesn’t require the user to click Save or Submit to apply the new state. [^4] +#### Immediate action -Toggles should never require users to press a button to apply the settings. [^5] +Use a switch to trigger an immediate stateful action like toggling WiFi on a mobile phone. Switches should provide an immediate noticeable effect that doesn’t require the user to click "Save" or "Submit" to apply the new state. [^4] Switches should never require users to press a button to apply the settings. [^5] | Design System | Base element | Recommends immediate action | Recommends form usage\* | No recommendation | | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :-------------- | --------------------------: | ----------------------: | ----------------: | @@ -215,58 +290,21 @@ Toggles should never require users to press a button to apply the settings. [^5] | [Tailwind Elements (uses checkbox)](https://tailwind-elements.com/docs/standard/forms/switch/) | checkbox | | | ✅ | | [WAI-ARIA (examples include button and checkbox variant)](https://www.w3.org/WAI/ARIA/apg/patterns/switch/) | button/checkbox | | | ✅ | -_\* No Data found for explicit form usage encouragement, allthough implementations that rely on a checkbox indirectly allow that behavior._ - -#### Pattern differentiation +_\* No data found for recommendations to use a switch for non-immediate actions._ -The switch is not a checkbox or radio button alternative. -A switch differs from a checkbox because: - -- It has no indeterminate state -- It requires an immediate action, no confirmation is needed for the state to take effect - -A switch differs from a radio button because: - -- It always has an initial state, either on or off. A radio button group can be in an initial "nothing selected" state -- Switches cannot be grouped together like radio buttons with the same `name` attribute. Two switches cannot have the same `name` attribute. -- It requires an immediate action, no confirmation is needed for the state to take effect ### Features {/* _A list of the key features unique to this component._ */} -#### Form association - -
- How should form validation work? Is there a way to describe that the valid state is "off" instead - of "on" if this is required for some reason? -
- -A `` can be part of a form. The value of a switch is reported to the form target as either "on" or "off". - #### Animation -Two popular animation techniques are supported. +Research found two different animation techniques that are frequently used. ##### Background fade -Upon toggling the switch, it's background changes from grey (off) to green (on) and the toggle slides to the respective position. Content on the thumb can indicate the currently active state. Track content is also possible in this variant, but as the track does not move, the content is being hidden and revealed by the sliding thumb. - -##### Track slide - -Upon toggling the switch, the track and the thumb slide together to the respective position. The track reveals the active side of the track while the inactive track side is being hidden. This variant imitates physical switches and can also reveal track content on either side of the thumb, describing the currently active state. - -### Risks and Challenges - -{/* _Notable risks or challenges associated with the component. Link issues related to platform blockers._ */} - -Implementing the switch as a form element could lead developers to use it as a checkbox replacement. - -### Prior Art/Examples - -{/* _Link to the OpenUI research page for the component. If any existing, canonical, or exemplary implementations of the component are found beyond what is documented in the research page, make a separate PR to add them there._ */} -Open UI research page: https://open-ui.org/components/switch/ +Upon toggling the switch, its background changes from grey (off) to green (on) and the thumb slides to the respective position. Content on the thumb can indicate the currently active state. Track content is also possible in this variant, but as the track does not move, the content is being hidden and revealed by the sliding thumb.