0.0.3

Switch

A pure vanilla JS implementation of Zag JS Switch Opens in a new window


Anatomy

The Switch component consists of the following data-part

root label hidden-input control thumb
<div class="switch switch-js">
                  <label data-part="root">
                  <span data-part="label">Label</span>
                  <input data-part="hidden-input">
                  <span data-part="control">
                  <span data-part="thumb"></span>
                  </span>
                  </label>
                  </div>

Data attributes

Each switch can be set with different settings with the following data-attribute.

<div class="switch switch-js" data-default-checked="true">
                      <label data-part="root">
                      <span data-part="label">Checked</span>
                      <input data-part="hidden-input">
                      <span data-part="control">
                      <span data-part="thumb"></span>
                      </span>
                      </label>
                      </div>
                      <div class="switch switch-js" data-disabled="true">
                      <label data-part="root">
                      <span data-part="label">Disabled</span>
                      <input data-part="hidden-input">
                      <span data-part="control">
                      <span data-part="thumb"></span>
                      </span>
                      </label>
                      </div>
                      <div class="switch switch-js" data-invalid="true">
                      <label data-part="root">
                      <span data-part="label">Invalid</span>
                      <input data-part="hidden-input">
                      <span data-part="control">
                      <span data-part="thumb"></span>
                      </span>
                      </label>
                      </div>
                      <div class="switch switch-js" data-default-checked="true" data-invalid="true">
                      <label data-part="root">
                      <span data-part="label">Invalid Checked</span>
                      <input data-part="hidden-input">
                      <span data-part="control">
                      <span data-part="thumb"></span>
                      </span>
                      </label>
                      </div>
Data attribute Type / Options Description
id string The unique id of the component. Default generated if none is provided
data-default-checked boolean || "indeterminate The initial checked state of the switch
data-checked boolean || "indeterminate The controlled checked state of the switch
data-dir ltr | rtl The orientation of the switch. Can be `ltr` or `rtl`
data-disabled string Whether the switch is disabled
data-invalid boolean Whether the switch is invalid
data-required boolean Whether the switch is required
data-read-only boolean Whether the switch is read only
data-form string The id of the form that the switch belongs to.
data-name string The name of the input field in a switch. Useful for form submission.
data-value string The value of switch input. Useful for form submission. Default to "on"

Callbacks

Each switch component can receive callbacks that can be used to respond to user interaction with custom behavior.

You must add a custom id and an event listener for your event name


                  document.getElementById("my-callback-switch")
                  ?.addEventListener("my-callback-switch-event", (event) => {
                    console.log("Received event:", (event as CustomEvent).detail);
                  });
              
<div id="my-callback-switch" class="switch switch-js" data-on-checked-change="my-callback-switch-event">
                  <label data-part="root">
                  <span data-part="label">Label</span>
                  <input data-part="hidden-input">
                  <span data-part="control">
                  <span data-part="thumb"></span>
                  </span>
                  </label>
                  </div>

Open your browser's console to see the events received when you check or uncheck the above switch

Data attribute Type / Options Description
data-on-open-change string Function to call when the switch's open state changes

Checked State Control

Switch checked state can be control with data attributes on any element

You must set a custom id for your switch, as the default is randomly generated

data-check-switch="switch-id" data-uncheck-switch="switch-id"
<div>
                  <button data-check-switch="my-switch" class="button button--sm">
                  Check Switch
                  </button>
                  <button data-uncheck-switch="my-switch" class="button button--sm">
                  Uncheck Switch
                  </button>
                  </div>
                  <div id="my-switch" class="switch switch-js">
                  <label data-part="root">
                  <span data-part="label">Label</span>
                  <input data-part="hidden-input">
                  <span data-part="control">
                  <span data-part="thumb"></span>
                  </span>
                  </label>
                  </div>

You also dispatch an event named switch:set-checked to the switch id with a boolean value


                  const el = document.getElementById("my-switch");
                  if (el) {
                    el.dispatchEvent(
                      new CustomEvent("switch:set-checked", {
                        detail: { value: true },
                      })
                    );
                  } else {
                    console.warn("Element with ID 'my-switch' not found");
                  }
              

Use with Form

Switch can be used inside a form

You must set the id of the form and the name of the switch

