{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "members-growth-chart",
  "title": "Members Growth Chart",
  "description": "Sleek analytics chart with tabbed segments and gradient area visualization.",
  "dependencies": [
    "recharts",
    "motion",
    "@hugeicons/react",
    "@hugeicons/core-free-icons"
  ],
  "registryDependencies": [],
  "files": [
    {
      "path": "registry/default/ui/members-growth-chart.tsx",
      "content": "\"use client\";\r\nimport { useState } from \"react\";\r\nimport {\r\n  Area,\r\n  AreaChart,\r\n  ResponsiveContainer,\r\n  Tooltip,\r\n  TooltipContentProps,\r\n  XAxis,\r\n} from \"recharts\";\r\nimport { motion } from \"motion/react\";\r\nimport { cn } from \"@/lib/utils\";\r\nimport { MembersGrowthData, TabKey } from \"./members-growth-chart-data\";\r\nimport { useId } from \"react\";\r\n\r\ntype MembersGrowthChartProps = {\r\n  data: Record<TabKey, MembersGrowthData[]>;\r\n  date?: string;\r\n  greeting?: string;\r\n  avatar: string;\r\n};\r\n\r\nexport const MembersGrowthChart = ({\r\n  data,\r\n  date = \"March 23, 2026\",\r\n  greeting = \"Good Morning\",\r\n  avatar,\r\n}: MembersGrowthChartProps) => {\r\n  const tabs = Object.keys(data) as TabKey[];\r\n  const [active, setActive] = useState<TabKey>(tabs[0]);\r\n\r\n  const currentData = data[active];\r\n  const totalMembers = currentData.reduce((sum, item) => sum + item.members, 0);\r\n\r\n  const layoutScope = useId();\r\n\r\n  return (\r\n    <div className=\"w-90  rounded-4xl bg-linear-to-b from-neutral-100 to-neutral-300 relative p-6 shadow-xs\">\r\n      <div className=\"flex flex-col gap-5\">\r\n        <ChartHeader date={date} greeting={greeting} avatar={avatar} />\r\n        <div className=\"rounded-xl bg-linear-to-b from-white via-neutral-200 to-transparent p-[1.5px]\">\r\n          <div className=\"rounded-xl bg-linear-to-b from-neutral-100 to-neutral-300 p-3 shadow-[inset_0_1px_5px_rgba(0,0,0,0.06),inset_0_-6px_12px_rgba(255,255,255,0.55)] flex flex-col gap-2.5\">\r\n            <MembersTab\r\n              tabs={tabs}\r\n              active={active}\r\n              setActive={setActive}\r\n              totalMembers={totalMembers}\r\n              layoutScope={layoutScope}\r\n            />\r\n            <CardText />\r\n            <div className=\"w-full h-20\">\r\n              <ResponsiveContainer width=\"100%\" height=\"100%\">\r\n                <AreaChart data={currentData} margin={{ left: 12, right: 12 }}>\r\n                  <Area\r\n                    type=\"monotone\"\r\n                    dataKey=\"members\"\r\n                    stroke=\"url(#membersStrokeGradient)\"\r\n                    fill=\"url(#membersFillGradient)\"\r\n                    strokeWidth={2}\r\n                    strokeLinecap=\"round\"\r\n                    strokeLinejoin=\"round\"\r\n                    activeDot={{\r\n                      r: 4,\r\n                      fill: \"url(#membersDotGradient)\",\r\n                      stroke: \"#ffffff\",\r\n                      strokeWidth: 2,\r\n                    }}\r\n                  />\r\n                  <XAxis\r\n                    dataKey=\"month\"\r\n                    tickLine={false}\r\n                    axisLine={false}\r\n                    tickMargin={6}\r\n                    tick={{\r\n                      fontSize: 11,\r\n                      fill: \"#37353E\",\r\n                      fontWeight: \"400\",\r\n                      letterSpacing: \"0.08em\",\r\n                    }}\r\n                  />\r\n                  <Tooltip\r\n                    content={CustomToolTip}\r\n                    cursor={{ stroke: \"#ffffff\", strokeWidth: 1.5 }}\r\n                  />\r\n                  <defs>\r\n                    <linearGradient\r\n                      id=\"membersStrokeGradient\"\r\n                      x1=\"0\"\r\n                      y1=\"0\"\r\n                      x2=\"1\"\r\n                      y2=\"0\"\r\n                    >\r\n                      <stop offset=\"0%\" stopColor=\"#FAAC68\" />\r\n                      <stop offset=\"33%\" stopColor=\"#FA6868\" />\r\n                      <stop offset=\"66%\" stopColor=\"#FB88B4\" />\r\n                      <stop offset=\"100%\" stopColor=\"#5272F2\" />\r\n                    </linearGradient>\r\n                    <linearGradient\r\n                      id=\"membersFillGradient\"\r\n                      x1=\"0\"\r\n                      y1=\"0\"\r\n                      x2=\"0\"\r\n                      y2=\"1\"\r\n                    >\r\n                      <stop\r\n                        offset=\"0%\"\r\n                        stopColor=\"#FA6868\"\r\n                        stopOpacity=\"0.65\"\r\n                      />\r\n\r\n                      <stop\r\n                        offset=\"40%\"\r\n                        stopColor=\"#FA6868\"\r\n                        stopOpacity=\"0.25\"\r\n                      />\r\n\r\n                      <stop offset=\"100%\" stopColor=\"#FA6868\" stopOpacity=\"0\" />\r\n                    </linearGradient>\r\n                    <radialGradient\r\n                      id=\"membersDotGradient\"\r\n                      cx=\"50%\"\r\n                      cy=\"50%\"\r\n                      r=\"50%\"\r\n                    >\r\n                      <stop offset=\"0%\" stopColor=\"#37353E\" />\r\n                      <stop offset=\"100%\" stopColor=\"#262626\" />\r\n                    </radialGradient>\r\n                  </defs>\r\n                </AreaChart>\r\n              </ResponsiveContainer>\r\n            </div>\r\n          </div>\r\n        </div>\r\n      </div>\r\n    </div>\r\n  );\r\n};\r\n\r\nconst CustomToolTip = ({\r\n  active,\r\n  payload,\r\n  label,\r\n}: TooltipContentProps) => {\r\n  if (!active || !payload?.length || !label) return null;\r\n  return (\r\n    <div className=\"bg-linear-to-b from-neutral-900 to-neutral-800 text-white text-xs px-2 py-1 rounded-full\">\r\n      {payload.map((entry) => {\r\n        return <span key={String(entry.dataKey)}>{entry.value}</span>;\r\n      })}\r\n    </div>\r\n  );\r\n};\r\n\r\ntype MembersTabProps = {\r\n  tabs: TabKey[];\r\n  active: TabKey;\r\n  setActive: React.Dispatch<React.SetStateAction<TabKey>>;\r\n  totalMembers: number;\r\n  layoutScope: string;\r\n};\r\nconst MembersTab = ({\r\n  tabs,\r\n  active,\r\n  setActive,\r\n  totalMembers,\r\n  layoutScope,\r\n}: MembersTabProps) => {\r\n  const formattedTotalMembers = totalMembers.toLocaleString();\r\n  const digits = formattedTotalMembers.split(\"\");\r\n  return (\r\n    <div className=\"flex\">\r\n      <div className=\"rounded-lg bg-neutral-200 flex-1 text-[11px] flex items-center justify-between px-1.5 font-semibold text-neutral-400 gap-1 shadow-[inset_0_-2px_6px_rgba(0,0,0,0.08),inset_0_1px_3px_rgba(255,255,255,0.5)]\">\r\n        {tabs.map((tab) => {\r\n          const isActive = active === tab;\r\n          return (\r\n            <button\r\n              key={tab}\r\n              onClick={() => setActive(tab)}\r\n              className=\"relative px-1.5 py-1.5 rounded-md cursor-pointer\"\r\n            >\r\n              {isActive && (\r\n                <motion.div\r\n                  layoutId={`membersActiveTab-${layoutScope}`}\r\n                  transition={{ type: \"spring\", bounce: 0.3, duration: 0.6 }}\r\n                  className=\"absolute inset-0 bg-white rounded-md shadow-xs\"\r\n                />\r\n              )}\r\n              <span\r\n                className={cn(\r\n                  \"relative z-10 transition-colors duration-100\",\r\n                  isActive ? \"text-neutral-800\" : \"text-neutral-400\",\r\n                )}\r\n              >\r\n                {tab}\r\n              </span>\r\n            </button>\r\n          );\r\n        })}\r\n      </div>\r\n      <div className=\"flex-1 flex justify-end flex-col text-end\">\r\n        <span className=\"font-semibold flex justify-end overflow-hidden\">\r\n          {digits.map((digit, index) => {\r\n            return (\r\n              <motion.span\r\n                key={index + digit}\r\n                initial={{ y: 30, opacity: 0, filter: \"blur(3px)\" }}\r\n                animate={{ y: 0, opacity: 1, filter: \"blur(0px)\" }}\r\n                transition={{\r\n                  duration: 0.6,\r\n                  delay: index * 0.05,\r\n                  ease: \"easeOut\",\r\n                  bounce: 0.3,\r\n                }}\r\n                className=\"inline-block text-neutral-800 text-[16px]\"\r\n              >\r\n                {digit}\r\n              </motion.span>\r\n            );\r\n          })}\r\n        </span>\r\n        <span className=\"text-[11px] text-muted-foreground\">Total Members</span>\r\n      </div>\r\n    </div>\r\n  );\r\n};\r\n\r\nconst ChartHeader = ({\r\n  date,\r\n  greeting,\r\n  avatar,\r\n}: {\r\n  date: string;\r\n  greeting: string;\r\n  avatar: string;\r\n}) => {\r\n  return (\r\n    <div className=\"flex justify-between items-center\">\r\n      <div className=\"flex flex-col\">\r\n        <span className=\"text-muted-foreground text-[10px] font-semibold\">\r\n          {date}\r\n        </span>\r\n        <span className=\"font-semibold text-neutral-800 text-[16px]\">{greeting}</span>\r\n      </div>\r\n      <div>\r\n        <img\r\n          src={avatar}\r\n          alt=\"women\"\r\n          onError={(e) => {\r\n            e.currentTarget.src = \"/mock/women-7.jpeg\";\r\n          }}\r\n          className=\"aspect-square w-10 h-10 object-cover rounded-full\"\r\n        />\r\n      </div>\r\n    </div>\r\n  );\r\n};\r\n\r\nconst CardText = () => {\r\n  return (\r\n    <div className=\"flex flex-col\">\r\n      <span className=\"text-sm font-medium text-neutral-900\">Members</span>\r\n      <p className=\"text-[11px] text-neutral-400 w-60 font-medium text-balance\">\r\n        Growth and engagement overview\r\n      </p>\r\n    </div>\r\n  );\r\n};",
      "type": "registry:component"
    },
    {
      "path": "registry/default/ui/members-growth-chart-data.ts",
      "content": "// Example data for the MembersGrowthChart.\r\n// Replace this with your real analytics data.\r\n\r\nexport type MembersGrowthData = {\r\n  month: string;\r\n  members: number;\r\n};\r\n\r\nexport type TabKey = \"All\" | \"Active\" | \"Enrolled\";\r\n\r\nexport const membersData: Record<TabKey, MembersGrowthData[]> = {\r\n  All: [\r\n    { month: \"Jan\", members: 1200 },\r\n    { month: \"Feb\", members: 1540 },\r\n    { month: \"Mar\", members: 1580 },\r\n    { month: \"Apr\", members: 1565 },\r\n    { month: \"May\", members: 1620 },\r\n    { month: \"Jun\", members: 1680 },\r\n    { month: \"Jul\", members: 1520 },\r\n  ],\r\n  Active: [\r\n    { month: \"Jan\", members: 420 },\r\n    { month: \"Feb\", members: 460 },\r\n    { month: \"Mar\", members: 480 },\r\n    { month: \"Apr\", members: 270 },\r\n    { month: \"May\", members: 520 },\r\n    { month: \"Jun\", members: 160 },\r\n    { month: \"Jul\", members: 400 },\r\n  ],\r\n  Enrolled: [\r\n    { month: \"Jan\", members: 480 },\r\n    { month: \"Feb\", members: 505 },\r\n    { month: \"Mar\", members: 540 },\r\n    { month: \"Apr\", members: 525 },\r\n    { month: \"May\", members: 590 },\r\n    { month: \"Jun\", members: 632 },\r\n    { month: \"Jul\", members: 670 },\r\n  ],\r\n};",
      "type": "registry:component"
    }
  ],
  "type": "registry:component"
}