{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "badge-morph", "type": "registry:ui", "title": "Badge Morph", "description": "A morphing status badge that transitions between states with spring-physics micro-interactions.", "dependencies": [ "motion" ], "files": [ { "path": "registry/ruixenui/badge-morph.tsx", "content": "\"use client\";\n\nimport { motion, AnimatePresence } from \"motion/react\";\nimport { cn } from \"@/lib/utils\";\n\ntype Status = \"idle\" | \"loading\" | \"success\" | \"error\";\n\nexport interface BadgeMorphProps {\n status: Status;\n label?: string;\n className?: string;\n}\n\nconst LABELS: Record = {\n idle: \"Ready\",\n loading: \"Deploying\",\n success: \"Live\",\n error: \"Failed\",\n};\n\n// Dynamic Island springs — stiffness 400, damping 30 is the golden ratio\nconst SPRING_PILL = { type: \"spring\" as const, stiffness: 400, damping: 30 };\nconst SPRING_CONTENT = { type: \"spring\" as const, stiffness: 420, damping: 25 };\nconst SPRING_DRAW = { type: \"spring\" as const, stiffness: 300, damping: 15 };\n\n// Icon accent colors — only the icon, not the pill surface\nconst ACCENT: Record = {\n idle: \"\",\n loading: \"\",\n success: \"text-emerald-400 dark:text-emerald-600\",\n error: \"text-red-400 dark:text-red-500\",\n};\n\n// Outer glow per status — radiates from the pill like a backlight\nfunction getGlow(status: Status): string {\n const base = \"0 1px 2px rgba(0,0,0,0.08), 0 1px 3px rgba(0,0,0,0.12)\";\n switch (status) {\n case \"idle\":\n return base;\n case \"loading\":\n return `${base}, 0 0 24px -6px rgba(96,165,250,0.4)`;\n case \"success\":\n return `${base}, 0 0 24px -6px rgba(52,211,153,0.5)`;\n case \"error\":\n return `${base}, 0 0 24px -6px rgba(248,113,113,0.45)`;\n }\n}\n\n/* ─── Icons ───────────────────────────────────────────── */\n\nfunction IdleDot() {\n return (\n \n \n \n \n );\n}\n\nfunction Spinner() {\n return (\n \n \n \n \n );\n}\n\nfunction Check() {\n return (\n \n \n \n );\n}\n\nfunction XMark() {\n return (\n \n \n \n );\n}\n\nconst ICONS: Record React.JSX.Element> = {\n idle: IdleDot,\n loading: Spinner,\n success: Check,\n error: XMark,\n};\n\n/* ─── Component ───────────────────────────────────────── */\n\nexport function BadgeMorph({ status, label, className }: BadgeMorphProps) {\n const displayLabel = label ?? LABELS[status];\n const Icon = ICONS[status];\n\n return (\n \n {/* Status indicator */}\n
\n \n \n \n \n \n
\n\n {/* Label */}\n \n \n {displayLabel}\n \n \n \n );\n}\n", "type": "registry:ui", "target": "components/ruixen/badge-morph.tsx" } ] }