Checkbox

Native HTML checkbox styled with custom checkmark; supports indeterminate state.

Overview

The Checkbox component is a core building block of the Byteion design system, providing a robust, accessibility-compliant interface for its specific UI capabilities.

Why this exists

Checkboxes are the standard for binary (yes/no) choices, especially in forms and data-table selection. The indeterminate state is critical for parent/child selection patterns.

Mental model

A checkbox represents a binary state: checked or unchecked. A third state (indeterminate) means"some but not all children are selected."

When to use

• Terms & conditions acceptance • Feature toggles in settings • Row selection in data tables • Filter multi-select (show all that apply)

When not to use

• Do not use for mutually exclusive options — use radio • Do not use for on/off toggles in settings panels — use a switch • Avoid in modal footers for"don't show again" — it distracts from the primary action

Basic example

The following example demonstrates standard usage, fully compliant with Byteion's token-first approach.

Variants

Each variant communicates a different meaning. Choose based on priority, not aesthetics.

  • solid — solid style variant.

Sizes

Size should match the importance and context of the component.

  • sm — sm size.
  • md — md size.
  • lg — lg size.

States

This component reacts seamlessly to the following interaction and data states:

  • default — Resting appearance before interaction.
  • hover — Pointer is over the element — visual feedback via color or shadow.
  • focus-visible — focus-visible state.
  • checked — Checkbox or radio is selected.
  • indeterminate — Checkbox shows partial selection (parent/child).
  • disabled — Non-interactive — grayed out, cursor not-allowed.

Anatomy

• Checkbox input — native, visually hidden but accessible • Custom checkmark — SVG rendered in the visible box • Label — clickable area, wraps the input • Indeterminate indicator — horizontal dash

Usage guidelines

  • Labels should be clickable.
  • Use indeterminate only for parent/child hierarchies.
  • Group related checkboxes with a fieldset and legend.

Do and Don't

Do

  • Make the label clickable.
  • Use indeterminate for"select all" parent checkboxes.
  • Group related checkboxes in a fieldset.

Don't

  • Do not use checkboxes for on/off settings — use switch.
  • Do not use for mutually exclusive options.
  • Do not auto-check on page load without user action.

Accessibility

Native checkbox is fully keyboard and screen-reader accessible. Group with <fieldset> and <legend>. Indeterminate state is set via JS property .indeterminate = true.

Role:checkbox

ARIA Attributes

  • aria-checked
  • aria-disabled
  • aria-describedby
  • aria-label

Keyboard Navigation

  • Tab: Moves focus to the checkbox
  • Space: Toggles the checked state

Customization

Check color follows --primary token.

Compose with React cva()

Use the exportedcva() +cn() utilities to compose your own variant on top of the Byteion tokens.

import { cva, cn, type VariantProps } from '@byteion/react';

const myCheckbox = cva('base classes…', {
 variants: {
  accent: { soft:'border-primary-200', loud:'border-primary-500' },
 },
 defaultVariants: { accent:'soft' },
});

type Props = React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof myCheckbox>;

Compose with Vue cva()

Use the exportedcva() +cn() utilities inside standard Vue setup blocks.

<script setup lang="ts">
import { computed, useAttrs } from 'vue';
import { cva, type VariantProps } from '@byteion/vue';

interface Props { accent?:'soft' |'loud' }
const props = withDefaults(defineProps<Props>(), { accent:'soft' });
const attrs = useAttrs();

const myCheckbox = cva('base classes…', {
  variants: { accent: { soft:'border-primary-200', loud:'border-primary-500' } },
});

const cls = computed(() => myCheckbox({ accent: props.accent, class: attrs.class as string | undefined }));
</script>

Runtime events

Byteion keeps framework APIs idiomatic: HTML uses DOM custom events, React uses callback props, and Vue uses emitted events / v-model updates.

HTML / JS events

No HTML runtime events are declared by this adapter.

React callbacks

No React callback events are declared by this adapter.

Vue emits

  • update:modelValue[value: boolean]; change: [event: Event]

Remote / AJAX

This component does not implement Byteion JS remote loading. Use normal HTML form submission, framework state, or your application data layer around it.

