{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "gradient-button-group",
  "type": "registry:ui",
  "description": "Premium layered button group with animated active state, gradient ring accents, and theme toggle underlay",
  "dependencies": [
    "motion",
    "next-themes"
  ],
  "files": [
    {
      "path": "registry/default/ui/gradient-button-group.tsx",
      "content": "\"use client\"\n\nimport { useEffect, useState } from \"react\"\nimport { animate, useMotionValue } from \"motion/react\"\nimport * as motion from \"motion/react-client\"\nimport { useTheme } from \"next-themes\"\n\nimport { cn } from \"@/lib/utils\"\n\n// Theme-aware color configurations\nconst themes = {\n  dark: {\n    bg: \"#111113\",\n    containerBg: \"#141416\",\n    underLayerBg: \"#101012\",\n    borderFrom: \"#0a0a0b\",\n    borderVia: \"#1a1a1c\",\n    borderTo: \"#252527\",\n    wellBg: \"#0a0a0b\",\n    innerRingBg: \"#0c0c0d\",\n    buttonBg: \"#111113\",\n    textActive: \"text-white\",\n    textInactive: \"text-[#6b6b6d] hover:text-zinc-400\",\n    iconColor: \"text-white hover:text-zinc-300\",\n  },\n  light: {\n    bg: \"#f5f5f7\",\n    containerBg: \"#ffffff\",\n    underLayerBg: \"#e8e8ea\",\n    borderFrom: \"#d0d0d5\",\n    borderVia: \"#e5e5e8\",\n    borderTo: \"#f0f0f2\",\n    wellBg: \"#e0e0e3\",\n    innerRingBg: \"#d8d8db\",\n    buttonBg: \"#f0f0f2\",\n    textActive: \"text-zinc-900\",\n    textInactive: \"text-zinc-400 hover:text-zinc-600\",\n    iconColor: \"text-zinc-700 hover:text-zinc-900\",\n  },\n}\n\ninterface NavItem {\n  id: string\n  icon: React.ReactNode\n  label: string\n}\n\nconst navItems: NavItem[] = [\n  {\n    id: \"dashboard\",\n    label: \"Dashboard\",\n    icon: (\n      <svg\n        width=\"24\"\n        height=\"24\"\n        viewBox=\"0 0 24 24\"\n        fill=\"none\"\n        stroke=\"currentColor\"\n        strokeWidth=\"1.5\"\n        aria-hidden=\"true\"\n        focusable=\"false\"\n      >\n        <rect x=\"3\" y=\"3\" width=\"7\" height=\"7\" rx=\"1\" />\n        <rect x=\"14\" y=\"3\" width=\"7\" height=\"7\" rx=\"1\" />\n        <rect x=\"3\" y=\"14\" width=\"7\" height=\"7\" rx=\"1\" />\n        <rect x=\"14\" y=\"14\" width=\"7\" height=\"7\" rx=\"1\" />\n      </svg>\n    ),\n  },\n  {\n    id: \"analytics\",\n    label: \"Analytics\",\n    icon: (\n      <svg\n        width=\"24\"\n        height=\"24\"\n        viewBox=\"0 0 24 24\"\n        fill=\"none\"\n        stroke=\"currentColor\"\n        strokeWidth=\"1.5\"\n        aria-hidden=\"true\"\n        focusable=\"false\"\n      >\n        <line x1=\"8\" y1=\"17\" x2=\"8\" y2=\"11\" />\n        <line x1=\"12\" y1=\"17\" x2=\"12\" y2=\"7\" />\n        <line x1=\"16\" y1=\"17\" x2=\"16\" y2=\"13\" />\n      </svg>\n    ),\n  },\n  {\n    id: \"layers\",\n    label: \"Layers\",\n    icon: (\n      <svg\n        width=\"24\"\n        height=\"24\"\n        viewBox=\"0 0 24 24\"\n        fill=\"none\"\n        stroke=\"currentColor\"\n        strokeWidth=\"1.5\"\n        aria-hidden=\"true\"\n        focusable=\"false\"\n      >\n        <path d=\"M12 2L2 7l10 5 10-5-10-5z\" />\n        <path d=\"M2 17l10 5 10-5\" />\n        <path d=\"M2 12l10 5 10-5\" />\n      </svg>\n    ),\n  },\n  {\n    id: \"storage\",\n    label: \"Storage\",\n    icon: (\n      <svg\n        width=\"24\"\n        height=\"24\"\n        viewBox=\"0 0 24 24\"\n        fill=\"none\"\n        stroke=\"currentColor\"\n        strokeWidth=\"1.5\"\n        aria-hidden=\"true\"\n        focusable=\"false\"\n      >\n        <path d=\"M4 4h16v6H4z\" />\n        <path d=\"M4 14h16v6H4z\" />\n        <circle cx=\"7\" cy=\"7\" r=\"1\" fill=\"currentColor\" />\n        <circle cx=\"7\" cy=\"17\" r=\"1\" fill=\"currentColor\" />\n      </svg>\n    ),\n  },\n]\n\nfunction InnerButtonOverlay({\n  isOverlayActive,\n  isDarkMode,\n}: {\n  isOverlayActive: boolean\n  isDarkMode: boolean\n}) {\n  const overlayProgress = useMotionValue(isOverlayActive ? 1 : 0)\n\n  useEffect(() => {\n    const controls = animate(overlayProgress, isOverlayActive ? 1 : 0, {\n      delay: isOverlayActive ? 0.02 : 0,\n      duration: isOverlayActive ? 0.18 : 0.14,\n      ease: \"easeOut\",\n    })\n\n    return () => controls.stop()\n  }, [isOverlayActive, overlayProgress])\n\n  return (\n    <motion.span\n      initial={false}\n      className=\"absolute inset-0 rounded-[10px]\"\n      animate={\n        isOverlayActive\n          ? {\n              borderWidth: 1,\n              borderColor: isDarkMode\n                ? \"rgba(255,255,255,0.08)\"\n                : \"rgba(0,0,0,0.08)\",\n            }\n          : {\n              borderWidth: 0,\n              borderColor: \"transparent\",\n              boxShadow: \"none\",\n            }\n      }\n      transition={{\n        borderColor: {\n          duration: 0.16,\n          ease: \"easeOut\",\n        },\n      }}\n      style={{\n        borderStyle: \"solid\",\n      }}\n    />\n  )\n}\n\nexport function GradientButtonGroup() {\n  const [activeId, setActiveId] = useState(\"dashboard\")\n  const [overlayReadyId, setOverlayReadyId] = useState<string | null>(\n    \"dashboard\"\n  )\n  const { resolvedTheme, setTheme } = useTheme()\n  const isDarkMode = resolvedTheme !== \"light\"\n\n  const theme = isDarkMode ? themes.dark : themes.light\n\n  return (\n    <div className=\"flex w-full justify-center py-1\">\n      <div className=\"inline-flex min-w-max origin-center scale-[0.72] items-center sm:scale-[0.82] md:scale-[0.9] lg:scale-100\">\n        <div className=\"relative inline-flex items-center\">\n          {/* Background tray layer (recessed) - spans full width including theme toggle */}\n          <div\n            className=\"absolute inset-0 z-0 rounded-[28px] transition-colors duration-300\"\n            style={{\n              background: isDarkMode\n                ? \"linear-gradient(180deg, #141416 0%, #111113 50%, #0e0e10 100%)\"\n                : \"linear-gradient(180deg, #d1d1d6 0%, #cacad0 50%, #c3c3c9 100%)\",\n              boxShadow: isDarkMode\n                ? \"inset 0 2px 8px rgba(0,0,0,0.6), inset 0 1px 2px rgba(0,0,0,0.4), 0 1px 0 rgba(255,255,255,0.04)\"\n                : \"inset 0 2px 6px rgba(0,0,0,0.1), inset 0 0 0 1px rgba(0,0,0,0.08), 0 1px 0 rgba(255,255,255,0.55)\",\n            }}\n          />\n\n          {/* Foreground nav layer (raised) - sits on the left */}\n          <div className=\"relative z-10 flex\">\n            {/* Outer rim/bezel */}\n            <div\n              className=\"bg-muted dark:bg-background absolute -inset-[4px] rounded-[28px] border-[1px] transition-colors duration-300\"\n              style={{\n                borderColor: isDarkMode\n                  ? \"rgba(255,255,255,0.05)\"\n                  : \"rgba(0,0,0,0.08)\",\n              }}\n            />\n\n            {/* Inner container */}\n            <nav\n              className=\"relative inline-flex items-center gap-3 rounded-[24px] p-1.5 transition-colors duration-300\"\n              style={{\n                background: isDarkMode\n                  ? \"linear-gradient(180deg, #1c1c1f 0%, #17171a 52%, #131316 100%)\"\n                  : \"linear-gradient(180deg, #ffffff 0%, #fefeff 52%, #fcfcfe 100%)\",\n                borderTop: isDarkMode\n                  ? \"1px solid rgba(255,255,255,0.1)\"\n                  : \"1px solid rgba(255,255,255,1)\",\n                boxShadow: isDarkMode\n                  ? \"none\"\n                  : \"0 1px 2px rgba(0,0,0,0.04), 0 1px 0 rgba(255,255,255,1)\",\n              }}\n            >\n              {navItems.map((item) => {\n                const isActive = activeId === item.id\n                const isOverlayActive = isActive && overlayReadyId === item.id\n\n                const wellStyle = isDarkMode\n                  ? {\n                      background:\n                        \"linear-gradient(180deg, #0a0a0c 0%, #0e0e10 50%, #0c0c0e 100%)\",\n                      boxShadow:\n                        \"inset 0 2px 6px rgba(0,0,0,0.9), inset 0 0 4px rgba(0,0,0,0.6), 0 1px 0 rgba(255,255,255,0.05)\",\n                    }\n                  : {\n                      boxShadow:\n                        \"inset 0 2px 6px rgba(0,0,0,0.12), inset 0 0 4px rgba(0,0,0,0.06), 0 1px 0 rgba(255,255,255,0.9)\",\n                    }\n\n                const innerGapStyle = isDarkMode\n                  ? {\n                      background: \"#0a0a0d\",\n                      boxShadow:\n                        \"inset 0 1px 3px rgba(0,0,0,0.9), inset 0 0 2px rgba(0,0,0,0.6)\",\n                    }\n                  : {\n                      boxShadow:\n                        \"inset 0 1px 3px rgba(0,0,0,0.18), inset 0 0 2px rgba(0,0,0,0.1)\",\n                    }\n\n                return (\n                  <button\n                    key={item.id}\n                    type=\"button\"\n                    onClick={() => {\n                      if (item.id === activeId) {\n                        return\n                      }\n                      setOverlayReadyId(null)\n                      setActiveId(item.id)\n                    }}\n                    className={cn(\n                      \"group/nav relative flex h-[76px] w-[76px] items-center justify-center rounded-[18px] transition-all duration-300\",\n                      isActive ? theme.textActive : theme.textInactive\n                    )}\n                    aria-label={item.label}\n                    aria-current={isActive ? \"page\" : undefined}\n                  >\n                    {/* Layered inset effect for active state - animated with layoutId */}\n                    {isActive && (\n                      <>\n                        {/* Inset well/channel - creates the recessed groove */}\n                        <motion.span\n                          layoutId=\"active-well\"\n                          className=\"bg-muted absolute inset-0 rounded-[18px] transition-colors duration-300\"\n                          style={wellStyle}\n                          transition={{\n                            type: \"spring\",\n                            stiffness: 400,\n                            damping: 30,\n                          }}\n                        />\n\n                        {/* Gold ring container */}\n                        <motion.span\n                          layoutId=\"active-gold-ring\"\n                          className=\"absolute inset-[3px] overflow-hidden rounded-[15px]\"\n                          onLayoutAnimationComplete={() =>\n                            setOverlayReadyId(item.id)\n                          }\n                          transition={{\n                            type: \"spring\",\n                            stiffness: 400,\n                            damping: 30,\n                          }}\n                        >\n                          {/* Spinning gradient ring */}\n                          <span\n                            className=\"animate-gold-spin absolute inset-[-60%] origin-center will-change-transform\"\n                            style={{\n                              background:\n                                \"conic-gradient(from 220deg, #6FF7CC 0%, #44EBCF 16%, #ADFA1F 33%, #C8FF5A 50%, #89F5A0 66%, #37D8C5 82%, #6FF7CC 100%)\",\n                            }}\n                          />\n                        </motion.span>\n\n                        {/* Inner gap - thin dark channel between gold and button */}\n                        <motion.span\n                          layoutId=\"active-inner-ring\"\n                          className=\"bg-muted absolute inset-[6px] rounded-[12px] transition-colors duration-300\"\n                          style={innerGapStyle}\n                          transition={{\n                            type: \"spring\",\n                            stiffness: 400,\n                            damping: 30,\n                          }}\n                        />\n                      </>\n                    )}\n\n                    {/* Inner button background */}\n                    <motion.span\n                      initial={false}\n                      className={cn(\n                        \"relative z-10 flex items-center justify-center rounded-[10px]\",\n                        isActive\n                          ? \"h-[calc(100%-18px)] w-[calc(100%-18px)]\"\n                          : \"h-full w-full\"\n                      )}\n                      animate={\n                        isActive\n                          ? {\n                              scale: 1,\n                              opacity: 1,\n                            }\n                          : {\n                              scale: 0.985,\n                              opacity: 0.96,\n                            }\n                      }\n                      transition={{\n                        type: \"spring\",\n                        stiffness: 380,\n                        damping: 30,\n                        delay: isActive ? 0.12 : 0,\n                      }}\n                    >\n                      <InnerButtonOverlay\n                        isOverlayActive={isOverlayActive}\n                        isDarkMode={isDarkMode}\n                      />\n                      <span className=\"relative z-10\">{item.icon}</span>\n                    </motion.span>\n                  </button>\n                )\n              })}\n            </nav>\n            {/* Theme toggle - sits in the recessed tray on the right */}\n            <div className=\"relative z-[1] flex items-center px-4\">\n              <button\n                type=\"button\"\n                onClick={() => setTheme(isDarkMode ? \"light\" : \"dark\")}\n                className={cn(\n                  \"relative flex h-[60px] w-[60px] items-center justify-center rounded-[16px] transition-colors\",\n                  theme.iconColor\n                )}\n                aria-label={\n                  isDarkMode ? \"Switch to light mode\" : \"Switch to dark mode\"\n                }\n              >\n                {isDarkMode ? (\n                  <svg\n                    width=\"28\"\n                    height=\"28\"\n                    viewBox=\"0 0 24 24\"\n                    fill=\"none\"\n                    stroke=\"currentColor\"\n                    strokeWidth=\"1.5\"\n                    aria-hidden=\"true\"\n                    focusable=\"false\"\n                  >\n                    <circle cx=\"12\" cy=\"12\" r=\"4\" />\n                    <path d=\"M12 2v2\" />\n                    <path d=\"M12 20v2\" />\n                    <path d=\"M4.93 4.93l1.41 1.41\" />\n                    <path d=\"M17.66 17.66l1.41 1.41\" />\n                    <path d=\"M2 12h2\" />\n                    <path d=\"M20 12h2\" />\n                    <path d=\"M6.34 17.66l-1.41 1.41\" />\n                    <path d=\"M19.07 4.93l-1.41 1.41\" />\n                  </svg>\n                ) : (\n                  <svg\n                    width=\"26\"\n                    height=\"26\"\n                    viewBox=\"0 0 24 24\"\n                    fill=\"none\"\n                    stroke=\"currentColor\"\n                    strokeWidth=\"1.5\"\n                    aria-hidden=\"true\"\n                    focusable=\"false\"\n                  >\n                    <path d=\"M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z\" />\n                  </svg>\n                )}\n              </button>\n            </div>\n          </div>\n        </div>\n      </div>\n      <div className=\"h-0 lg:hidden\" />\n    </div>\n  )\n}\n",
      "type": "registry:ui"
    }
  ]
}