Pulsating Button
Pulsating Button renders a second copy of itself behind the real one and grows it from 1 to 1.35 while fading it to nothing, then starts again. The result is a radar ping that pulls the eye without moving the label or the hit area.
The halo is pointer-events-none and sits behind the button, so it never intercepts a click. It is dropped entirely for visitors who have asked for reduced motion.
Usage
A copy of the button sits behind it and keeps expanding and fading, like a radar ping.
<template>
<div class="flex w-full flex-col items-center gap-4 py-6">
<MPulsatingButton>
Live now
</MPulsatingButton>
</div>
</template>
Customize
Customize
Props
| Prop | Type | Default | Description |
|---|---|---|---|
duration | number | 1.6 | Seconds one pulse takes to expand and fade. |
class | string | '' | CSS classes for the button itself. The halo inherits the button's rounding through rounded-[inherit]. |
Slots
| Slot | Props | Description |
|---|---|---|
default | - | The button's label. |
UI
This component's theme exposes the slots below. Override any of them per instance with the ui prop, or app-wide under ui.pulsatingButton in app.config.ts.
| Prop | Type | Default | Description |
|---|---|---|---|
ui | object | - | Per-slot classes merged over the theme defaults. |
| Slot | Props | Description |
|---|---|---|
root | - | group relative inline-flex items-center justify-center rounded-lg bg-primary px-6 py-3 text-sm font-medium text-inverted active:scale-[0.98] |
pulse | - | pointer-events-none absolute inset-0 -z-10 rounded-[inherit] bg-primary |
label | - | relative |
Accessibility
The root is a real <button type="button">. The halo is decorative and marked aria-hidden, so it contributes nothing to the accessibility tree. A looping pulse can be distracting for some visitors, which is why it is skipped entirely under reduced motion.