Getting Started
Components
- All Components
- Animated Arrow
- Animated Save Button
- Animated Tabs
- Animated List/Grid View
- Animated Copy Button
- Animated 3D Folder
- Cursor-Tracking Glow Card
- Gradient Border Button
- Inline Edit Animation
- Animated OTP Input
- Liquid Metal Border
- Animated Password Input
- Interactive Pie Chart
- Typewriter
- Interactive World Map
Installation
npx shadcn@latest add "https://ui.srb.codes/r/gradient-border-button"
Copy and paste the following code into your project.
"use client";
import { Slot } from "@radix-ui/react-slot";
import { type VariantProps, cva } from "class-variance-authority";
import type * as React from "react";
import { cn } from "@/lib/utils";
const gradientBorderButtonVariants = cva(
"group/gradient-border relative inline-flex shrink-0 items-stretch justify-center overflow-visible rounded-xl p-0.5 outline-none transition-transform focus-within:ring-[3px] focus-within:ring-ring/50 has-disabled:pointer-events-none has-disabled:opacity-50 active:scale-[0.98]",
{
variants: {
size: {
default: "",
sm: "",
lg: ""
}
},
defaultVariants: {
size: "default"
}
}
);
const gradientBorderButtonInnerVariants = cva(
"relative z-10 inline-flex items-center justify-center gap-2 rounded-[calc(var(--radius-xl)-2px)] bg-muted font-medium text-foreground shadow-xs outline-none transition-shadow group-hover/gradient-border:shadow-md focus-visible:outline-none",
{
variants: {
size: {
default: "h-9 px-4 text-sm",
sm: "h-8 px-3 text-xs",
lg: "h-12 px-8 text-base"
}
},
defaultVariants: {
size: "default"
}
}
);
const borderTrackClassName =
"pointer-events-none absolute inset-0 overflow-hidden rounded-xl transition-[inset] duration-300 ease-out group-hover/gradient-border:-inset-1";
function GradientBorderButton({
className,
size,
asChild = false,
children,
...props
}: React.ComponentProps<"button"> &
VariantProps<typeof gradientBorderButtonVariants> & {
asChild?: boolean;
}) {
const InnerComp = asChild ? Slot : "button";
return (
<span
data-slot="gradient-border-button"
className={cn(gradientBorderButtonVariants({ size, className }))}
>
<span aria-hidden className={borderTrackClassName}>
<span className="absolute inset-[-200%] animate-[spin_3s_linear_infinite] bg-[conic-gradient(from_0deg,var(--color-blue-500),var(--color-blue-600),var(--color-blue-400),var(--color-blue-600),var(--color-blue-500))] opacity-90" />
</span>
<span
aria-hidden
className={cn(
borderTrackClassName,
"opacity-40 mix-blend-soft-light dark:opacity-50 dark:mix-blend-overlay"
)}
>
<span className="absolute inset-[-200%] animate-[spin_5s_linear_infinite_reverse] bg-[conic-gradient(from_180deg,var(--color-blue-500)_0%,transparent_35%,var(--color-blue-600)_50%,transparent_65%,var(--color-blue-500)_100%)]" />
</span>
<InnerComp
className={cn(gradientBorderButtonInnerVariants({ size }))}
{...props}
>
{children}
</InnerComp>
</span>
);
}
export { GradientBorderButton, gradientBorderButtonVariants };