import { useCallback, useId } from 'react' export interface SectionTab { id: T label: string count?: number } interface SectionTabsProps { tabs: SectionTab[] activeTab: T onChange: (tab: T) => void className?: string idPrefix?: string ariaLabel?: string } export function sectionTabPanelProps( idPrefix: string, tabId: T, activeTab: T, ) { return { id: `${idPrefix}-panel-${tabId}`, role: 'tabpanel' as const, 'aria-labelledby': `${idPrefix}-tab-${tabId}`, hidden: activeTab !== tabId, } } export default function SectionTabs({ tabs, activeTab, onChange, className = '', idPrefix, ariaLabel = 'Sections', }: SectionTabsProps) { const generatedId = useId().replace(/:/g, '') const tabListPrefix = idPrefix || generatedId const focusTab = useCallback( (tabId: T) => { const element = document.getElementById(`${tabListPrefix}-tab-${tabId}`) element?.focus() }, [tabListPrefix], ) const handleKeyDown = useCallback( (event: React.KeyboardEvent) => { const currentIndex = tabs.findIndex((tab) => tab.id === activeTab) if (currentIndex < 0) { return } let nextIndex = currentIndex if (event.key === 'ArrowRight') { nextIndex = (currentIndex + 1) % tabs.length } else if (event.key === 'ArrowLeft') { nextIndex = (currentIndex - 1 + tabs.length) % tabs.length } else if (event.key === 'Home') { nextIndex = 0 } else if (event.key === 'End') { nextIndex = tabs.length - 1 } else { return } event.preventDefault() const nextTab = tabs[nextIndex] onChange(nextTab.id) focusTab(nextTab.id) }, [activeTab, focusTab, onChange, tabs], ) return (
{tabs.map((tab) => { const isActive = activeTab === tab.id return ( ) })}
) }