RealisticSwitch

A latching push switch, a raised box that sinks into its socket when pressed, stays down and glows while on, and springs back up on the next press.

RealisticSwitch is a latching push switch. A solid, raised box stands in a recessed socket and casts its shadow into the well. Hover it and it dips a little. Press it and it sinks all the way down, then latches partway down while it is on, lighting up from inside and pooling light in the socket around it. Press again and it springs back up with a small bounce. The socket is ceramic white in light mode and graphite in dark mode. It is a native role="switch" button, so clicks, Enter, and Space all work.

Preview

Props

Variants

Colors

Pass any CSS color. The walls, shading, and glow are all mixed from it. Use markColor to keep the power mark readable on light caps.

Sizes

Install

Add the item with the shadcn CLI.

npx shadcn@latest add @evilbuttons/realistic-switch

Usage

import { RealisticSwitch } from "@/components/evil-buttons/realistic-switch";

export function PowerSwitch() {
  return (
    <RealisticSwitch
      sound
      aria-label="Main power"
      onCheckedChange={(on) => console.log("power:", on)}
    />
  );
}

Controlled usage:

<RealisticSwitch checked={isLive} onCheckedChange={setIsLive} color="#1f6feb" />

Props

PropTypeDefaultDescription
checkedboolean-Controlled on state.
defaultCheckedbooleanfalseInitial state when uncontrolled.
onCheckedChange(checked: boolean) => void-Called when the switch latches or releases.
colorstring"#e1261c"Cap color. Any CSS color.
markColorstringwhiteColor of the power mark on the cap.
tone"auto" | "light" | "dark""auto"Socket finish: follow the theme, or force ceramic white or graphite.
illuminatedbooleantrueLight the cap from inside while it is latched on.
soundbooleanfalsePlay a short mechanical click when it latches or releases.
size"sm" | "default" | "lg""default"Scales the whole switch.
disabledbooleanfalseDisables the switch.
aria-labelstring"Power"Accessible name for the switch.
classNamestring-Extra classes on the button.

Notes

  • The cap is a box standing on its own walls, and only its height changes, so it sinks and rises as one solid piece with its shadow following it.
  • The click sound is synthesized with the Web Audio API, so there are no audio files to ship. It stays silent where audio is unavailable.
  • Everything is sized in em, so size just sets the font size the whole switch scales from.
  • The spring is skipped when the user prefers reduced motion, and the hover dip only follows a mouse, not touch.

Registry

The registry item includes components/evil-buttons/realistic-switch.tsx and installs motion, clsx, and tailwind-merge as dependencies. The component imports cn from @/lib/utils.

Search docs

Jump to a button documentation page