Shimmer Button
A shimmer button with light flowing around its edge, an inner highlight lining, and dimensional hover feedback.
A bright arc rotates continuously around the button's center, revealed only along the border ring, forming light that flows around the perimeter. Pure CSS conic gradient plus motion/react rotation — no canvas and no external assets.
Bring this into your project
Run this command in your project folder. The CLI adds the source and dependencies; then follow the usage example below.
npx webberui@latest add shimmer-button.enShimmer Button is a React shimmer button component built with Tailwind CSS and Motion. A CSS conic-gradient arc rotates behind the button and only the outer edge shows through, so light appears to travel around the border.
Playground
Tune the props live — the code snippet updates as you go, so you can dial in the look you want before copying it.
<ShimmerButton/>
The complete example includes the preview layout and data. Install the component first, then paste this file into your project.
When to use
- The primary call to action in a landing page hero, such as "Get started" or "Book a demo".
- The button on the recommended plan of a pricing page, to set it apart from the regular buttons.
- Dark-themed product or event pages that need one button to stand out on a dark background.
- Not a good fit: several on the same screen. The moving light competes for attention, so use one per section and regular buttons for the rest.
Installation
npx webberui@latest add https://webberui.com/r/shimmer-button.en.jsonOr, once registries are configured in components.json, install it as @webberui/shimmer-button.
Usage
import { ShimmerButton } from "@/components/ui/shimmer-button";
<ShimmerButton onClick={() => console.log("clicked")}>
Get Started
</ShimmerButton>The component forwards all native button attributes (onClick, disabled, type, and so on), and className can override the size and background color.
Examples
Form submit button, disabled while pending
All native button attributes are forwarded, so type="submit" and disabled work as usual; when disabled the button dims and stops receiving clicks.
"use client";
import { useFormStatus } from "react-dom";
import { ShimmerButton } from "@/components/ui/shimmer-button";
export function SubmitButton() {
const { pending } = useFormStatus();
return (
<ShimmerButton type="submit" disabled={pending}>
{pending ? "Submitting…" : "Join the waitlist"}
</ShimmerButton>
);
}Brand gradient background with colored light
background takes any CSS background value, including gradients. shimmerColor changes the light color and spread sets the arc length.
<ShimmerButton
background="linear-gradient(135deg, #4f46e5, #7c3aed)"
shimmerColor="#c4b5fd"
spread={70}
shimmerDuration={4}
>
Book a product demo
</ShimmerButton>Square corners and a larger size
A fixed borderRadius gives square corners; override the default px-6 py-3 text-sm sizing with className.
<ShimmerButton
borderRadius="12px"
shimmerSize="2px"
className="px-8 py-4 text-base"
>
Download for desktop
</ShimmerButton>Props
| Prop | Type | Default | Description |
|---|---|---|---|
shimmerColor | string | "#ffffff" | Color of the light flowing around the edge |
shimmerSize | string | "1.5px" | Thickness of the light band (that is, the border width) |
shimmerDuration | number | 3 | Time for the light to travel around once (seconds) |
spread | number | 40 | Angular width of the bright arc (degrees); larger means a longer light band |
borderRadius | string | "9999px" | Button corner radius |
background | string | "rgba(0, 0, 0, 1)" | Button background color, either a solid color or a gradient |
className | string | — | Forwarded to the root button; can override spacing and size |
All other React.ButtonHTMLAttributes are forwarded to the underlying button.
Accessibility
- When the user has "reduce motion" enabled at the system level, the light stops rotating and the button keeps a static appearance
- Every decorative layer carries
aria-hidden, so assistive technology only reads the button text - It has a
focus-visiblefocus ring, keeping keyboard operation visible
FAQ
Does it work with the Next.js App Router?
Yes. The file starts with "use client", so import it from a Server Component page as usual. The first render matches the server output, and rotation stops for reduced motion only after mount.
Can I use it as a link?
It renders a native button and has no option to render an a instead. To navigate, call your router in onClick. Do not wrap it in <a> or Link, because a button inside a link is invalid HTML.
How do I change the speed, color and thickness of the light?
shimmerDuration is seconds per lap (default 3), shimmerColor is the light color, shimmerSize is the band thickness (default 1.5px) and spread is the arc width in degrees (default 40).
Can I change the text color?
It defaults to text-white. Add another text-* class in className to override it, for example text-neutral-900 on a light background.
What are the dependencies?
motion, clsx and tailwind-merge. The light itself is a CSS gradient, with no canvas or images. If you prefer not to use the CLI, copy the source from the Manual tab in Installation.
Related guides
Stateful Button
A state-machine button running idle → loading → success / error, switching automatically from an async onClick, with the content crossfading and the width morphing along with it.
Ripple Button
A button with a spreading click ripple, radiating a Material-style wave out from the click point.