WebberUI

Ripple Button

A button with a spreading click ripple, radiating a Material-style wave out from the click point.

On click, a ripple radiates from the cursor's landing point, with a diameter reaching the farthest corner so the wave always covers the whole button. The ripple sits beneath the content and is clipped into the button's shape by overflow-hidden.

Loading preview…
npx shadcn@latest add https://webberui.com/r/ripple-button.json

Playground

Tune the props live — the code snippet updates as you go, so you can dial in the look you want before copying it.

0.6
0.5
<RippleButton />

Installation

npx shadcn@latest add https://webberui.com/r/ripple-button.json

Or, once registries are configured in components.json, install it as @webberui/ripple-button.

Usage

import { RippleButton } from "@/components/ui/ripple-button";

<RippleButton onClick={() => console.log("clicked")}>
  Click to ripple
</RippleButton>

To change the color just pass rippleColor; all other <button> attributes (type, disabled, onClick, and so on) are forwarded.

Props

Apart from the props below, all native <button> attributes are forwarded.

PropTypeDefaultDescription
rippleColorstring"rgba(255, 255, 255, 0.55)"Ripple color; any CSS color value
durationnumber0.6Duration of a single ripple's spread (seconds)
opacitynumber0.5Starting opacity of the ripple
classNamestringForwarded to the button; can override the default styles
childrenReactNodeButton content

Accessibility

  • When the user has "reduce motion" enabled at the system level, the ripple is skipped and only the ordinary button behavior remains
  • The ripple layer carries aria-hidden and pointer-events-none, so it affects neither assistive technology nor clicks
  • The native <button> semantics and keyboard focus ring are preserved, and interaction is disabled while disabled

On this page