npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@data-slot/switch

v0.2.166

Published

Headless switch component for vanilla JavaScript. Accessible, form-ready, and unstyled.

Readme

@data-slot/switch

Headless switch component for vanilla JavaScript. Accessible, form-ready, and unstyled.

Installation

npm install @data-slot/switch

Quick Start

<label>
  <span data-slot="switch" data-name="notifications">
    <span data-slot="switch-thumb"></span>
  </span>
  Notifications
</label>

<script type="module">
  import { create } from "@data-slot/switch";

  const controllers = create();
</script>

API

create(scope?)

Auto-discover and bind all switch instances in a scope (defaults to document).

import { create } from "@data-slot/switch";

const controllers = create(); // Returns SwitchController[]

createSwitch(root, options?)

Create a controller for a specific element.

import { createSwitch } from "@data-slot/switch";

const controller = createSwitch(element, {
  defaultChecked: true,
  name: "notifications",
  uncheckedValue: "off",
  onCheckedChange: (checked) => console.log(checked),
});

Options

| Option | Type | Default | Description | |--------|------|---------|-------------| | defaultChecked | boolean | false | Initial checked state | | disabled | boolean | false | Disable user interaction and form submission | | readOnly | boolean | false | Prevent user interaction while keeping the field enabled | | required | boolean | false | Require the switch to be checked for native form validation | | name | string | - | Form field name | | value | string | native checkbox "on" | Submitted value when checked | | uncheckedValue | string | - | Submitted value when unchecked | | onCheckedChange | (checked: boolean) => void | undefined | Callback when checked state changes |

Data Attributes

JS options take precedence over data attributes on the root element.

| Attribute | Type | Default | Description | |-----------|------|---------|-------------| | data-default-checked | boolean | false | Initial checked state | | data-disabled | boolean | false | Disable user interaction and form submission | | data-read-only / data-readOnly | boolean | false | Prevent user interaction while keeping the field enabled | | data-required | boolean | false | Require a checked value | | data-name | string | - | Form field name | | data-value | string | native checkbox "on" | Submitted value when checked | | data-unchecked-value / data-uncheckedValue | string | - | Submitted value when unchecked |

Controller

| Method/Property | Description | |-----------------|-------------| | checked | Current checked state (readonly boolean) | | toggle() | Toggle the checked state | | check() | Set checked to true | | uncheck() | Set checked to false | | setChecked(checked) | Set the checked state explicitly | | destroy() | Remove listeners and generated inputs |

Markup Structure

The authored API is just a root and an optional thumb:

<span data-slot="switch">
  <span data-slot="switch-thumb"></span>
</span>

Use a neutral root element (span or div) when you want Base UI-style label wrapping and shadcn-like composition. The controller injects a visually hidden checkbox next to the root for form submission, label support, and native validation.

Styling

State Attributes

The root and thumb expose presence attributes:

  • data-checked
  • data-unchecked
  • data-disabled
  • data-readonly
  • data-required

The root also syncs:

  • role="switch"
  • aria-checked="true|false"
  • aria-disabled="true" when disabled
  • aria-readonly="true" when read-only
  • aria-required="true" when required

Tailwind Example

<label class="inline-flex items-center gap-3">
  <span
    data-slot="switch"
    data-size="default"
    class="data-checked:bg-primary data-unchecked:bg-input
           focus-visible:border-ring focus-visible:ring-ring/50
           shrink-0 rounded-full border border-transparent
           focus-visible:ring-3 peer group/switch relative
           inline-flex items-center transition-all outline-none
           h-[18.4px] w-[32px]"
  >
    <span
      data-slot="switch-thumb"
      class="bg-background rounded-full size-4
             data-checked:translate-x-[calc(100%-2px)]
             data-unchecked:translate-x-0
             pointer-events-none block transition-transform"
    ></span>
  </span>
  Notifications
</label>

Events

Outbound

element.addEventListener("switch:change", (event) => {
  console.log(event.detail.checked);
});

Inbound

element.dispatchEvent(
  new CustomEvent("switch:set", { detail: { checked: true } })
);

License

MIT