import { useEffect, useLayoutEffect, useRef, useState } from 'react'; import { useNavigate } from 'react-router-dom'; import type { AppTabConfig, TabId } from '../../router/tabs'; import { appTabs } from '../../router/tabs'; interface TabNavProps { activeTab: AppTabConfig; } interface IndicatorStyle { opacity: number; transform: string; width: number; } const reducedMotionQuery = '(prefers-reduced-motion: reduce)'; export function TabNav({ activeTab }: TabNavProps) { const navigate = useNavigate(); const trackRef = useRef(null); const buttonRefs = useRef>({ perception: null, docs: null, compliance: null, status: null, rag: null, }); const [indicatorStyle, setIndicatorStyle] = useState({ opacity: 0, transform: 'translateX(0px)', width: 0, }); const [reducedMotion, setReducedMotion] = useState(false); const handleValueChange = (value: string) => { const nextTab = appTabs.find((tab) => tab.id === value); if (nextTab && nextTab.path !== activeTab.path) { navigate(nextTab.path); } }; useEffect(() => { const mediaQuery = window.matchMedia(reducedMotionQuery); const updateMotionPreference = () => { setReducedMotion(mediaQuery.matches); }; updateMotionPreference(); mediaQuery.addEventListener('change', updateMotionPreference); return () => { mediaQuery.removeEventListener('change', updateMotionPreference); }; }, []); useLayoutEffect(() => { const updateIndicator = () => { const trackNode = trackRef.current; const activeNode = buttonRefs.current[activeTab.id]; if (!trackNode || !activeNode) { return; } const trackRect = trackNode.getBoundingClientRect(); const activeRect = activeNode.getBoundingClientRect(); setIndicatorStyle({ opacity: 1, transform: `translateX(${activeRect.left - trackRect.left}px)`, width: activeRect.width, }); }; updateIndicator(); window.addEventListener('resize', updateIndicator); return () => { window.removeEventListener('resize', updateIndicator); }; }, [activeTab.id]); return ( ); }