{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "animated-tabs", "title": "Animated Tabs", "author": "designbycode", "dependencies": [ "framer-motion", "clsx", "tailwind-merge" ], "registryDependencies": [], "files": [ { "path": "resources/js/registry/new-york/components/ui/tabs/animated-tabs.tsx", "content": "'use client';\n\nimport { motion } from 'framer-motion';\nimport type { HTMLAttributes, ReactNode } from 'react';\nimport { useId, useState } from 'react';\n\nimport { cn } from '@/lib/utils';\n\nexport type AnimatedTabsProps = Omit<\n HTMLAttributes,\n 'onChange'\n> & {\n tabs: {\n id: string;\n label: ReactNode;\n content?: ReactNode;\n }[];\n value?: string;\n defaultValue?: string;\n onChange?: (tabId: string) => void;\n tabsClassName?: string;\n tabClassName?: string;\n activeTabClassName?: string;\n inactiveTabClassName?: string;\n indicatorClassName?: string;\n contentClassName?: string;\n showContent?: boolean;\n};\n\nexport function AnimatedTabs({\n tabs,\n value,\n defaultValue,\n onChange,\n className,\n tabsClassName,\n tabClassName,\n activeTabClassName,\n inactiveTabClassName,\n indicatorClassName,\n contentClassName,\n showContent = false,\n ...props\n}: AnimatedTabsProps) {\n const id = useId();\n\n const resolveIndex = (tabId?: string) => {\n if (!tabId) {\n return 0;\n }\n\n const idx = tabs.findIndex((t) => t.id === tabId);\n\n return idx >= 0 ? idx : 0;\n };\n\n const [activeIndex, setActiveIndex] = useState(() =>\n resolveIndex(defaultValue),\n );\n\n const isControlled = value !== undefined;\n const activeTabIndex = isControlled ? resolveIndex(value) : activeIndex;\n const activeTab = tabs[activeTabIndex] ?? tabs[0];\n\n const handleChange = (index: number) => {\n if (!isControlled) {\n setActiveIndex(index);\n }\n\n onChange?.(tabs[index].id);\n };\n\n return (\n
\n \n {tabs.map((tab, index) => (\n handleChange(index)}\n className={cn(\n 'relative rounded-sm px-4 py-2 text-xs font-medium transition focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:outline-none',\n tabClassName,\n activeTabIndex === index\n ? cn('text-foreground', activeTabClassName)\n : cn(\n 'text-muted-foreground hover:text-foreground',\n inactiveTabClassName,\n ),\n )}\n >\n {activeTabIndex === index && (\n \n )}\n {tab.label}\n \n ))}\n
\n\n {showContent && activeTab?.content && (\n \n \n {activeTab.content}\n \n \n )}\n \n );\n}\n", "type": "registry:ui" } ], "meta": { "category": "components", "version": "1.0.0" }, "type": "registry:ui" }