data-form="form-id" data-name="switch-name"

You can also add the value of the switch. Default to : "on"

data-value="yes"
<form id="my-form">
                  <div class="switch switch-js" data-form="my-form" data-name="newsletter" data-value="yes">
                  <label data-part="root">
                  <span data-part="label">Receive Newsletter ?</span>
                  <input data-part="hidden-input">
                  <span data-part="control">
                  <span data-part="thumb"></span>
                  </span>
                  </label>
                  </div>
                  <button class="button button--accent" type="submit">Submit</button>
                  </form>
                  <div id="result"></div>

You can use the results from the form as you wish


                const form = document.getElementById('my-form') as HTMLFormElement | null;
                const result = document.getElementById('result') as HTMLDivElement | null;
                
                if (form && result) {
                  form.addEventListener('submit', (e: Event) => {
                    e.preventDefault();
                    const formData = new FormData(form);
                    const newsletter = (formData.get('newsletter') as string) || 'no';
                    result.textContent = `Submitted: newsletter: ${newsletter}`;
                  });
                }
              

Modifier

Each switch can be styled with modifiers.

You can mix as many modifiers on the same switch, however you can choose only one choice per modifer

For convenience the default variant name is omited, meaning there is no need to add the default name class

You may have noticed the double dash before the modifier name — this follows the BEM (Block Element Modifier) Opens in a new window naming convention
Modifier Option Description
Color base (default), brand, alert Use any semantic colors
Size md (default), sm, lg, xl Modify the size of the switch.
Shape square (default), circle Modify the shape of the switch.

Color

Set the color of each button

Options: base(default), brand, alert

<div>
                  <div class="switch switch-js">
                  <label data-part="root">
                  <span data-part="label">Label</span>
                  <input data-part="hidden-input">
                  <span data-part="control">
                  <span data-part="thumb"></span>
                  </span>
                  </label>
                  </div>
                  <div class="switch switch-js switch--brand">
                  <label data-part="root">
                  <span data-part="label">Label</span>
                  <input data-part="hidden-input">
                  <span data-part="control">
                  <span data-part="thumb"></span>
                  </span>
                  </label>
                  </div>
                  <div class="switch switch-js switch--alert">
                  <label data-part="root">
                  <span data-part="label">Label</span>
                  <input data-part="hidden-input">
                  <span data-part="control">
                  <span data-part="thumb"></span>
                  </span>
                  </label>
                  </div>
                  </div>

Size

Set the size of each button

Options: md(default), sm, lg, xl

<div>
                  <div class="switch switch-js switch--sm">
                  <label data-part="root">
                  <span data-part="label">Label</span>
                  <input data-part="hidden-input">
                  <span data-part="control">
                  <span data-part="thumb"></span>
                  </span>
                  </label>
                  </div>
                  <div class="switch switch-js">
                  <label data-part="root">
                  <span data-part="label">Label</span>
                  <input data-part="hidden-input">
                  <span data-part="control">
                  <span data-part="thumb"></span>
                  </span>
                  </label>
                  </div>
                  <div class="switch switch-js switch--lg">
                  <label data-part="root">
                  <span data-part="label">Label</span>
                  <input data-part="hidden-input">
                  <span data-part="control">
                  <span data-part="thumb"></span>
                  </span>
                  </label>
                  </div>
                  <div class="switch switch-js switch--xl">
                  <label data-part="root">
                  <span data-part="label">Label</span>
                  <input data-part="hidden-input">
                  <span data-part="control">
                  <span data-part="thumb"></span>
                  </span>
                  </label>
                  </div>
                  </div>

Shape

Set the shape of each button

Options: inherit(default), circle

<div>
                  <div class="switch switch-js">
                  <label data-part="root">
                  <span data-part="label">Label</span>
                  <input data-part="hidden-input">
                  <span data-part="control">
                  <span data-part="thumb"></span>
                  </span>
                  </label>
                  </div>
                  <div class="switch switch-js switch--circle">
                  <label data-part="root">
                  <span data-part="label">Label</span>
                  <input data-part="hidden-input">
                  <span data-part="control">
                  <span data-part="thumb"></span>
                  </span>
                  </label>
                  </div>
                  </div>

Mix

