Switch Button

Recipe 4.4 Add states and properties

Sample:

Code:

<button role="switch" aria-checked="false">Functional cookies</button>

<script>
  const button = document.querySelector('button')

  button.addEventListener('click', e => {
    const isChecked = button.getAttribute('aria-checked') === "true"
    button.setAttribute('aria-checked', !isChecked)

  })
</script>

<style>
   button {
    --toggle-offset: 2px;
    --toggle-height: 1.6em;
    --toggle-background: oklab(0.82 0 0);

    all: unset;
    align-items: center;
    display: flex;
    gap: 0.5em;
    position: relative;
  }

   button:focus-visible::before {
    outline: 2px solid;
    outline-offset: 2px;
  }

   button:is(:focus-visible, :hover)::before {
    box-shadow: 0px 0px 3px 1px rgb(0 0 0 / 0.3);
  }

   button::before {
    background: var(--toggle-background);
    border-radius: 4em;
    content: "";
    display: inline-block;
    height: var(--toggle-height);
    transition: background 0.3s, box-shadow 0.3s;
    width: 3em;
  }

   button::after {
    --_size: calc(var(--toggle-height) - (var(--toggle-offset) * 2));

    background: #FFF;
    border-radius: 50%;
    content: "";
    height: var(--_size);
    left: var(--toggle-offset);
    position: absolute;
    transition: translate 0.3s;
    top: var(--toggle-offset);
    width: var(--_size);
  }

   [aria-checked="true"] {
    --toggle-background: oklab(0.7 -0.18 0.17);
  }

   button[aria-checked="true"]::after {
    translate: 100% 0;
  }
</style>