TrollButton

A button that dodges the cursor until it runs out of stamina, then gives up and lets you click it.

TrollButton refuses to be clicked, at first. As the cursor closes in it springs out of the way, leaning into each dodge, and when it's backed into a corner it slips past you to the other side. Every chase drains a thin stamina bar along its bottom edge. After a few seconds it runs out of breath, slumps back into place, and finally lets you click it.

Preview

Props

Install

Add the item with the shadcn CLI.

npx shadcn@latest add @evilbuttons/troll-button

Usage

import TrollButton from "@/components/evil-buttons/troll-button";

export function ButtonDemo() {
  return (
    <TrollButton giveUpAfter={3000} onClick={() => console.log("Caught it")}>
      Click If You Can
    </TrollButton>
  );
}

Variants

Stubborn

A long chase over a wide area before it gives in.

Props

The component spreads native button props and forwards its ref to the button.

PropTypeDefaultDescription
childrenReact.ReactNode-Button label. Falls back to label.
labelReact.ReactNode"Click Me"Label used when no children are provided.
surrenderLabelReact.ReactNode"Fine, click me"Label shown once the button gives up.
giveUpAfternumber3500Milliseconds of chasing before it gives up. The timer starts on the first dodge.
fleeRadiusnumber56How close in px the cursor can get to the button's edge before it dodges.
rangenumber140Maximum distance in px it strays from its resting spot.
resetAfternumber1500Milliseconds after a successful click before it starts fleeing again. 0 keeps it caught.
onClick(event) => void-Only fires once the button has given up.
classNamestring-Extra classes passed to the button.

Notes

  • Distance is measured from the button's resting slot plus its current offset, so dodges don't jitter as it moves.
  • On touch there is no hover, so tapping makes it dodge instead, and those taps count toward the timer.
  • Keyboard activation always goes through, and prefers-reduced-motion turns the fleeing off entirely.
  • Shares the graded dark surface, hairline ring, and spring press used by MinimalButton and CommandButton. The stamina bar drains along its bottom edge while it's chased.

Registry

The registry item includes components/evil-buttons/troll-button.tsx and installs motion, clsx, and tailwind-merge as dependencies. The component imports cn from @/lib/utils, matching the project alias in components.json.

Search docs

Jump to a button documentation page