API Reference

Native checkbox element.

HTML Data Attributes

No custom data attributes required.

React Props · CheckboxProps

Extracted directly fromreact/src/components/Checkbox.tsx.

export interface CheckboxProps
  extends Omit<InputHTMLAttributes<HTMLInputElement>, 'type' | 'size' | 'children'>,
    VariantProps<typeof checkboxBox> {
  /** Label rendered to the right of the checkbox. */
  label?: ReactNode;
  /** Optional helper / description (smaller, muted). */
  description?: ReactNode;
  size?: Size;
  /**
   * Indeterminate is a JS property, not an HTML attribute.
   * Setting this prop syncs `inputElement.indeterminate` for you.
   */
  indeterminate?: boolean;
}

React Variant Schema

Internal variant composition defined viacva().

cva(
  'peer m-0 h-full w-full cursor-pointer appearance-none border bg-card shadow-inner-sm transition-colors duration-150 focus-visible:outline-none dark:border-border dark:bg-muted',
  {
    variants: {
      tone: {
        primary: 'border-border hover:border-primary-400 focus-visible:ring-2 focus-visible:ring-primary-500/30 checked:border-primary-500 checked:bg-primary-500 dark:checked:bg-primary-500 indeterminate:border-primary-500 indeterminate:bg-primary-500 dark:indeterminate:bg-primary-500',
        success: 'border-border hover:border-success-400 focus-visible:ring-2 focus-visible:ring-success-500/30 checked:border-success-500 checked:bg-success-500 dark:checked:bg-success-500 indeterminate:border-success-500 indeterminate:bg-success-500 dark:indeterminate:bg-success-500',
        danger:  'border-border hover:border-danger-400  focus-visible:ring-2 focus-visible:ring-danger-500/30  checked:border-danger-500  checked:bg-danger-500  dark:checked:bg-danger-500  indeterminate:border-danger-500  indeterminate:bg-danger-500  dark:indeterminate:bg-danger-500',
        neutral: 'border-border hover:border-muted-foreground/40 focus-visible:ring-2 focus-visible:ring-muted-foreground/30 checked:border-muted-foreground checked:bg-muted-foreground indeterminate:border-muted-foreground indeterminate:bg-muted-foreground',
        info:    'border-border hover:border-info-400 focus-visible:ring-2 focus-visible:ring-info-500/30 checked:border-info-500 checked:bg-info-500 dark:checked:bg-info-500 indeterminate:border-info-500 indeterminate:bg-info-500 dark:indeterminate:bg-info-500',
      },
    },
    defaultVariants: { tone: 'primary' },
  },
)

Vue Props · CheckboxProps

Extracted directly fromvue/src/components/Checkbox.vue.

export interface CheckboxProps {
  modelValue?: boolean;
  tone?: 'primary' | 'success' | 'danger' | 'neutral' | 'info';
  size?: 'sm' | 'md' | 'lg';
  label?: string;
  description?: string;
  /** Indeterminate is a JS property, not an HTML attribute. */
  indeterminate?: boolean;
  disabled?: boolean;
  id?: string;
  name?: string;
  value?: string | number;
}

Developer tips

• Common mistake: using checkbox for settings toggle — switches communicate"on/off" more clearly. • Edge case: indeterminate cannot be set via HTML attribute — requires JS.

Common mistakes

Avoid hardcoded neutral colors, placeholder-only labels, duplicated primary actions, and missing keyboard states. Keep this component on Byteion tokens so dashboard, admin, POS, ERP, ecommerce back-office, Laravel, React, and Vue starter-kit screens can be rebranded without rewriting markup.

Production usage tips

Use the canonical HTML as the source of truth, keep React and Vue wrappers aligned with the documented variants, test dark mode and branded themes before release, and wire interactive behavior through data-bi-* attributes instead of styling hooks.

Premium examples

Advanced patterns available in Byteion Pro:

• Animated checkmark pop-in • Hierarchical tree with parent/child selection

Unlock Premium Patterns

Get access to copy-paste ready Pro blocks, SaaS templates, and advanced data-tables built with this component.

Explore Pro Components