# Badge Gradient Outline — React Badge Component

> Pill badges with a hairline gradient border and matching gradient text; on hover the colours slide through the outline and a soft tint fills the pill.

- Category: [Badges](https://pixelpapa.com/components/badges.md)
- Tags: badge, gradient, outline, label, hover
- Dependencies: lucide-react (plus React and Tailwind CSS v4)
- Last updated: 2026-11-13
- Live preview: https://pixelpapa.com/components/badges/badge-gradient-outline

## Install

```bash
npx shadcn@latest add "https://pixelpapa.com/r/badge-gradient-outline.json"
```

The file is written to `components/pixelpapa/badge-gradient-outline.tsx`. To install manually, run `npm install lucide-react` and copy the source below into your project. It imports `cn` from `@/lib/utils`, which every shadcn project has.

## Source

```tsx
"use client";

import { ArrowRight, Crown, Sparkles } from "lucide-react";
import type { CSSProperties, ReactNode } from "react";
import { cn } from "@/lib/utils";

type GradientBadgeProps = {
  children: ReactNode;
  /** Two or three CSS colours, left to right. */
  colors?: string[];
  icon?: ReactNode;
  size?: "sm" | "md";
  /** Keep the gradient drifting instead of only moving on hover. */
  animated?: boolean;
  /** Render as a link. */
  href?: string;
  className?: string;
};

export function GradientBadge({
  children,
  colors = ["var(--chart-2)", "var(--chart-1)", "var(--chart-3)"],
  icon,
  size = "md",
  animated = false,
  href,
  className,
}: GradientBadgeProps) {
  // Mirrored stops (a → b → c → b → a) so the 200% wide image can slide without a seam.
  const mirrored = [...colors, ...colors.slice(0, -1).reverse()].join(", ");
  const paint: CSSProperties = {
    backgroundImage: `linear-gradient(100deg, ${mirrored})`,
    backgroundSize: "200% 100%",
  };
  const slide = cn(
    "bg-[position:0%_0] transition-[background-position] duration-700 ease-out group-hover:bg-[position:100%_0]",
    animated && "[animation:pp-badge-gradient-outline-drift_5s_ease-in-out_infinite_alternate] motion-reduce:[animation:none]",
  );
  const shell = cn("group relative inline-flex rounded-full p-px", className);
  const tint = { "--pp-tint": colors[Math.floor(colors.length / 2)] } as CSSProperties;

  const body = (
    <>
      <style>{`@keyframes pp-badge-gradient-outline-drift { to { background-position: 100% 0; } }`}</style>
      <span aria-hidden style={paint} className={cn("absolute inset-0 rounded-full", slide)} />
      <span
        className={cn(
          "relative inline-flex items-center rounded-full bg-background font-medium transition-colors duration-500 group-hover:bg-[color-mix(in_oklch,var(--pp-tint)_9%,var(--background))]",
          size === "md" ? "gap-1.5 px-3 py-1 text-xs" : "gap-1 px-2 py-0.5 text-[11px]",
        )}
      >
        {icon && <span className="flex shrink-0 text-[var(--pp-tint)]">{icon}</span>}
        <span style={paint} className={cn("bg-clip-text text-transparent", slide)}>
          {children}
        </span>
        {href && (
          <ArrowRight className="size-3 text-[var(--pp-tint)] transition-transform duration-300 group-hover:translate-x-0.5" />
        )}
      </span>
    </>
  );

  return href ? (
    <a href={href} style={tint} className={cn(shell, "outline-offset-4")}>
      {body}
    </a>
  ) : (
    <span style={tint} className={shell}>
      {body}
    </span>
  );
}

const sunset = ["var(--chart-4)", "oklch(0.66 0.22 20)", "var(--chart-3)"];
const mint = ["var(--chart-5)", "var(--chart-2)"];

export default function BadgeGradientOutlineDemo() {
  return (
    <div className="flex max-w-xl flex-col items-center text-center">
      <GradientBadge href="#" animated icon={<Sparkles className="size-3.5" />}>
        Northwind 4.2 is in early access
      </GradientBadge>
      <h3 className="mt-5 text-3xl font-semibold tracking-tight text-balance text-foreground">
        Dashboards that explain themselves
      </h3>
      <div className="mt-7 flex flex-wrap items-center justify-center gap-2.5">
        <GradientBadge colors={sunset} icon={<Crown className="size-3.5" />}>
          Pro plan
        </GradientBadge>
        <GradientBadge colors={mint}>SOC 2 Type II</GradientBadge>
        <GradientBadge>v4.2.0</GradientBadge>
        <GradientBadge colors={sunset} size="sm">
          Limited
        </GradientBadge>
        <GradientBadge colors={mint} size="sm">
          Free
        </GradientBadge>
      </div>
    </div>
  );
}
```

## AI prompt

```text
Add the "Badge Gradient Outline" component from PixelPapa UI to this project.

What it is: Pill badges with a hairline gradient border and matching gradient text; on hover the colours slide through the outline and a soft tint fills the pill.
Category: Badges. Depends on: lucide-react.

1. Install it with the shadcn CLI:
   npx shadcn@latest add "https://pixelpapa.com/r/badge-gradient-outline.json"
   (If the CLI is unavailable, fetch that URL, write files[0].content to components/pixelpapa/badge-gradient-outline.tsx and install the listed dependencies.)
2. Import it from "@/components/pixelpapa/badge-gradient-outline" and place it where I describe below.
3. Keep its animation timings and accessibility attributes. Replace the demo copy and data with content that fits my product, and use my existing theme tokens (bg-background, text-foreground, bg-primary, border-border) rather than hard-coded colours.

Where to use it: <describe the page and position here>
```

## More badges

- [Badge Count Pop](https://pixelpapa.com/components/badges/badge-count-pop.md) (Pro): A notification count that bumps with a spring whenever it changes, rolls the digits in the direction of the change and pops out at zero.
- [Badge Dismissible Tags](https://pixelpapa.com/components/badges/badge-dismissible-tags.md) (Pro): Removable tags that blur and shrink away while their neighbours glide into the gap with a layout spring.
- [Badge Shimmer New](https://pixelpapa.com/components/badges/badge-shimmer-new.md): A small "New" label whose text catches a passing highlight on a loop while a tiny spark twinkles beside it.
- [Badge Status Pulse](https://pixelpapa.com/components/badges/badge-status-pulse.md): Status badges with a live dot per state: a calm sonar ring for healthy, a breathing glow for degraded, urgent double rings for down and an orbiting arc for deploying.
- [Badge Trend Delta](https://pixelpapa.com/components/badges/badge-trend-delta.md) (Pro): A delta badge that flips its arrow with a spring, cross-fades between green and red and rolls the figure whenever the value changes sign or size.
- [Badge Verified Seal](https://pixelpapa.com/components/badges/badge-verified-seal.md) (Pro): A scalloped verification seal that spins in on a spring, draws its check stroke, takes a single sheen and then keeps turning slowly. Hover replays it.
