Theme Toggle
A dithered “hand of god” Theme toggle. Hands slide in, meet at the center, the theme changes with circular View Transition, then retreat. Uses next-themes.
Default
Click the trigger to watch the hands slide in and flip the theme. Honors prefers-reduced-motion.
Installation
$ npx shadcn add https://knot-ui.trupal.me/r/hand-toggle.json
Customization
Tune the dither resolution, cell size, and colors via props.
Props
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| leftImage | string | "/left.png" | URL of the image used for the left hand. Falls back to a drawn hand if missing. |
| rightImage | string | "/right.png" | URL of the image used for the right hand (mirrored). Falls back to a drawn hand if missing. |
| columns | number | 100 | Dither resolution — number of columns used to render each hand. |
| cellSize | number | 10 | Pixel size of each dither cell before scaling. |
| lightColor | string | "#111111" | Dither color used when the light theme is active. |
| darkColor | string | "#eaeaea" | Dither color used when the dark theme is active. |
| travelDistance | number | — | Override how far the hands slide in from the edges. Defaults to half the viewport width plus the pair width. |
| gap | number | 10 | Gap (px) between the two hands at the center meet point. |
| className | string | — | Classes applied to the overlay layer that holds the hands. |
| triggerClassName | string | — | Classes applied to the trigger button. |
| children | React.ReactNode | <Sun /> / <Moon /> | Custom trigger content. Defaults to a lucide Sun icon in dark mode and a Moon icon in light mode (shadcn-style). |
| onToggle | (isDark: boolean) => void | undefined | Callback fired after a toggle. Use together with isDark for fully controlled theming. |
| isDark | boolean | undefined | Controlled dark state. When provided the component never manages theme itself. |