Mix as many modifiers for each button

<div>
                  <div class="switch switch-js switch--sm">
                  <label data-part="root">
                  <span data-part="label">Label</span>
                  <input data-part="hidden-input">
                  <span data-part="control">
                  <span data-part="thumb"></span>
                  </span>
                  </label>
                  </div>
                  <div class="switch switch-js switch--sm switch--brand">
                  <label data-part="root">
                  <span data-part="label">Label</span>
                  <input data-part="hidden-input">
                  <span data-part="control">
                  <span data-part="thumb"></span>
                  </span>
                  </label>
                  </div>
                  <div class="switch switch-js switch--sm switch--alert">
                  <label data-part="root">
                  <span data-part="label">Label</span>
                  <input data-part="hidden-input">
                  <span data-part="control">
                  <span data-part="thumb"></span>
                  </span>
                  </label>
                  </div>
                  </div>
                  <div>
                  <div class="switch switch-js switch--circle switch--sm">
                  <label data-part="root">
                  <span data-part="label">Label</span>
                  <input data-part="hidden-input">
                  <span data-part="control">
                  <span data-part="thumb"></span>
                  </span>
                  </label>
                  </div>
                  <div class="switch switch-js switch--circle switch--sm switch--brand">
                  <label data-part="root">
                  <span data-part="label">Label</span>
                  <input data-part="hidden-input">
                  <span data-part="control">
                  <span data-part="thumb"></span>
                  </span>
                  </label>
                  </div>
                  <div class="switch switch-js switch--circle switch--sm switch--alert">
                  <label data-part="root">
                  <span data-part="label">Label</span>
                  <input data-part="hidden-input">
                  <span data-part="control">
                  <span data-part="thumb"></span>
                  </span>
                  </label>
                  </div>
                  </div>
                  <div>
                  <div class="switch switch-js switch--lg">
                  <label data-part="root">
                  <span data-part="label">Label</span>
                  <input data-part="hidden-input">
                  <span data-part="control">
                  <span data-part="thumb"></span>
                  </span>
                  </label>
                  </div>
                  <div class="switch switch-js switch--lg switch--brand">
                  <label data-part="root">
                  <span data-part="label">Label</span>
                  <input data-part="hidden-input">
                  <span data-part="control">
                  <span data-part="thumb"></span>
                  </span>
                  </label>
                  </div>
                  <div class="switch switch-js switch--lg switch--alert">
                  <label data-part="root">
                  <span data-part="label">Label</span>
                  <input data-part="hidden-input">
                  <span data-part="control">
                  <span data-part="thumb"></span>
                  </span>
                  </label>
                  </div>
                  </div>
                  <div>
                  <div class="switch switch-js switch--circle switch--lg">
                  <label data-part="root">
                  <span data-part="label">Label</span>
                  <input data-part="hidden-input">
                  <span data-part="control">
                  <span data-part="thumb"></span>
                  </span>
                  </label>
                  </div>
                  <div class="switch switch-js switch--circle switch--lg switch--brand">
                  <label data-part="root">
                  <span data-part="label">Label</span>
                  <input data-part="hidden-input">
                  <span data-part="control">
                  <span data-part="thumb"></span>
                  </span>
                  </label>
                  </div>
                  <div class="switch switch-js switch--circle switch--lg switch--alert">
                  <label data-part="root">
                  <span data-part="label">Label</span>
                  <input data-part="hidden-input">
                  <span data-part="control">
                  <span data-part="thumb"></span>
                  </span>
                  </label>
                  </div>
                  </div>

Custom (Tailwind)

If you are using Tailwind styling, you can customize each switch with Tailwind utilities

<div class="switch switch-js">
                  <label data-part="root">
                  <span data-part="label" class="text-contrast-brand-2">Label</span>
                  <input data-part="hidden-input">
                  <span data-part="control" class="rounded-lg text-accent-contrast-alert bg-ui-brand  data-[state=checked]:bg-accent-brand border-contrast-alert border-2 ">
                  <span data-part="thumb" class="bg-ui-contrast-alert data-[state=checked]:bg-accent-contrast-alert"></span>
                  </span>
                  </label>
                  </div>

Templates

Switch components is available in the followng templates

Scrollbar Switcher