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

@19h47/checkbox

v6.2.1

Published

Custom checkbox element with accessibility in mind

Readme

Ask DeepWiki

@19h47/checkbox

Custom checkbox behaviour for UIs where a native <input type="checkbox"> is awkward to style or compose (selectable cards, dense layouts, mixed-state parents). Not a replacement for native checkboxes in ordinary forms — prefer those whenever you can.

Install

pnpm add @19h47/checkbox

HTML

HTML is the source of truth. Set role, tabindex, aria-checked, aria-disabled, and labelling attributes in the markup; the library reads them and mirrors state onto classes and an optional native input.

<div role="checkbox" aria-checked="false" tabindex="0">
	<span aria-hidden="true"></span>
	Do you want to click me?
	<div style="display: none;">
		<input id="option" name="option" value="option" type="checkbox" />
	</div>
</div>

JavaScript

import Checkbox from '@19h47/checkbox';

const $checkbox = document.querySelector('[role="checkbox"]');
const checkbox = new Checkbox($checkbox);

checkbox.init();

Keyboard Support

| Key | Function | | ----- | ------------------------------------------------------ | | Tab | Moves keyboard focus to the checkbox. | | Space | Toggles checkbox between checked and unchecked states. |

Role, Property, State, and Tabindex Attributes

| Role | Attribute | Element | Usage | | ---------- | ---------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------ | | | | h3 | Provides a grouping label for the group of checkboxes. | | group | | div | Identifies the div element as a group container for the checkboxes. | | | aria-labelledby | div | References the id of the element that labels the group. | | checkbox | | div | Identifies the element as a checkbox. Child text (or aria-label / aria-labelledby) provides the accessible name. | | | tabindex="0" | div | Includes the checkbox in the page tab sequence. | | | aria-checked="false" | div | Indicates the checkbox is not checked. | | | aria-checked="true" | div | Indicates the checkbox is checked. | | | aria-checked="mixed" | div | Indicates the checkbox is partially checked. | | | aria-disabled="true" | div | Indicates the checkbox is disabled. Prefer tabindex="-1" when disabled so it leaves the tab sequence. |

Methods

| Method | Description | Arguments | | -------------- | ----------------------------------------- | ----------------------------------------------------------------------------------- | | init() | Bind events and sync from HTML | — | | destroy() | Remove event listeners | — | | sync() | Re-apply HTML → classes & native input | — | | activate() | Set aria-checked="true" on the element | trigger (optional) Whether events should fire. Default true | | deactivate() | Set aria-checked="false" on the element | trigger (optional) Whether events should fire. Default true | | mix() | Set aria-checked="mixed" on the element | trigger (optional) Whether events should fire. Default true |

import Checkbox from '@19h47/checkbox';

const $checkbox = document.querySelector('[role="checkbox"]');
const checkbox = new Checkbox($checkbox);

checkbox.init();

checkbox.activate();
checkbox.deactivate();
checkbox.destroy();

Getters

Read state from the HTML attributes on el:

| Getter | Type | Source | | -------------- | --------------------------------- | ------------------------------- | | ariaChecked | 'true' \| 'false' \| 'mixed' | aria-checked on el | | checked | boolean | true when ariaChecked is 'true' | | disabled | boolean | aria-disabled="true" on el | | $input | HTMLInputElement \| null | first input inside el |

checkbox.init();

checkbox.ariaChecked; // "true" | "false" | "mixed"
checkbox.checked;     // boolean
checkbox.disabled;    // boolean

Sync classes

sync() (called by init() and every state change) mirrors HTML onto optional CSS hooks and the native input:

| Class | When | | -------------- | ----------------------------------------- | | is-selected | aria-checked="true" | | is-mixed | aria-checked="mixed" | | is-disabled | aria-disabled="true" | | is-focus | while the checkbox has focus (interaction) |

The library does not ship styles for these classes — use them in your own CSS.

Events

Events are dispatched on the hidden input when present, otherwise on the checkbox element. When trigger is true, each state change also fires native-like input and change.

Activate

import Checkbox from '@19h47/checkbox';

const $checkbox = document.querySelector('[role="checkbox"]');
const checkbox = new Checkbox($checkbox);

checkbox.init();

checkbox.$input.addEventListener('activate', event => {
	const {
		target: { value },
	} = event;

	console.log(value);
});

Deactivate

import Checkbox from '@19h47/checkbox';

const $checkbox = document.querySelector('[role="checkbox"]');
const checkbox = new Checkbox($checkbox);

checkbox.init();

checkbox.$input.addEventListener('deactivate', event => {
	const {
		target: { value },
	} = event;

	console.log(value);
});

Mix

checkbox.$input.addEventListener('mix', event => {
	const {
		target: { value },
	} = event;

	console.log(value);
});

CheckboxGroup

The CheckboxGroup is a wrapper class around Checkbox.

When a user clicks a checkbox, holds Shift, and then clicks another checkbox a few rows down, all the checkboxes in between those two checkboxes should be checked (disabled items are skipped).

<div role="group" aria-labelledby="group-label">
	<h3 id="group-label">Options</h3>

	<div tabindex="0" role="checkbox" aria-checked="false">
		<span aria-hidden="true"></span>
		Curst
		<div style="display: none;">
			<input id="curst" name="curst" value="Curst" type="checkbox" />
		</div>
	</div>

	<div tabindex="0" role="checkbox" aria-checked="false">
		<span aria-hidden="true"></span>
		Doppelganger, Greater
		<div style="display: none;">
			<input
				id="doppelganger-greater"
				name="city-of-splendors[]"
				value="Doppelganger, greater"
				type="checkbox"
			/>
		</div>
	</div>
</div>
import { CheckboxGroup } from '@19h47/checkbox';

const $element = document.querySelector('[role="group"]');
const checkboxgroup = new CheckboxGroup($element);

checkboxgroup.init();

Example

An interactive demo covering every API surface is at 19h47.github.io/19h47-checkbox (sources):

  • When to use: selectable cards (whole tile as checkbox)
  • HTML states (aria-checked, aria-disabled, aria-label, aria-labelledby, aria-describedby)
  • Methods (activate, deactivate, mix, sync, destroy) and getters
  • Events (activate, deactivate, mix, input, change)
  • Keyboard support (Tab, Space)
  • Groups, conditional logic, CheckboxGroup, tri-state select all, shift selection

Run tests with pnpm test.

References