DitherButton uses a tiny canvas painter to render a 4x4 ordered (Bayer) dither, animated as a slow rotating sine wave. The label sits in a knockout panel with a hard offset shadow so it stays readable on top of the moving pattern. Colors are read from the current --color-foreground / --color-background tokens so it tracks the active theme.

Preview

DitherButton

Interactive

Variants

Because the dither colors are read from the resolved color and background-color of the canvas, you can re-skin the button by overriding text/background utilities via className.

Rounded pill

Pill

Rounded full + extra padding

Hot pink

Hot pink

Magenta dither on deep navy

Tiny chip

Chip

Compact size with thin border

Chunky dither

Chunky

Big particles via ditherSize={10}

Fine dither

Fine

Tight particles via ditherSize={2}

Install

Add the item with the shadcn CLI.

npx shadcn@latest add @evilbuttons/dither-button

Usage

[]txt
import DitherButton from "@/components/evil-buttons/dither-button";

export function ButtonDemo() {
  return <DitherButton>Launch</DitherButton>;
}

Props

The component spreads any <button> HTML attributes.

PropTypeDefaultDescription
childrenReact.ReactNode-The visible button label or content.
classNamestring-Extra classes passed to the button.
ditherColorstring (hex)-Override the dither "on" pixel color (e.g. #ff0066). Falls back to the resolved color.
ditherOpacitynumber (0–1)1CSS opacity applied to the dither canvas.
ditherSizenumber (1–32)4Pixel scale of the dither particles. Higher = chunkier blocks.

Notes

  • Renders at 1/4 the visual resolution with image-rendering: pixelated for crisp pixel edges.
  • Honors prefers-reduced-motion by drawing a single static frame.
  • The dither colors follow the resolved CSS color and background-color of the canvas, so themes work out of the box.

Registry

The registry item includes components/evil-buttons/dither-button.tsx and installs clsx and tailwind-merge as dependencies.