'use client'; import { classNames } from '@/lib/components/classNames'; import { useId, useRef, useState, type KeyboardEvent, type ReactNode } from 'react'; import styles from './Tabs.module.css'; export interface TabItem { id: string; label: string; content: ReactNode; disabled?: boolean; } interface TabsProps { items: TabItem[]; label: string; defaultActiveId?: string; activation?: 'automatic' | 'manual'; className?: string; } export function Tabs({ items, label, defaultActiveId, activation = 'automatic', className, }: TabsProps) { const available = items.filter((item) => !item.disabled); const initial = defaultActiveId && available.some((item) => item.id === defaultActiveId) ? defaultActiveId : (available[0]?.id ?? ''); const [activeId, setActiveId] = useState(initial); const [focusedId, setFocusedId] = useState(initial); const refs = useRef(new Map()); const prefix = useId().replaceAll(':', ''); const focusByOffset = (currentId: string, offset: number) => { const currentIndex = available.findIndex((item) => item.id === currentId); if (currentIndex < 0 || available.length === 0) return; const next = available[(currentIndex + offset + available.length) % available.length]; if (!next) return; setFocusedId(next.id); if (activation === 'automatic') setActiveId(next.id); refs.current.get(next.id)?.focus(); }; const handleKeyDown = (event: KeyboardEvent, id: string) => { if (event.key === 'ArrowRight') { event.preventDefault(); focusByOffset(id, document.documentElement.dir === 'rtl' ? -1 : 1); } else if (event.key === 'ArrowLeft') { event.preventDefault(); focusByOffset(id, document.documentElement.dir === 'rtl' ? 1 : -1); } else if (event.key === 'Home') { event.preventDefault(); const first = available[0]; if (first) focusByOffset(first.id, 0); } else if (event.key === 'End') { event.preventDefault(); const last = available.at(-1); if (last) focusByOffset(last.id, 0); } else if ((event.key === 'Enter' || event.key === ' ') && activation === 'manual') { event.preventDefault(); setActiveId(id); } }; return (
{items.map((item) => { const selected = item.id === activeId; return ( ); })}
{items.map((item) => ( ))}
); }