DEV Community

Cover image for Make Your Buttons Dodge the Cursor with a Wrium Plugin
Benyamin Khalife
Benyamin Khalife

Posted on

Make Your Buttons Dodge the Cursor with a Wrium Plugin

Most buttons just sit there and wait to be clicked. This one doesn't.

Wrium Evasive Button is a small plugin for Wrium that makes a button (or any interactive element) smoothly dodge the cursor when you get close. It's silly on purpose, but it turns out to be surprisingly useful.

Why would you want this?

  • Smart form validation: the submit button stays out of reach until the required fields are valid
  • Gamified forms and playful login screens
  • Interactive confirmations where the "wrong" choice is hard to click

What you get

  • Smooth, physics-style gliding along walls, with no teleporting or sticking at edges
  • Movement limited to the parent, the viewport, or any element you choose
  • Limits via maxRadius, duration, and maxAttempts, so the button eventually gives up and settles
  • Reactive toggling: v-evade="{ active: !isFormValid }"
  • State classes and attributes for styling: .is-evading, .is-settled, data-state
  • @evade, @settle, and @giveup events
  • Respects prefers-reduced-motion and keeps keyboard navigation working (Tab + Enter/Space)
  • Zero dependencies

Install

npm install @wrium/evasive-button
Enter fullscreen mode Exit fullscreen mode

@wrium/wrium is a peer dependency, so install it too if you haven't already.

Basic usage

<div id="app">
    <button v-evade>Try to Click Me!</button>
</div>

<script type="module">
    import { createApp } from '@wrium/wrium';
    import { EvasiveButtonPlugin } from '@wrium/evasive-button';

    createApp(() => ({}))
        .use(EvasiveButtonPlugin)
        .mount('#app');
</script>
Enter fullscreen mode Exit fullscreen mode

That's it. The button now runs away from your mouse.

The practical version: form validation

Bind active to your form state. While the form is invalid the button dodges, and once it's valid the button glides back home, ready to be clicked:

<div id="button-arena">
    <button
        v-evade="{ active: !isFormValid, bounds: '#button-arena', maxRadius: 150 }"
    >
        {{ isFormValid ? 'Log In' : 'Fill fields first!' }}
    </button>
</div>
Enter fullscreen mode Exit fullscreen mode

You can also style it based on its state:

.login-btn.is-evading { background: #e11d48; }
Enter fullscreen mode Exit fullscreen mode

A note on UX and accessibility

An evasive button is a fun UX trick, so use it with care. The plugin helps by respecting reduced-motion preferences, letting keyboard users submit normally, and giving up after a duration or number of attempts if you set those options. I'd still keep it for playful or low-stakes moments rather than critical flows.

Try it

It's MIT licensed, and the repo includes unit tests (Vitest) and end-to-end tests (Playwright). Issues and PRs are welcome. I'd love to see the creative ways you use it!

Top comments (0)