Bevel
Browse the docs

Toggle lever

An everyday on/off switch, as a bat-handle toggle on a small plate. The lever swings through its bushing toward the side that's on and settles with a little spring; a lamp at the end of the plate lights. For settings rows. (For banks of config bits use DIP switches; for dangerous actions, the guarded switch.)

Notification settings

A lever per row, and a master lever that pauses them all.

Sent to you@acme.com.

The moment an agent run fails.

When an agent stops to ask you.

Runs, spend and failures, every Monday.

New models and features, about monthly.

Installation

Add with the CLI

  1. Once per project, add the Bevel registry to components.json.

    components.json
    {
      "registries": {
        "@bevel": "https://bevel-ui.vercel.app/r/{name}.json"
      }
    }
  2. Add Toggle lever. This brings in the Bevel foundation, installs @base-ui/react and cn, and merges the styles into your global CSS.

    Terminal
    npx shadcn@latest add @bevel/toggle-lever
Install manually
  1. Install the dependencies.

    Terminal
    pnpm add @base-ui/react cn
  2. Add the Bevel foundation, if you haven't already. Light, depth, materials, motion and shape tokens, plus the utilities components use to apply them.

    styles/bevel.css
    /*
     * Bevel foundation. Every component builds on these tokens and utilities;
     * component stylesheets only add their own palettes and shapes.
     *
     * Layers:
     *   1. Light     one source, above and slightly in front of the screen.
     *   2. Depth     named elevations built from the light: recessed, flush,
     *                raised, pressed, object.
     *   3. Material  a surface recipe (leather, plastic, metal) that reads
     *                --bevel-material and --bevel-material-edge.
     *   4. Motion    two curves, a spring, and durations named by purpose.
     *   5. Shape     radii, stitching, and the type scale for amounts.
     */
    
    :root {
      /* 1. Light */
      --bevel-highlight: oklch(1 0 0 / 0.22);
      --bevel-highlight-strong: oklch(1 0 0 / 0.35);
      --bevel-shade: oklch(0 0 0 / 0.32);
      --bevel-shade-strong: oklch(0 0 0 / 0.5);
      --bevel-cast: oklch(0.25 0.03 50 / 0.22);
      /* Stamped into a surface: shaded on the upper inner edge, lit below. */
      --bevel-deboss: 0 -1px 0 oklch(0 0 0 / 0.45), 0 1px 0 oklch(1 0 0 / 0.12);
    
      /* 3. Material defaults; components and variants override these. */
      --bevel-material: oklch(0.47 0.085 52);
      --bevel-material-edge: oklch(0.3 0.06 44);
      --bevel-material-recess: oklch(0.2 0.008 260); /* neutral dark; materials set their own */
      --bevel-grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.7' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .7 0 0 0 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23g)'/%3E%3C/svg%3E");
      --bevel-grain-size: 180px;
    
      /* 2. Depth */
      --bevel-depth-recessed:
        inset 0 1px 2px var(--bevel-shade-strong),
        0 1px 0 var(--bevel-highlight);
      --bevel-depth-flush:
        inset 0 1px 0 var(--bevel-highlight),
        inset 0 -1px 0 var(--bevel-shade);
      --bevel-depth-raised:
        inset 0 1px 0 var(--bevel-highlight),
        0 1px 0 var(--bevel-material-edge),
        0 2px 0 var(--bevel-material-edge),
        0 3px 5px var(--bevel-shade);
      --bevel-depth-pressed:
        inset 0 1px 2px var(--bevel-shade),
        0 1px 0 var(--bevel-highlight);
      /* A whole object resting on the page. */
      --bevel-depth-object:
        inset 0 1px 0 var(--bevel-highlight),
        inset 0 -1px 0 var(--bevel-shade),
        0 0 0 1px var(--bevel-material-edge),
        0 1px 1px var(--bevel-cast),
        0 6px 12px -2px var(--bevel-cast),
        0 18px 32px -8px var(--bevel-cast);
      /* The shadow under a loose object, for filter: drop-shadow(). */
      --bevel-depth-cast-sm: 0 4px 6px var(--bevel-cast);
      /* A thin object (a card) lying on another surface. */
      --bevel-depth-sheet:
        inset 0 1px 0 var(--bevel-highlight-strong),
        inset 0 0 0 1px oklch(0 0 0 / 0.12),
        0 -1px 2px oklch(0 0 0 / 0.18);
    
      /* 4. Motion */
      --bevel-ease-out: cubic-bezier(0.23, 1, 0.32, 1);
      --bevel-ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
      /* Underdamped spring, ~8% overshoot. Pure CSS; pair with --bevel-duration-move or longer. */
      --bevel-ease-spring: linear(0, 0.06, 0.202, 0.38, 0.561, 0.723, 0.856, 0.955, 1.023, 1.062, 1.081, 1.083, 1.075, 1.062, 1.047, 1.032, 1.019, 1.009, 1.002, 0.997, 0.994, 0.993, 0.993, 0.994, 1);
      --bevel-duration-press: 100ms; /* a control giving under a finger */
      --bevel-duration-small: 200ms; /* hover lifts, tabs, small state changes */
      --bevel-duration-move: 300ms; /* objects moving: cards, drawers */
      --bevel-duration-ambient: 520ms; /* whole-scene changes: lighting */
      --bevel-stagger: 30ms;
      --bevel-lift: 3px; /* how far an object rises on hover */
      --bevel-perspective: 30rem; /* viewing distance for parts that turn in 3D (covers, flaps) */
      /* Unchosen items in a group sit back in shadow. */
      --bevel-dim: 0.82;
    
      /* 5. Shape */
      --bevel-radius-xs: 0.25rem;
      --bevel-radius-sm: 0.5rem;
      --bevel-radius-md: 0.625rem;
      --bevel-radius-lg: 1rem;
      --bevel-radius-xl: 1.5rem;
      --bevel-stitch-width: 1.5px;
      --bevel-stitch-inset: 0.375rem;
      /* Amounts: the figure, its secondary parts (currency, cents), labels, fine print. */
      --bevel-amount: 2.25rem;
      --bevel-amount-minor: 1.25rem;
      --bevel-label: 0.75rem;
      --bevel-fine: 0.6875rem;
      --bevel-tracking-label: 0.08em; /* stamped labels */
      --bevel-tracking-print: 0.06em; /* printed marks on cards */
    
      /* Paper and ink */
      --bevel-paper: oklch(0.975 0.008 85);
      --bevel-paper-foreground: oklch(0.28 0.02 260);
      --bevel-paper-muted: oklch(0.48 0.015 260);
      --bevel-paper-rule: oklch(0.78 0.04 240 / 0.45);
      --bevel-paper-margin: oklch(0.68 0.14 25 / 0.45);
      --bevel-fibre: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='f'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9 .35' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .18 0 0 0 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23f)'/%3E%3C/svg%3E");
      /* Ink soaks unevenly: mostly solid with pale specks. Used as a mask. */
      --bevel-ink-texture: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='i'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -2.4 0 0 0 2.1'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23i)'/%3E%3C/svg%3E");
      --bevel-ink-red: oklch(0.52 0.19 27);
      --bevel-ink-blue: oklch(0.44 0.14 262);
      --bevel-ink-green: oklch(0.5 0.12 155);
      --bevel-ink-black: oklch(0.3 0.01 260);
      --bevel-ink-amber: oklch(0.55 0.13 65);
    
      /* Brass and ivory: instrument hardware and dial faces */
      --bevel-brass: oklch(0.76 0.11 82);
      --bevel-brass-edge: oklch(0.52 0.08 70);
      --bevel-ivory: oklch(0.95 0.025 90);
      --bevel-ivory-foreground: oklch(0.25 0.015 60);
      --bevel-needle: oklch(0.55 0.2 27);
    
      /* Desk stationery: legal pads, pens, pencils, exhibit stickers */
      --bevel-pad: oklch(0.95 0.075 98); /* yellow legal pad */
      --bevel-pad-foreground: oklch(0.27 0.03 255);
      --bevel-pad-rule: oklch(0.72 0.06 235 / 0.45);
      --bevel-pad-margin: oklch(0.62 0.16 25 / 0.55);
      --bevel-pen-red: oklch(0.52 0.2 27); /* correcting pen */
      --bevel-pen-blue: oklch(0.42 0.15 262); /* writing pen */
      --bevel-pencil: oklch(0.55 0.01 260); /* not written in ink yet */
      --bevel-sticker: oklch(0.9 0.12 95); /* exhibit sticker */
      --bevel-sticker-foreground: oklch(0.26 0.03 70);
      /* Handwriting. Bring a marker font (e.g. Permanent Marker) for the full effect; these are fallbacks. */
      --bevel-font-marker: "Permanent Marker", "Marker Felt", "Chalkboard SE", ui-rounded, "Arial Rounded MT Bold", system-ui, sans-serif;
    }
    
    .dark {
      --bevel-highlight: oklch(1 0 0 / 0.14);
      /* Paper under dim light, not inverted: it's still paper. */
      --bevel-paper: oklch(0.88 0.008 85);
      --bevel-ivory: oklch(0.86 0.022 90);
      --bevel-pad: oklch(0.86 0.07 98);
      --bevel-cast: oklch(0 0 0 / 0.55);
    }
    
    /* Depth */
    @utility bevel-recessed {
      background-color: var(--bevel-material-recess);
      box-shadow: var(--bevel-depth-recessed);
    }
    @utility bevel-flush {
      box-shadow: var(--bevel-depth-flush);
    }
    @utility bevel-raised {
      background-color: color-mix(in oklch, var(--bevel-material), white 7%);
      background-image: linear-gradient(to bottom, var(--bevel-highlight), transparent 60%);
      box-shadow: var(--bevel-depth-raised);
    }
    @utility bevel-pressed {
      background-color: color-mix(in oklch, var(--bevel-material), black 4%);
      background-image: none;
      box-shadow: var(--bevel-depth-pressed);
    }
    @utility bevel-object {
      box-shadow: var(--bevel-depth-object);
    }
    
    /* Materials */
    @utility bevel-leather {
      background-color: var(--bevel-material);
      background-image:
        var(--bevel-grain),
        linear-gradient(to bottom, var(--bevel-highlight), transparent 28%, transparent 72%, var(--bevel-shade));
      background-size: var(--bevel-grain-size) var(--bevel-grain-size), 100% 100%;
      background-blend-mode: soft-light, normal;
    }
    @utility bevel-plastic {
      background-color: var(--bevel-material);
      background-image:
        linear-gradient(115deg, var(--bevel-highlight-strong), transparent 40%),
        linear-gradient(to bottom, transparent 25%, oklch(0 0 0 / 0.45));
      box-shadow: var(--bevel-depth-sheet);
    }
    @utility bevel-metal {
      background-color: var(--bevel-material);
      background-image:
        linear-gradient(to bottom, var(--bevel-highlight-strong), transparent 45%, var(--bevel-shade) 100%),
        repeating-linear-gradient(90deg, oklch(1 0 0 / 0.06) 0 1px, transparent 1px 3px);
      box-shadow:
        inset 0 0 0 1px oklch(0 0 0 / 0.25),
        inset 0 1px 0 var(--bevel-highlight-strong);
    }
    
    /* Details */
    @utility bevel-deboss {
      text-shadow: var(--bevel-deboss);
    }
    @utility bevel-stitch {
      border-color: var(--bevel-stitch, oklch(0.88 0.05 82 / 0.8));
      border-style: dashed;
      border-width: var(--bevel-stitch-width);
      filter: drop-shadow(0 1px 0 var(--bevel-shade));
    }
    /* A lit fill sitting in a recess (meters, progress). Colour from --bevel-fill. */
    @utility bevel-fill {
      background-color: var(--bevel-fill);
      background-image: linear-gradient(to bottom, oklch(1 0 0 / 0.55), transparent 55%, oklch(0 0 0 / 0.18));
      box-shadow: 0 0 6px -1px var(--bevel-fill);
    }
    /* A small indicator light. Colour from --bevel-led. */
    @utility bevel-led {
      background-color: var(--bevel-led);
      background-image: radial-gradient(circle at 35% 30%, oklch(1 0 0 / 0.85), transparent 45%);
      box-shadow:
        0 0 6px var(--bevel-led),
        inset 0 -1px 1px oklch(0 0 0 / 0.35),
        0 1px 0 var(--bevel-highlight);
    }
    
    /* Paper: a sheet resting on the surface, with fibre in it. */
    @utility bevel-paper {
      background-color: var(--bevel-paper);
      background-image: var(--bevel-fibre);
      background-size: 240px 240px;
      color: var(--bevel-paper-foreground);
      box-shadow:
        0 1px 1px var(--bevel-cast),
        0 6px 14px -4px var(--bevel-cast);
    }
    /* Ink on paper: multiplies into the surface and soaks unevenly. Colour from --bevel-ink. */
    @utility bevel-ink {
      color: var(--bevel-ink, var(--bevel-ink-red));
      border-color: currentColor;
      mix-blend-mode: multiply;
      mask-image: var(--bevel-ink-texture);
      mask-size: 160px 160px;
    }
    /* Glass over an instrument window: one reflection from the light above. Put on an overlay element. */
    @utility bevel-glass {
      pointer-events: none;
      background-image: linear-gradient(165deg, var(--bevel-highlight-strong) 0%, transparent 38%, transparent 70%, var(--bevel-shade) 100%);
    }
    
    /* Material families: one per screen. Set on the screen's container. */
    [data-bevel-family="leather"] {
      --bevel-cast: oklch(0.25 0.03 50 / 0.22);
    }
    [data-bevel-family="paper"] {
      --bevel-cast: oklch(0.3 0.01 250 / 0.16);
    }
    .dark :is([data-bevel-family="leather"], [data-bevel-family="paper"]) {
      --bevel-cast: oklch(0 0 0 / 0.55);
    }
    
    /*
     * Ruled paper: rules every --bevel-rule-height and a margin line at
     * --bevel-rule-margin. Set --bevel-sheet for the paper colour. The ruling
     * scrolls with the content.
     */
    @utility bevel-ruled {
      background-color: var(--bevel-sheet, var(--bevel-paper));
      background-image:
        linear-gradient(
          to right,
          transparent calc(var(--bevel-rule-margin) - 1px),
          var(--bevel-sheet-margin, var(--bevel-paper-margin)) calc(var(--bevel-rule-margin) - 1px) calc(var(--bevel-rule-margin) + 1px),
          transparent calc(var(--bevel-rule-margin) + 1px)
        ),
        repeating-linear-gradient(
          to bottom,
          transparent 0 calc(var(--bevel-rule-height) - 1px),
          var(--bevel-sheet-rule, var(--bevel-paper-rule)) calc(var(--bevel-rule-height) - 1px) var(--bevel-rule-height)
        ),
        var(--bevel-fibre);
      background-size: 100% 100%, 100% 100%, 240px 240px;
      background-attachment: local;
      color: var(--bevel-paper-foreground);
      box-shadow:
        0 1px 1px var(--bevel-cast),
        0 6px 14px -4px var(--bevel-cast);
    }
  3. Copy toggle-lever.tsx into components/ui.

    components/toggle-lever.tsx
    "use client"
    
    import * as React from "react"
    import { Field } from "@base-ui/react/field"
    import { Switch as SwitchPrimitive } from "@base-ui/react/switch"
    import { cn } from "cn"
    import { useBevelFeedback } from "@/lib/feedback"
    
    type ToggleLeverProps = Omit<SwitchPrimitive.Root.Props, "children"> & {
      /** md prints OFF and ON on the plate; sm is the lever and lamp alone, for dense rows. */
      size?: "sm" | "md"
    }
    
    /**
     * An everyday on/off switch, as a bat-handle toggle on a small plate. The
     * lever swings through the bushing toward the side that's on, settling with
     * a little spring, and a lamp beside it lights. A Base UI Switch: Space
     * flips it.
     */
    function ToggleLever({ className, size = "md", onCheckedChange, ...props }: ToggleLeverProps) {
      const feedback = useBevelFeedback()
      return (
        <SwitchPrimitive.Root
          data-slot="toggle-lever"
          data-size={size}
          onCheckedChange={(checked, details) => {
            feedback.toggle()
            onCheckedChange?.(checked, details)
          }}
          className={cn(
            "bevel-metal inline-flex h-6 shrink-0 cursor-pointer items-center gap-1.5 rounded-(--bevel-radius-xs) px-1.5 select-none",
            "outline-none focus-visible:ring-2 focus-visible:ring-(--toggle-lever-focus) focus-visible:ring-offset-2 focus-visible:ring-offset-background",
            "data-disabled:cursor-not-allowed data-disabled:opacity-60",
            "in-data-[slot=toggle-lever-field]:col-start-2 in-data-[slot=toggle-lever-field]:row-span-2 in-data-[slot=toggle-lever-field]:row-start-1 in-data-[slot=toggle-lever-field]:self-center",
            className
          )}
          {...props}
        >
          {size === "md" && (
            <span aria-hidden data-slot="toggle-lever-legend" data-side="off" className="toggle-lever-print">
              Off
            </span>
          )}
          <span aria-hidden data-slot="toggle-lever-throw" className="relative h-full w-(--toggle-lever-throw)">
            <SwitchPrimitive.Thumb
              data-slot="toggle-lever-bat"
              className={cn(
                "toggle-lever-bat absolute top-1/2 left-1/2 flex h-2 w-(--toggle-lever-reach) origin-left -translate-y-1/2 items-center",
                // Off points left, on points right: the bat swings out toward you and over, foreshortening on the way.
                "-scale-x-100 data-checked:scale-x-100",
                "transition-[scale] duration-(--bevel-duration-move) ease-(--bevel-ease-spring) motion-reduce:transition-none"
              )}
            >
              <span className="h-1 flex-1 rounded-full bg-(--toggle-lever-chrome-shaft)" />
              <span className="toggle-lever-ball size-2 shrink-0 rounded-full" />
            </SwitchPrimitive.Thumb>
            <span data-slot="toggle-lever-bushing" className="toggle-lever-bushing absolute top-1/2 left-1/2 size-2.5 -translate-1/2 rounded-full" />
          </span>
          {size === "md" && (
            <span aria-hidden data-slot="toggle-lever-legend" data-side="on" className="toggle-lever-print">
              On
            </span>
          )}
          <span aria-hidden data-slot="toggle-lever-lamp" className="bevel-led size-1.5 shrink-0 rounded-full" />
        </SwitchPrimitive.Root>
      )
    }
    
    /**
     * A settings row: label and description on the left, the lever on the right.
     * Base UI Field, so the label names the switch and the description describes it.
     */
    function ToggleLeverField({ className, ...props }: Field.Root.Props) {
      return (
        <Field.Root
          data-slot="toggle-lever-field"
          className={cn("grid grid-cols-[minmax(0,1fr)_auto] items-center gap-x-4 gap-y-0.5", className)}
          {...props}
        />
      )
    }
    
    function ToggleLeverLabel({ className, ...props }: Field.Label.Props) {
      return (
        <Field.Label
          data-slot="toggle-lever-label"
          className={cn("col-start-1 text-sm font-medium text-foreground", className)}
          {...props}
        />
      )
    }
    
    function ToggleLeverDescription({ className, ...props }: Field.Description.Props) {
      return (
        <Field.Description
          data-slot="toggle-lever-description"
          className={cn("col-start-1 text-xs text-muted-foreground", className)}
          {...props}
        />
      )
    }
    
    export { ToggleLever, ToggleLeverField, ToggleLeverLabel, ToggleLeverDescription }
    export type { ToggleLeverProps }
  4. Copy toggle-lever.css into your styles.

    styles/toggle-lever.css
    /*
     * Toggle lever: a bat-handle toggle on a small brushed plate. The bat pivots
     * in a hex bushing at the centre and points at the word that's on; the lamp
     * at the end of the plate is lit while it's on. Builds on bevel.css (metal,
     * led, spring).
     */
    
    :root {
      --toggle-lever-plate: oklch(0.88 0.004 260);
      --toggle-lever-plate-edge: oklch(0.68 0.006 260);
      --toggle-lever-print: oklch(0.42 0.01 260); /* engraved legend */
      --toggle-lever-print-lit: oklch(0.2 0.01 260);
      --toggle-lever-print-size: 0.5625rem;
      --toggle-lever-chrome: oklch(0.97 0.003 260);
      --toggle-lever-chrome-shaft: oklch(0.8 0.004 260);
      --toggle-lever-chrome-edge: oklch(0.55 0.006 260);
      --toggle-lever-bushing: oklch(0.6 0.006 260);
      --toggle-lever-lamp-off: oklch(0.55 0.01 260);
      --toggle-lever-lamp-on: oklch(0.8 0.17 145); /* green: running */
      --toggle-lever-focus: oklch(0.76 0.15 68);
      --toggle-lever-cast: 0 1px 0.5px oklch(0 0 0 / 0.45); /* the bat's shadow on the plate */
      --toggle-lever-glint: oklch(1 0 0);
      --toggle-lever-lamp-shade: oklch(0 0 0 / 0.35);
      --toggle-lever-throw: 1.5rem; /* the space the bat swings across */
      --toggle-lever-reach: 0.6875rem; /* bushing centre to the end of the ball */
    }
    
    .dark {
      --toggle-lever-plate: oklch(0.34 0.006 260);
      --toggle-lever-plate-edge: oklch(0.22 0.006 260);
      --toggle-lever-print: oklch(0.66 0.01 260);
      --toggle-lever-print-lit: oklch(0.95 0.005 260);
      --toggle-lever-bushing: oklch(0.24 0.006 260);
      --toggle-lever-lamp-off: oklch(0.3 0.01 260);
    }
    
    [data-slot="toggle-lever"] {
      --bevel-material: var(--toggle-lever-plate);
      --bevel-material-edge: var(--toggle-lever-plate-edge);
      --bevel-led: var(--toggle-lever-lamp-off);
    }
    [data-slot="toggle-lever"][data-checked] {
      --bevel-led: var(--toggle-lever-lamp-on);
    }
    /* An unlit lamp gives no glow. */
    [data-slot="toggle-lever"]:not([data-checked]) [data-slot="toggle-lever-lamp"] {
      box-shadow:
        inset 0 -1px 1px var(--toggle-lever-lamp-shade),
        0 1px 0 var(--bevel-highlight);
    }
    
    /* Engraved legends: the one the bat points at is the lit one. */
    @utility toggle-lever-print {
      font-size: var(--toggle-lever-print-size);
      font-weight: 700;
      line-height: 1;
      letter-spacing: var(--bevel-tracking-label);
      text-transform: uppercase;
      color: var(--toggle-lever-print);
      text-shadow: var(--bevel-deboss);
    }
    [data-slot="toggle-lever"][data-checked] [data-side="on"],
    [data-slot="toggle-lever"][data-unchecked] [data-side="off"] {
      color: var(--toggle-lever-print-lit);
    }
    
    /* The bat: a chrome shaft ending in a ball, casting a small shadow on the plate. */
    @utility toggle-lever-bat {
      filter: drop-shadow(var(--toggle-lever-cast));
    }
    @utility toggle-lever-ball {
      background-color: var(--toggle-lever-chrome);
      background-image: radial-gradient(circle at 35% 30%, var(--toggle-lever-glint), transparent 55%);
      box-shadow: inset 0 0 0 0.5px var(--toggle-lever-chrome-edge);
    }
    @utility toggle-lever-bushing {
      background-color: var(--toggle-lever-bushing);
      background-image: radial-gradient(circle at 50% 35%, var(--bevel-highlight-strong), transparent 60%);
      box-shadow:
        inset 0 0 0 1px var(--toggle-lever-chrome-edge),
        0 1px 0 var(--bevel-highlight);
    }
    
    @media (forced-colors: active) {
      [data-slot="toggle-lever"] {
        border: 1px solid CanvasText;
      }
      [data-slot="toggle-lever-bat"] > * {
        background: CanvasText;
      }
      [data-slot="toggle-lever"][data-checked] [data-slot="toggle-lever-lamp"] {
        background: Highlight;
      }
    }
  5. Import the stylesheets after Tailwind in your global CSS, foundation first.

    globals.css
    @import "./bevel.css";
    @import "./toggle-lever.css";

Anatomy

Each part is its own component. Leave out the ones you don't need.

Anatomy
<ToggleLeverField>
  <ToggleLeverLabel />
  <ToggleLeverDescription />
  <ToggleLever />
</ToggleLeverField>

Parts

PartWhat it does
ToggleLeverSwitchchecked, defaultChecked, onCheckedChange, disabled, name. size md prints OFF and ON on the plate; sm is lever and lamp only. Space flips it. Alone, give it an aria-label.
ToggleLeverFieldField.RootA settings row: label and description on the left, the lever on the right. disabled locks the row.
ToggleLeverLabelField.LabelNames the switch. Clicking it throws the lever.
ToggleLeverDescriptionField.DescriptionDescribes the switch.