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
When not to use
Basic example
The following example demonstrates standard usage, fully compliant with Byteion's token-first approach.
Sizes
States
Color variants
Stacked with description
import { Checkbox } from '@byteion/react';
export default function CheckboxDemo() {
return (
<div className="space-y-2 p-6">
<Checkbox label="I agree to the terms and conditions" />
<Checkbox label="Send me product updates" defaultChecked />
<Checkbox label="Indeterminate (select all)" indeterminate />
<Checkbox label="Disabled" disabled />
<Checkbox label="Disabled checked" disabled defaultChecked />
</div>
);
}
<script setup lang="ts">
import { Checkbox } from '@byteion/vue';
</script>
<template>
<div class="space-y-2 p-6">
<Checkbox label="I agree to the terms and conditions" />
<Checkbox label="Send me product updates" model-value />
<Checkbox label="Indeterminate (select all)" indeterminate />
<Checkbox label="Disabled" disabled />
<Checkbox label="Disabled checked" disabled model-value />
</div>
</template>
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
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-checkedaria-disabledaria-describedbyaria-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 mistakes
Production usage tips
data-bi-* attributes instead of styling hooks.
Premium examples
Advanced patterns available in Byteion Pro:
Related components
Unlock Premium Patterns
Get access to copy-paste ready Pro blocks, SaaS templates, and advanced data-tables built with this component.
Explore Pro Components