Components
Badge
Badge
Animated badge component with multiple variants, sizes, and customizable styling options.
Badge
Installation
1
Install the packages
npm i motion clsx tailwind-merge2
Add util file
lib/util.ts
import { ClassValue, clsx } from "clsx";
import { twMerge } from "tailwind-merge";
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
import { ClassValue, clsx } from "clsx";
import { twMerge } from "tailwind-merge";
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
3
Copy and paste the following code into your project
badge.tsx
"use client";
import { cn } from "@/lib/utils";
import { motion } from "motion/react";
import React from "react";
interface BadgeProps {
children?: React.ReactNode;
variant?: "default" | "secondary" | "destructive" | "outline" | "success" | "warning";
size?: "sm" | "md" | "lg";
rounded?: boolean;
animated?: boolean;
}
const Badge: React.FC<BadgeProps> = ({
children = "Badge",
variant = "default",
size = "md",
rounded = false,
animated = false
}) => {
const variantClasses = {
default: "bg-neutral-800 text-white border-neutral-700",
secondary: "bg-neutral-700 text-neutral-300 border-neutral-600",
destructive: "bg-red-500/10 text-red-400 border-red-500/20",
outline: "bg-transparent text-neutral-400 border-neutral-600",
success: "bg-green-500/10 text-green-400 border-green-500/20",
warning: "bg-yellow-500/10 text-yellow-400 border-yellow-500/20",
};
const sizeClasses = {
sm: "px-2 py-1 text-xs",
md: "px-3 py-1.5 text-sm",
lg: "px-4 py-2 text-base",
};
const badgeContent = (
<span
className={cn(
"inline-flex items-center font-medium border",
variantClasses[variant],
sizeClasses[size],
rounded ? "rounded-full" : "rounded-md",
animated && "transition-all duration-200 hover:scale-105"
)}
>
{children}
</span>
);
if (animated) {
return (
<motion.div
initial={{ opacity: 0, scale: 0.8 }}
animate={{ opacity: 1, scale: 1 }}
whileHover={{ scale: 1.05 }}
transition={{ duration: 0.2 }}
>
{badgeContent}
</motion.div>
);
}
return badgeContent;
};
export default Badge;"use client";
import { cn } from "@/lib/utils";
import { motion } from "motion/react";
import React from "react";
interface BadgeProps {
children?: React.ReactNode;
variant?: "default" | "secondary" | "destructive" | "outline" | "success" | "warning";
size?: "sm" | "md" | "lg";
rounded?: boolean;
animated?: boolean;
}
const Badge: React.FC<BadgeProps> = ({
children = "Badge",
variant = "default",
size = "md",
rounded = false,
animated = false
}) => {
const variantClasses = {
default: "bg-neutral-800 text-white border-neutral-700",
secondary: "bg-neutral-700 text-neutral-300 border-neutral-600",
destructive: "bg-red-500/10 text-red-400 border-red-500/20",
outline: "bg-transparent text-neutral-400 border-neutral-600",
success: "bg-green-500/10 text-green-400 border-green-500/20",
warning: "bg-yellow-500/10 text-yellow-400 border-yellow-500/20",
};
const sizeClasses = {
sm: "px-2 py-1 text-xs",
md: "px-3 py-1.5 text-sm",
lg: "px-4 py-2 text-base",
};
const badgeContent = (
<span
className={cn(
"inline-flex items-center font-medium border",
variantClasses[variant],
sizeClasses[size],
rounded ? "rounded-full" : "rounded-md",
animated && "transition-all duration-200 hover:scale-105"
)}
>
{children}
</span>
);
if (animated) {
return (
<motion.div
initial={{ opacity: 0, scale: 0.8 }}
animate={{ opacity: 1, scale: 1 }}
whileHover={{ scale: 1.05 }}
transition={{ duration: 0.2 }}
>
{badgeContent}
</motion.div>
);
}
return badgeContent;
};
export default Badge;4
Update the import paths to match your project setup
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| children | ReactNode | Badge | Content to display inside the badge. |
| variant | string | default | Badge variant (default, secondary, destructive, outline, success, warning). |
| size | string | md | Badge size (sm, md, lg). |
| rounded | boolean | false | Make the badge fully rounded. |
| animated | boolean | false | Enable hover animations. |