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

@bento/checkbox

v0.2.3

Published

Checkbox component

Readme

import { Meta, ArgTypes, Story, Controls, Source, } from '@storybook/addon-docs/blocks';

Checkbox

The @bento/checkbox package provides accessible and customizable checkbox inputs. It exports the CheckboxGroup and Checkbox primitives, enabling you to build individual or groups of checkboxes with consistent keyboard navigation, focus management, and ARIA support. React Aria is used to ensure that the checkboxes are accessible to all users.

The CheckboxGroup allows a user to select multiple items from a list of Checkbox components.

The Checkbox is a single checkbox option that can be selected by the user.

Installation

npm install --save @bento/checkbox

Props

The following properties are available to be used on the CheckboxGroup and Checkbox primitives:

Checkbox

CheckboxGroup

Data Attributes, Slot Map and Props

Data Attributes

The following data attributes can be used to style and customize the CheckboxGroup and Checkbox primitives.

CheckboxGroup Data Attributes

| Attribute | Description | Example Values | | ---------------- | ---------------------------------------- | -------------- | | data-disabled | Indicates the checkbox group is disabled | "true" | | data-readonly | Indicates the checkbox group is readonly | "true" | | data-required | Indicates the checkbox group is required | "true" | | data-invalid | Indicates the checkbox group is invalid | "true" |

Checkbox Data Attributes

| Attribute | Description | Example Values | | -------------------- | --------------------------------------------------- | -------------- | | data-disabled | Indicates the checkbox is disabled | "true" | | data-readonly | Indicates the checkbox is readonly | "true" | | data-required | Indicates the checkbox is required | "true" | | data-invalid | Indicates the checkbox is invalid | "true" | | data-indeterminate | Indicates the checkbox is in an indeterminate state | "true" | | data-pressed | Indicates the checkbox is being pressed | "true" | | data-hovered | Indicates the checkbox is hovered | "true" | | data-focused | Indicates the checkbox has focus | "true" | | data-focus-visible | Indicates focus should be visible | "true" | | data-selected | Indicates the checkbox is selected | "true" |

CheckboxGroup Slot Map

| Slot Name | Description | | ------------- | ------------------------------ | | label | Label for checkbox group | | description | Description for checkbox group | | error | Error for checkbox group |

Checkbox Slot Map

| Slot Name | Description | | -------------------- | ------------------------------- | | icon-checked | Icon for checked checkbox | | icon-unchecked | Icon for unchecked checkbox | | icon-indeterminate | Icon for indeterminate checkbox |

Examples

Default Checkbox - Uncontrolled

The Checkbox primitive is uncontrolled by default, meaning it manages its own state internally. You can also use it in a controlled manner by providing the checked and onChange props.

/* v8 ignore next */
import React from 'react';
import { Checkbox } from '@bento/checkbox';

export function CheckboxExample(args: React.ComponentProps<typeof Checkbox>) {
  return (
    <Checkbox name="checkbox-example" value="checkbox-value" {...args}>
      Checkbox Label
    </Checkbox>
  );
}

Controlled Checkbox

The Checkbox can also be used in a controlled manner, where you manage its state externally with the checked and onChange props.

/* v8 ignore next */
import React, { useState } from 'react';
import { Checkbox } from '@bento/checkbox';

export function CheckboxControlledExample() {
  const [checked, setChecked] = useState(false);

  return (
    <Checkbox
      name="checkbox-controlled-example"
      value="checkbox-controlled-value"
      isSelected={checked}
      onChange={setChecked}
    >
      Controlled Checkbox
    </Checkbox>
  );
}

Checkbox Group

The CheckboxGroup allows a user to select multiple items from a list of Checkbox components.

/* v8 ignore next */
import React from 'react';
import { Checkbox, CheckboxGroup } from '@bento/checkbox';
import { Text } from '@bento/text';
import { FieldError } from '@bento/field-error';

