# Gradient Border Button

> Button with a continuously rotating conic-gradient border; colors and speed are configurable.

- Author: Atelier UI
- License: MIT
- Page: https://chromotion.dev/en/components/gradient-border-button
- Site: Atelier UI (https://chromotion.dev)

## Install

```bash
npx shadcn@latest add https://chromotion.dev/r/gradient-border-button.json
```

Stack: React + TypeScript + Tailwind CSS v4, shadcn/ui conventions. `cn` comes from `@/lib/utils`.

## Dependencies

No extra dependencies.

## Usage

```tsx title="components/gradient-border-button-demo.tsx"
import { Sparkles } from "lucide-react"

import { GradientBorderButton } from "@/components/gradient-border-button"

export default function GradientBorderButtonDemo() {
  return (
    <div className="flex flex-wrap items-center justify-center gap-6 rounded-2xl bg-neutral-100 p-12 dark:bg-neutral-900">
      <GradientBorderButton>
        <Sparkles className="size-4" />
        Generate
      </GradientBorderButton>
      <GradientBorderButton colors="#f97316, #ef4444, #eab308, #f97316" speed={2}>
        Upgrade
      </GradientBorderButton>
    </div>
  )
}
```

## Source

```tsx title="components/gradient-border-button.tsx"
import * as React from "react"

import { cn } from "@/lib/utils"

export interface GradientBorderButtonProps extends React.ComponentProps<"button"> {
  /** Seconds per rotation */
  speed?: number
  /** Conic-gradient color stops */
  colors?: string
}

export function GradientBorderButton({
  speed = 3,
  colors = "#a855f7, #3b82f6, #22d3ee, #a855f7",
  className,
  children,
  ...props
}: GradientBorderButtonProps) {
  return (
    <button
      type="button"
      className={cn(
        "group relative inline-flex h-12 items-center justify-center overflow-hidden rounded-full p-[2px] select-none",
        "transition-transform duration-150 active:scale-[0.97]",
        "focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background focus-visible:outline-none",
        "disabled:pointer-events-none disabled:opacity-50",
        className
      )}
      {...props}
    >
      <span
        aria-hidden
        className="absolute top-1/2 left-1/2 aspect-square w-[200%] -translate-x-1/2 -translate-y-1/2 animate-spin motion-reduce:animate-none"
        style={{ backgroundImage: `conic-gradient(from 0deg, ${colors})`, animationDuration: `${speed}s` }}
      />
      <span className="relative inline-flex h-full items-center justify-center gap-2 rounded-full bg-neutral-950 px-7 text-sm font-medium text-white transition-colors duration-300 group-hover:bg-neutral-900">
        {children}
      </span>
    </button>
  )
}
```
