- Kent Tamura [email protected]
This document proposes a new HTML element for a 'switch' control. It is provided as a built-in module.
Many UI frameworks have switch controls to represent off/on states and ask a user to change the state. As of April 2019 the HTML standard has a checkbox, which is functionally similar to switch control. However:
- Semantically, a switch and checkbox have different meanings, with a switch being more appropriate for turning things on/off. (See e.g. Microsoft Fluent design guidelines, Nielsen Norman Group, UX Planet.)
- Switches and checkboxes manifest differently to accessibility technology: see the
switch
ARIA role. - It's hard to change checkbox's appearance to a switch-like appearance, for when that user experience is desired.
- Identical appearance on all platforms and all supported browsers by default
- Easy and flexible customization
- The switch control should provide a way to switch its appearance from the default one to platform-dependent one.
- The switch control should provide a way to customize color, size, radius, etc. of its visual parts.
- API similar to existing form controls
<script type="module">
import 'std:elements/switch';
</script>
<form action="...">
<label>Enable something <std-switch name="something"></std-switch></label>
<input type="submit">
</form>
Users can turn on/off the switch by clicking it, and submitting the form will have an entry for the switch control.
The element is provided as a built-in module.
import 'std:elements/switch'
defines <std-switch>
element and StdSwitchElement
interface.
<std-switch>
is similar to <input type=checkbox>
in terms of API. A <std-switch>
instance has two states; "off" and "on". It doesn't support indeterminate state like the checkbox.
- Global attributes
autocomplete
disabled
form
name
required
TODO: Supports autofocus
, which should be a global attribute. (whatwg/html#4563)
These attributes should work same as existing form controls.
<std-switch>
should support checked
and defaultchecked
attributes (Issue #2). There are some approaches for them. We have not decided yet. (Issue #4)
- A) Compatible with
<input type=checkbox>
checked
attribute represents the default state, anddefaultChecked
property reflects onchecked
attribute. No attribute mapped tochecked
property. - B) Simple mappings
defaultChecked
property reflects ondefaultchecked
attribute value, andchecked
property reflects onchecked
attribute. Code likeswitch.checked = true
addschecked
attribute. We need to specifydefaultchecked
attribute if we want to reset the element to on state, like<std-switch defaultchecked checked>
-
checked
- Represents the element's state. See the previous section -
defaultChecked
- Represents the default state. See the previous section -
disabled
- Same as existing form controls -
form
- Same as existing form controls -
labels
- Same as existing form controls -
name
- Same as existing form controls -
type
- returns'std-switch'
-
willValidate
- Same as existing form controls -
validationMessage
- Same as existing form controls -
checkValidity()
- Same as existing form controls -
reportValidity()
- Same as existing form controls -
setCustomValidity(errorMessage)
- Same as existing form controls
- Global ones such as
:focus
:hover
:target
:valid
- match if the element has norequired
attribute, of if the element hasrequired
attribute and the state is on.:invalid
- match if the element doesn't match to:valid
.:disabled
- match if the element hasdisabled
attribute, or an ancestor<fieldset>
hasdisabled
attribute.:enabled
- match if the element doesn't match to:disabled
.
TODO: Supports :checked
(Issue #3), :required
, and :optional
(w3c/webcomponents#813)
<std-switch>
dispatches input
and change
events when a user changes the element's state.
form
Markup like<form>...<std-switch></std-switch>...</form>
associates the<std-switch>
element to the<form>
.<form>
'selements
property lists the<std-switch>
, and submitting the<form>
adds an entry for the<std-switch>
.fieldset
Markup like<fieldset>...<std-switch></std-switch>...</fieldset>
associates the<std-switch>
element to the<fieldset>
.<fieldset>
'selements
property lists the<std-switch>
, and disabling the<fieldset>
also disables the<std-switch>
implicitly.label
Markup like<label>...<std-switch></std-switch></label>
associates the<std-switch>
element to the<label>
. Clicking anywhere in the<label>
changes the state of the<std-switch>
.
There are two approaches. We have not decided yet. (Issue #5)
- A) Compatible with
<input type=checkbox>
<std-swtich name=something>
with "off" state will send no entry. One with "on" state will sendvalue
attribute value if it exists, orsomething=on
. - B) Send state simply
<std-swtich name=something>
with "off" state will sendsomething=off
, one with "on" state will sendsomething=on
.
TODO: an easy flag to enable platform-dependent appearance (Issue #6)
When the flag is enabled, std-switch
element is styled as UISwitch on iOS, Material Design switch on Android, Fluent design toggle switch on Windows.
TODO: Full customization. Shadow parts? CSS custom properties? (Issue #7)
Providing a swtich control as a variant of <input type=checkbox> would be possible.
We can add switch
content attribute, add swtich
keyword to appearance
CSS property, or something.
However, as decribed in 'Why a switch control?' section, using <input type=checkbox> for a switch control is semantically incorrect. Also, it would add complexity to UA implementations, and it's difficult to provide customization flexibility with a switch control implemented by these ways.
Form control elements are major sources of interoperability issues. Native implementations likely introduce new interoperability issues.
UAs can share a built-in module implementation because it's a JavaScript code, and web developers won't see interoperablity issues with it at all.
See JavaScript Standard Library Proposal
- whatwg/html#4180 posted by Atishay Jain gave us a motivation to start this project.