Skip to content
Components

Checkbox

Toggles an independent choice between checked and unchecked states.

Playground

scheme

Applies a semantic color when checked.

defaultChecked

Sets the initial uncontrolled state.

disabled

Prevents the choice from being changed.

Usage

tsx
import { Checkbox } from "earthling-ui/checkbox";
import { Label } from "earthling-ui/label";

export function Example() {
  return (
    <>
      <Checkbox id="updates" defaultChecked />
      <Label htmlFor="updates">Email me product updates</Label>
    </>
  );
}
  • Use a label that describes the checked state in affirmative language.
  • The mixed state is available through checked=indeterminate.
  • Group related checkboxes with a fieldset and legend when context is shared.

Installation

Start with the project setup for React and Tailwind CSS 4. Both paths use the same component and theme.

bash
npm install earthling-ui

Use the component import shown above. Package updates keep the implementation current.

API reference

Declarations from the current library build, including inherited primitive props. Playground controls above show selected options; they are not the complete API.

tsx
// Generated by dts-bundle-generator v9.5.1

import * as CheckboxPrimitive from '@radix-ui/react-checkbox';
import { VariantProps } from 'class-variance-authority';
import { ComponentPropsWithoutRef } from 'react';

export declare const checkboxVariants: (props?: ({
	scheme?: "default" | "primary" | "secondary" | "tertiary" | "neutral" | "muted" | "good" | "caution" | "bad" | null | undefined;
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
export interface CheckboxProps extends ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>, VariantProps<typeof checkboxVariants> {
}
export declare const Checkbox: import("react").ForwardRefExoticComponent<CheckboxProps & import("react").RefAttributes<HTMLButtonElement>>;

export {};

Runtime dependencies: @radix-ui/react-checkbox, class-variance-authority, cnfast.

Source

Use the eject command to copy this implementation with its required helpers and project-specific imports.

View Checkbox implementation
tsx
"use client";

import {
  type ComponentPropsWithoutRef,
  type ComponentRef,
  forwardRef,
} from "react";
import * as CheckboxPrimitive from "@radix-ui/react-checkbox";

import { cn } from "@/utils/cn";
import { schemes } from "@/utils/variants";
import { cva, type VariantProps } from "class-variance-authority";

const checkboxVariants = cva(
  "peer size-5 shrink-0 rounded-md border border-current/30 ring-offset-background transition-transform duration-150 ease-out motion-reduce:transition-none active:scale-[0.96] motion-reduce:active:scale-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-outline focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-bad aria-invalid:ring-bad/30 data-[state=checked]:border-transparent data-[state=checked]:bg-(--scheme-tint) data-[state=checked]:text-(--scheme-foreground)",
  {
    variants: {
      scheme: schemes,
    },
    defaultVariants: { scheme: "default" },
  },
);

export interface CheckboxProps
  extends
    ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>,
    VariantProps<typeof checkboxVariants> {}

const Checkbox = forwardRef<
  ComponentRef<typeof CheckboxPrimitive.Root>,
  CheckboxProps
>(({ className, scheme, ...props }, ref) => (
  <CheckboxPrimitive.Root
    ref={ref}
    className={cn(checkboxVariants({ scheme }), className)}
    {...props}
  >
    <CheckboxPrimitive.Indicator className="flex items-center justify-center text-current animate-in zoom-in-50 fade-in-0 duration-150 motion-reduce:animate-none">
      <i className="icon-[lucide--check] h-4 w-4" />
    </CheckboxPrimitive.Indicator>
  </CheckboxPrimitive.Root>
));
Checkbox.displayName = CheckboxPrimitive.Root.displayName;

export { Checkbox, checkboxVariants };