COMPONENTS/INPUTS

Switch.

An immediate change, clearly expressed.

In practice

Compose SwitchThumb inside Switch. Label the control. Use checked/onCheckedChange for controlled state.

Installation

Install Coal once. Components and TypeScript declarations are included. React 19 and React DOM 19 are peer dependencies.

Terminal · local package
npm install http://localhost:3100/downloads/chlohal-coal-ui-0.5.0.tgz

This installs the local package. It is not yet published on npm. See installation for stylesheet setup and integration.

Usage

example.tsx
"use client";
import * as React from "react";
import "@chlohal/coal-ui/styles.css";
import { Switch, SwitchThumb } from "@chlohal/coal-ui";
export default function Example() {
    return (<div>
          <label>
            Quiet mode
            <Switch defaultChecked>
              <SwitchThumb />
            </Switch>
          </label>
          <label>
            Email updates
            <Switch>
              <SwitchThumb />
            </Switch>
          </label>
        </div>);
}

Source

The original Coal implementation. Use the package export to integrate it.

packages/react/src/switch.tsx
"use client";
import * as React from "react";
import { cn } from "./internal.js";
export type SwitchProps = Omit<
  React.ComponentPropsWithRef<"input">,
  "type" | "size"
> & { onCheckedChange?: (checked: boolean) => void };
export function Switch({
  checked,
  defaultChecked = false,
  onCheckedChange,
  onChange,
  children,
  className,
  ...props
}: SwitchProps) {
  return (
    <span
      className={cn("coal-switch", className)}
      data-disabled={props.disabled || undefined}
    >
      <input
        {...props}
        type="checkbox"
        role="switch"
        checked={checked}
        defaultChecked={checked === undefined ? defaultChecked : undefined}
        onChange={(e) => {
          onChange?.(e);
          if (!e.defaultPrevented) onCheckedChange?.(e.target.checked);
        }}
      />
      {children ?? <SwitchThumb />}
    </span>
  );
}
export function SwitchThumb({
  className,
  ...props
}: React.ComponentPropsWithRef<"span">) {
  return (
    <span
      aria-hidden="true"
      className={cn("coal-switch-thumb", className)}
      {...props}
    />
  );
}

Accessibility checklist

  • Provide an accessible name for controls, including icon-only buttons.
  • Check keyboard navigation, visible focus and disabled states in your application.
  • Do not rely on color alone to communicate status.