'use client'; import * as React from 'react'; import { cn } from '@/lib/utils'; interface TabsContextValue { value: string; onValueChange: (value: string) => void; baseId: string; registerTab: (value: string) => void; unregisterTab: (value: string) => void; tabs: string[]; } const TabsContext = React.createContext(null); function useTabs() { const context = React.useContext(TabsContext); if (!context) throw new Error('Tabs components must be used within '); return context; } interface TabsProps extends React.HTMLAttributes { value: string; onValueChange: (value: string) => void; } let tabsCounter = 0; function Tabs({ value, onValueChange, className, ...props }: TabsProps) { const [baseId] = React.useState(() => `tabs-${++tabsCounter}`); const [tabs, setTabs] = React.useState([]); const registerTab = React.useCallback((tabValue: string) => { setTabs((prev) => (prev.includes(tabValue) ? prev : [...prev, tabValue])); }, []); const unregisterTab = React.useCallback((tabValue: string) => { setTabs((prev) => prev.filter((t) => t !== tabValue)); }, []); return (
); } const TabsList = React.forwardRef>( ({ className, ...props }, ref) => { const { tabs, value, onValueChange } = useTabs(); const handleKeyDown = (e: React.KeyboardEvent) => { const currentIndex = tabs.indexOf(value); if (currentIndex === -1) return; let nextIndex: number | null = null; switch (e.key) { case 'ArrowRight': nextIndex = (currentIndex + 1) % tabs.length; break; case 'ArrowLeft': nextIndex = (currentIndex - 1 + tabs.length) % tabs.length; break; case 'Home': nextIndex = 0; break; case 'End': nextIndex = tabs.length - 1; break; default: return; } e.preventDefault(); const next = tabs[nextIndex]; if (next) onValueChange(next); }; return (
); }, ); TabsList.displayName = 'TabsList'; interface TabsTriggerProps extends React.ButtonHTMLAttributes { value: string; } const TabsTrigger = React.forwardRef( ({ className, value, ...props }, ref) => { const { value: selectedValue, onValueChange, baseId, registerTab, unregisterTab } = useTabs(); const isSelected = selectedValue === value; const internalRef = React.useRef(null); React.useEffect(() => { registerTab(value); return () => unregisterTab(value); }, [value, registerTab, unregisterTab]); // Focus the newly selected tab React.useEffect(() => { if (isSelected && internalRef.current) { internalRef.current.focus(); } }, [isSelected]); return (