Buttons & Toggles

Rainbow Button

A button with a flowing rainbow gradient animation, in solid and outline styles, with a soft glow in matching hues.

A button whose rainbow gradient keeps flowing horizontally, with solid and outline styles built in plus an adjustable flow speed and a matching-hue glow.

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 rainbow-button.en

New project or installation trouble? Start here →

Rainbow Button is a React rainbow gradient button built with Tailwind CSS and CSS keyframes: the gradient flows continuously through a background-position animation, a blurred glow in the same colors sits underneath, and an outline variant shows the rainbow only on the border. Motion is used only to read the reduced-motion setting.

Playground

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

3
Active edited usageDefault props
<RainbowButton/>

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 "Start free trial" or "Get started"
  • An entry point that has to stand out on a feature launch or event page
  • Secondary buttons on dark developer-tool pages, using the outline variant
  • Once per screen, so it doesn't compete with other buttons

Installation

npx webberui@latest add https://webberui.com/r/rainbow-button.en.json

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

Usage

import { RainbowButton } from "@/components/ui/rainbow-button";

<RainbowButton>Get Started</RainbowButton>
<RainbowButton variant="outline">Outline</RainbowButton>

Custom color ramp and flow speed:

<RainbowButton
  colors={["#ff4d4d", "#4dd2ff", "#c14dff"]}
  speed={1.5}
>
  Custom
</RainbowButton>

RainbowButton forwards all native <button> attributes (onClick, disabled, type, and so on).

Examples

With an icon

The children wrapper is already inline-flex with gap-2, so drop in text and an icon.

import { ArrowRight } from "lucide-react";
import { RainbowButton } from "@/components/ui/rainbow-button";

<RainbowButton className="px-6 py-3 text-base">
  Start free trial
  <ArrowRight className="size-4" />
</RainbowButton>

Form submit with a pending state

Native button attributes are passed through, so type="submit" and disabled work as usual; a disabled button gets opacity-50 and ignores pointer events.

"use client";

import { useFormStatus } from "react-dom";
import { RainbowButton } from "@/components/ui/rainbow-button";

export function SubmitButton() {
  const { pending } = useFormStatus();
  return (
    <RainbowButton type="submit" disabled={pending}>
      {pending ? "Submitting…" : "Join the waitlist"}
    </RainbowButton>
  );
}

Dark brand palette

The solid variant uses near-black text by default; with a dark palette, switch to white text through className. glow={false} removes the glow underneath.

<RainbowButton
  colors={["#1e3a8a", "#7c3aed", "#be185d"]}
  speed={5}
  glow={false}
  className="text-white"
>
  Book a demo
</RainbowButton>

Props

PropTypeDefaultDescription
colorsstring[]the seven rainbow colorsThe rainbow color ramp; the end loops back to the first color to close the ring, minimum two colors
speednumber3Duration of one flow cycle (seconds); smaller is faster
variant"solid" | "outline""solid"solid fills with the gradient; outline shows the rainbow only on the border and the glow
glowbooleantrueWhether to layer a soft glow in matching hues underneath
classNamestring—Styles forwarded to the root button

All native button attributes are supported as well.

Accessibility

  • When the user has "reduce motion" enabled at the system level, the gradient flow pauses at a standstill while the rainbow appearance is kept
  • On focus it provides a clear focus-visible outline ring, keeping keyboard operation visible
  • Rendering is identical before and after mounting, avoiding an SSR hydration mismatch

FAQ

It always renders a <button> and has no asChild option. For navigation, call your router in onClick (for example router.push in Next.js) rather than wrapping it in an <a>, since a button inside a link is invalid HTML nesting.

Does it work with the Next.js App Router?

Yes. The source already has "use client", so import it from a Server Component page. The animation keyframes are injected into <head> after mount, and all buttons share a single copy.

How do I change the speed and colors?

speed is the length of one cycle in seconds, so lower is faster. colors takes any CSS color strings, at least two, and the first color is appended to the end so the loop has no seam.

What happens with reduced motion enabled?

The gradient pauses in place; the button keeps its rainbow look without moving.

What are the dependencies?

motion, clsx, tailwind-merge, and the cn helper in @/lib/utils; lucide-react is only needed for the icon in the example. You can also copy the source from the Manual tab.