

index.html
<!-- aria-checked is the
only state: CSS reads
it, JS writes it -->
<button class="dew"
type="button"
aria-labelledby="l-wifi"
aria-checked="true">
<!-- role="switch" is added
by the script -->
<span class="dew-knob">
</span></button>dew.css
/* typed, so it can
transition: one number
moves knob and colour */
@property --dew-p {
syntax: "<number>"; …
.dew { …
transition: --dew-p
420ms var(--dew-spring);
…
.dew[aria-checked="true"]
{ --dew-p: 1; }dew.js
// drag writes the number
// in; CSS springs the rest
const p = Math.max(0,
Math.min(1, drag.p0 +
dx / travel()));
root.style.setProperty(
'--dew-p', p.toFixed(3));
// released past halfway
// wins; a tap just flips
set(moved ? p > 0.5
: !isOn());




