{ "$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