{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "headless-tabs", "type": "registry:ui", "title": "Headless Tabs", "description": "Easily create accessible, fully customizable tab interfaces, with robust focus management and keyboard navigation support.", "dependencies": [ "motion", "@headlessui/react" ], "registryDependencies": [ "https://animate-ui.com/r/motion-highlight" ], "files": [ { "path": "registry/headless/tabs/index.tsx", "content": "'use client';\n\nimport * as React from 'react';\nimport { motion, type Transition } from 'motion/react';\nimport {\n TabGroup as TabGroupPrimitive,\n TabList as TabListPrimitive,\n Tab as TabPrimitive,\n TabPanels as TabPanelsPrimitive,\n TabPanel as TabPanelPrimitive,\n type TabGroupProps as TabGroupPrimitiveProps,\n type TabListProps as TabListPrimitiveProps,\n type TabProps as TabPrimitiveProps,\n type TabPanelsProps as TabPanelsPrimitiveProps,\n type TabPanelProps as TabPanelPrimitiveProps,\n} from '@headlessui/react';\n\nimport { cn } from '@/lib/utils';\nimport {\n MotionHighlight,\n MotionHighlightItem,\n} from '@/components/animate-ui/effects/motion-highlight';\n\ntype TabGroupProps =\n TabGroupPrimitiveProps & {\n className?: string;\n as?: TTag;\n };\n\nfunction TabGroup({\n className,\n ...props\n}: TabGroupProps) {\n return (\n \n );\n}\n\ntype TabListProps =\n TabListPrimitiveProps & {\n as?: TTag;\n className?: string;\n activeClassName?: string;\n transition?: Transition;\n };\n\nfunction TabList({\n children,\n className,\n activeClassName,\n transition = {\n type: 'spring',\n stiffness: 200,\n damping: 25,\n },\n ...props\n}: TabListProps) {\n return (\n \n {(bag) => (\n \n {typeof children === 'function' ? children(bag) : children}\n \n )}\n \n );\n}\n\ntype TabProps = Omit<\n TabPrimitiveProps,\n 'children'\n> &\n Required, 'children'>> & {\n index: number;\n className?: string;\n as?: TTag;\n };\n\nfunction Tab(props: TabProps) {\n const { children, className, index, as = 'button', ...rest } = props;\n\n return (\n \n \n {children}\n \n \n );\n}\n\ntype TabPanelProps = Omit<\n TabPanelPrimitiveProps,\n 'transition'\n> & {\n children: React.ReactNode;\n className?: string;\n as?: TTag;\n transition?: Transition;\n};\n\nfunction TabPanel(\n props: TabPanelProps,\n) {\n const {\n className,\n as = motion.div,\n transition = {\n duration: 0.5,\n ease: 'easeInOut',\n },\n ...rest\n } = props;\n\n return (\n \n );\n}\n\ntype TabPanelsProps = Omit<\n TabPanelsPrimitiveProps,\n 'transition'\n> & {\n className?: string;\n as?: TTag;\n transition?: Transition;\n};\n\nfunction TabPanels(\n props: TabPanelsProps,\n) {\n const {\n children,\n className,\n as = motion.div,\n transition = { type: 'spring', stiffness: 200, damping: 25 },\n ...rest\n } = props;\n const containerRef = React.useRef(null);\n\n const [height, setHeight] = React.useState(0);\n\n React.useEffect(() => {\n if (!containerRef.current) return;\n\n const resizeObserver = new ResizeObserver((entries) => {\n const newHeight = entries[0]?.contentRect.height ?? 0;\n requestAnimationFrame(() => {\n setHeight(newHeight);\n });\n });\n\n resizeObserver.observe(containerRef.current);\n\n return () => {\n resizeObserver.disconnect();\n };\n }, [children]);\n\n React.useLayoutEffect(() => {\n if (containerRef.current) {\n const initialHeight = containerRef.current.getBoundingClientRect().height;\n setHeight(initialHeight);\n }\n }, [children]);\n\n return (\n \n
{children}
\n \n );\n}\n\nexport {\n TabGroup,\n TabList,\n Tab,\n TabPanel,\n TabPanels,\n type TabGroupProps,\n type TabListProps,\n type TabProps,\n type TabPanelProps,\n type TabPanelsProps,\n};\n", "type": "registry:ui", "target": "components/animate-ui/headless/tabs.tsx" } ] }