Beacon Badge

A premium status badge with a customizable beacon (ping) animation and blur reveal text.

Live Updates
System Alert
New Components
Static Status
TSX
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
"use client"; import { motion } from "motion/react"; import BlurReveal from "@/components/satori-ui/blur-reveal"; export type BeaconColor = | "green" | "blue" | "purple" | "yellow" | "pink" | "orange" | "red" | "white" | "black"; export type RevealDirection = "up" | "down" | "left" | "right" | "none"; export type BorderSize = "sm" | "md" | "lg" | "xl" | "full"; export interface BeaconBadgeProps { label?: string; className?: string; beconColor?: BeaconColor; beconPulses?: boolean; speedReveal?: number; revealDirection?: RevealDirection; staticTheme?: "dark" | "light"; border?: BorderSize; } const colorMap: Record<BeaconColor, string> = { green: "bg-emerald-500 dark:bg-emerald-400", blue: "bg-sky-500 dark:bg-sky-400", purple: "bg-purple-500 dark:bg-purple-400", yellow: "bg-yellow-500 dark:bg-yellow-400", pink: "bg-pink-500 dark:bg-pink-400", orange: "bg-orange-500 dark:bg-orange-400", red: "bg-red-500 dark:bg-red-400", white: "bg-zinc-200 dark:bg-white", black: "bg-black dark:bg-zinc-800", }; const borderMap: Record<BorderSize, string> = { sm: "rounded-sm", md: "rounded-md", lg: "rounded-lg", xl: "rounded-xl", full: "rounded-full", }; const directionMap: Record< RevealDirection, { initial: { x: number; y: number }; animate: { x: number; y: number } } > = { up: { initial: { x: 0, y: 20 }, animate: { x: 0, y: 0 } }, down: { initial: { x: 0, y: -20 }, animate: { x: 0, y: 0 } }, left: { initial: { x: 20, y: 0 }, animate: { x: 0, y: 0 } }, right: { initial: { x: -20, y: 0 }, animate: { x: 0, y: 0 } }, none: { initial: { x: 0, y: 0 }, animate: { x: 0, y: 0 } }, }; const BeaconBadge = ({ label = "50+ Components Available", className, beconColor = "blue", beconPulses = true, speedReveal = 3, revealDirection = "up", staticTheme, border = "full", }: BeaconBadgeProps) => { const colorClass = colorMap[beconColor] || colorMap.blue; const { initial, animate } = directionMap[revealDirection]; const themeClasses = { container: staticTheme === "dark" ? "border-white/[0.08] bg-white/[0.03]" : staticTheme === "light" ? "border-black/[0.08] bg-black/[0.03]" : "border-black/[0.08] bg-black/[0.03] dark:border-white/[0.08] dark:bg-white/[0.03]", text: staticTheme === "dark" ? "text-white/60" : staticTheme === "light" ? "text-black/60" : "text-black/60 dark:text-white/60", beacon: staticTheme === "dark" ? (colorClass.split(" ").pop() || "").replace("dark:", "") : staticTheme === "light" ? colorClass.split(" ")[0] : colorClass, }; return ( <motion.div initial={{ opacity: 0, ...initial }} animate={{ opacity: 1, ...animate }} transition={{ duration: 0.5, ease: "easeOut", }} className={`inline-flex items-center gap-2 px-3 py-1.5 border backdrop-blur-sm ${borderMap[border]} ${themeClasses.container} ${className || ""}`} > <span className="relative flex h-1.5 w-1.5"> {beconPulses && ( <span className={`animate-ping absolute inline-flex h-full w-full rounded-full ${themeClasses.beacon} opacity-75`} /> )} <span className={`relative inline-flex rounded-full h-1.5 w-1.5 ${themeClasses.beacon}`} /> </span> <BlurReveal className={`text-[11px] tracking-widest uppercase font-medium ${themeClasses.text}`} speedReveal={speedReveal} > {label} </BlurReveal> </motion.div> ); }; export default BeaconBadge;

Installation

pnpm dlx shadcn@latest add @satoriui/beacon-badge