SlideToDetonate guards destructive actions behind a deliberate drag gesture. A raised handle sits in a recessed track (dark or light), a soft white trail fills in behind it as you drag, and the handle glows once the fuse is armed. Let go too early and it springs back; release past the threshold and onConfirm fires. Tune how hard the fuse pushes back with resistance and how softly the handle follows your finger with smoothness.
Preview
Props
Install
Add the item with the shadcn CLI.
npx shadcn@latest add @evilbuttons/slide-to-detonateUsage
import { SlideToDetonate } from "@/components/evil-buttons/slide-to-detonate";
export function ButtonDemo() {
return (
<SlideToDetonate onConfirm={() => launchTheMissiles()}>
Slide to detonate
</SlideToDetonate>
);
}Variants
Light
variant="light" swaps the dark groove for a light one with a white handle.
Heavy fuse
High resistance makes the handle lag further behind the pointer the closer it gets to the end.
Locked to the pointer
smoothness={0} and resistance={0} give a direct, one-to-one drag with no spring.
Floaty
High smoothness lets the handle glide behind the pointer on a loose spring.
Props
The component spreads native button props onto the handle, except onClick and style.
| Prop | Type | Default | Description |
|---|---|---|---|
children | React.ReactNode | - | Track label shown while idle. Falls back to label. |
label | React.ReactNode | "Slide to detonate" | Idle label used when no children are provided. |
onConfirm | () => void | - | Fired once the handle is released past the threshold. |
threshold | number | 0.9 | Fraction of the track (0-1) the handle must cross to arm the action. |
resistance | number | 0.35 | How hard the fuse pushes back (0-1). 0 tracks the pointer one to one; higher values make the handle lag further behind toward the end. |
smoothness | number | 0.4 | How softly the handle follows the pointer (0-1). 0 locks it to the pointer; higher values glide behind on a looser spring. |
variant | "dark" | "light" | "dark" | Surface style: a recessed dark groove or a light one. |
resetAfter | number | 1600 | Milliseconds to stay in the success state before resetting. Set to 0 to stay. |
disabled | boolean | false | Locks the handle and dims the track. |
className | string | - | Extra classes passed to the track. |
Notes
- Resistance bends the pointer-to-handle curve rather than capping it, so a heavy fuse still reaches the end if you drag all the way.
- Smoothness maps to the follow spring:
0sets the position directly, and higher values lower the stiffness and damping so the handle trails and settles. - Pulling back past the start rubber-bands a few pixels instead of stopping dead.
- The handle is a
role="slider"with livearia-valuenow. ←/→ step by 10%, Home resets, and End or stepping past the threshold detonates. Keyboard progress snaps back when focus leaves. - Crossing the threshold arms the fuse: the handle glows, the trail brightens, and phones get a short vibration where supported.
data-state(idle|sliding|success) anddata-armedare exposed on both the track and the handle. - A
ResizeObserverre-measures the track so the drag range stays correct across layout changes. - With reduced motion, springs and the label shimmer are skipped; the handle moves directly.
Registry
The registry item includes components/evil-buttons/slide-to-detonate.tsx and installs clsx, tailwind-merge, and motion.