{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "tabs", "type": "registry:ui", "title": "Tabs", "description": "A customizable tabs component", "dependencies": [ "@base-ui/react", "clsx", "tailwind-merge" ], "registryDependencies": [ "classes" ], "files": [ { "path": "src/registry/pure-ui/ui/tabs/index.tsx", "content": "\"use client\";\r\n\r\nimport { createContext, useContext, useEffect, useRef, useState } from \"react\";\r\nimport { Tabs as TabsPrimitive } from \"@base-ui/react/tabs\";\r\n\r\nimport { cn } from \"@/lib/classes\";\r\n\r\ntype TabsVariant = \"segmented\" | \"underline\" | \"card\";\r\n\r\nfunction isValidVariant(variant: TabsVariant): variant is TabsVariant {\r\n return (\r\n variant === \"segmented\" || variant === \"underline\" || variant === \"card\"\r\n );\r\n}\r\n\r\ninterface TabsContextType {\r\n variant?: TabsVariant;\r\n}\r\n\r\nconst TabsContext = createContext({\r\n variant: \"segmented\",\r\n});\r\n\r\nfunction useTabs() {\r\n const context = useContext(TabsContext);\r\n if (!context) {\r\n throw new Error(\"useTabs must be used within a Tabs component\");\r\n }\r\n return context;\r\n}\r\n\r\ninterface TabsProps extends TabsPrimitive.Root.Props {\r\n variant?: TabsVariant;\r\n}\r\n\r\nfunction Tabs({ className, variant = \"segmented\", ...props }: TabsProps) {\r\n const finalVariant = isValidVariant(variant) ? variant : \"segmented\";\r\n\r\n return (\r\n \r\n \r\n \r\n );\r\n}\r\n\r\ninterface TabsListProps extends TabsPrimitive.List.Props {}\r\n\r\nfunction TabsList({ className, children, ...props }: TabsListProps) {\r\n const { variant } = useTabs();\r\n\r\n return (\r\n \r\n {children}\r\n \r\n \r\n );\r\n}\r\n\r\ninterface TabsTriggerProps extends TabsPrimitive.Tab.Props {}\r\n\r\nfunction TabsTrigger({ className, ...props }: TabsTriggerProps) {\r\n const { variant } = useTabs();\r\n\r\n return (\r\n \r\n );\r\n}\r\n\r\ninterface TabsPanelWrapperProps {\r\n children: React.ReactNode;\r\n}\r\n\r\nfunction TabsPanelsWrapper({ children }: TabsPanelWrapperProps) {\r\n const contentContainerRef = useRef(null);\r\n const [height, setHeight] = useState(0);\r\n\r\n useEffect(() => {\r\n const resizeObserver = new ResizeObserver((entries) => {\r\n for (const entry of entries) {\r\n const rect = entry.target.getBoundingClientRect();\r\n\r\n setHeight(rect.height);\r\n }\r\n });\r\n\r\n if (contentContainerRef.current) {\r\n resizeObserver.observe(contentContainerRef.current);\r\n }\r\n\r\n return () => {\r\n if (contentContainerRef.current) {\r\n resizeObserver.disconnect();\r\n }\r\n };\r\n }, []);\r\n\r\n return (\r\n \r\n
\r\n {children}\r\n
\r\n \r\n );\r\n}\r\n\r\ninterface TabsPanelProps extends TabsPrimitive.Panel.Props {}\r\n\r\nfunction TabsPanel({ className, ...props }: TabsPanelProps) {\r\n return (\r\n \r\n );\r\n}\r\n\r\nexport { Tabs, TabsList, TabsTrigger, TabsPanelsWrapper, TabsPanel };\r\n", "type": "registry:ui", "target": "components/ui/tabs.tsx" } ] }