export function CheckboxGroupExample(args: React.ComponentProps<typeof CheckboxGroup>) {
  return (
    <CheckboxGroup name="checkbox-group-example" {...args}>
      <Text slot="label">Checkbox Group</Text>
      <Checkbox value="checkbox-1">Checkbox 1</Checkbox>
      <Checkbox value="checkbox-2">Checkbox 2</Checkbox>
      <Text slot="description">Select your options</Text>
      <FieldError slot="error">This is an error message</FieldError>
    </CheckboxGroup>
  );
}

Controlled Checkbox Group

The CheckboxGroup can also be used in a controlled manner, where you manage the state of the checkboxes externally with the value and onChange props.

/* v8 ignore next */
import React, { useState } from 'react';
import { Checkbox, CheckboxGroup } from '@bento/checkbox';
import { Text } from '@bento/text';

export function CheckboxGroupControlledExample() {
  const [selectedValues, setSelectedValues] = useState<string[]>([]);

  return (
    <CheckboxGroup value={selectedValues} onChange={setSelectedValues}>
      <Text slot="label">Checkbox Group</Text>
      <Checkbox value="option1">Option 1</Checkbox>
      <Checkbox value="option2">Option 2</Checkbox>
      <Checkbox value="option3">Option 3</Checkbox>
    </CheckboxGroup>
  );
}

Checkbox Group with Indeterminate State

The CheckboxGroup can also support an indeterminate state, which is useful when some but not all checkboxes are selected. The complex state management shown here is an example of how to handle indeterminate states in a checkbox group in a common way.

/* v8 ignore next */
import React, { useState } from 'react';
import { Checkbox, CheckboxGroup } from '@bento/checkbox';
import { Text } from '@bento/text';

const SELECT_ALL = 'select-all';

export function CheckboxGroupIndeterminateExample() {
  const items = [
    { id: 'option1', label: 'Option 1' },
    { id: 'option2', label: 'Option 2' },
    { id: 'option3', label: 'Option 3' }
  ];
  const allItemIds = items.map(function getItemId(item) {
    return item.id;
  });

  const [checkedItems, setCheckedItems] = useState<string[]>([]);

  const itemsSelectedCount = checkedItems.filter(function isItem(value) {
    return value !== SELECT_ALL;
  }).length;
  const isIndeterminate = itemsSelectedCount > 0 && itemsSelectedCount < allItemIds.length;

  function handleGroupChange(nextValues: string[]) {
    const prevHadSelectAll = checkedItems.includes(SELECT_ALL);
    const nextHasSelectAll = nextValues.includes(SELECT_ALL);

    // Select All was just toggled on → select every item, with select-all last.
    if (!prevHadSelectAll && nextHasSelectAll) {
      setCheckedItems([...allItemIds, SELECT_ALL]);
      return;
    }

    // Select All was just toggled off → clear everything.
    if (prevHadSelectAll && !nextHasSelectAll) {
      setCheckedItems([]);
      return;
    }

    // An individual item toggled. Strip select-all so its membership is purely derived.
    const itemsOnly = nextValues.filter(function notSelectAll(value) {
      return value !== SELECT_ALL;
    });
    const allItemsNowSelected = allItemIds.every(function isInItems(id) {
      return itemsOnly.includes(id);
    });
    if (allItemsNowSelected) {
      setCheckedItems([...itemsOnly, SELECT_ALL]);
    } else {
      setCheckedItems(itemsOnly);
    }
  }

  return (
    <CheckboxGroup value={checkedItems} onChange={handleGroupChange} data-value={checkedItems}>
      <Text slot="label">Select Items</Text>
      <Checkbox name={SELECT_ALL} value={SELECT_ALL} isIndeterminate={isIndeterminate}>
        Select All
      </Checkbox>

      {items.map(function renderItem(item) {
        return (
          <Checkbox key={item.id} name={item.id} value={item.id}>
            {item.label}
          </Checkbox>
        );
      })}
    </CheckboxGroup>
  );
}