{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "timeframe-tabs", "title": "Timeframe Tabs", "description": "A scrollable, controlled pill-tab row with an animated active-state highlight and a slot for trailing content.", "dependencies": [ "motion" ], "files": [ { "path": "registry/new-york/components/timeframe-tabs/timeframe-tabs.tsx", "type": "registry:component", "content": "\"use client\";\nimport * as React from \"react\";\nimport { AnimatePresence, motion } from \"motion/react\";\nimport { cn } from \"@/lib/utils\";\n\nconst springTransition = { type: \"spring\", stiffness: 500, damping: 40, mass: 0.6 } as const;\n\nexport interface TimeframeTabsProps {\n /** The pills to render, in order. */\n items: string[];\n /** Currently active pill. */\n value: string;\n /** Called with the pill value when the user clicks one. */\n onValueChange: (value: string) => void;\n /** Optional accessible label for the tablist (defaults to \"Tabs\"). */\n label?: string;\n className?: string;\n /**\n * Anything rendered after the pill row — a divider, a dropdown menu,\n * a shadcn Tabs trigger, an icon button, whatever the consumer needs.\n * This is what makes the component reusable beyond just timeframes.\n */\n children?: React.ReactNode;\n}\n\n/**\n * A scrollable row of pill buttons with an animated active-state highlight.\n * Deliberately has no domain knowledge — pass any `items` list and control\n * it like any other controlled input. Trailing content (dividers, menus,\n * extra actions) goes in `children`.\n */\nexport function TimeframeTabs({\n items,\n value,\n onValueChange,\n label = \"Tabs\",\n className,\n children,\n}: TimeframeTabsProps) {\n // Unique per-instance id so multiple TimeframeTabs on one page don't\n // share a layout animation namespace.\n const layoutId = React.useId();\n\n return (\n \n
\n \n {items.map((item) => {\n const isActive = value === item;\n\n return (\n onValueChange(item)}\n className=\"relative shrink-0 whitespace-nowrap rounded-md px-2.5 py-1.5 text-[13px] font-medium outline-none cursor-pointer sm:px-3 sm:text-sm focus-visible:ring-2 focus-visible:ring-ring/50\"\n >\n {isActive && (\n \n )}\n \n {item}\n \n \n );\n })}\n \n
\n\n {children}\n \n );\n}\n\n/** Ready-made vertical divider for use inside a TimeframeTabs' children slot. */\nexport function TimeframeTabsDivider({ className }: { className?: string }) {\n return
;\n}\n\nexport default TimeframeTabs;" } ], "type": "registry:component" }