import { useId, useRef, type KeyboardEvent } from 'react'; import clsx from 'clsx'; import Icon from '../Icon/index.js'; import styles from '../Segmented/styles.module.css'; import tabStyles from './styles.module.css'; export interface TabItem { value: T; label: string; icon?: string; id?: string; panelId?: string; disabled?: boolean; } export interface TabsProps { value: T; items: TabItem[]; onChange: (value: T) => void; ariaLabel: string; size?: 'sm' | 'md'; orientation?: 'horizontal' | 'vertical'; className?: string; } export default function Tabs({ value, items, onChange, ariaLabel, size = 'md', orientation = 'horizontal', className, }: TabsProps) { const generatedId = useId(); const refs = useRef<(HTMLButtonElement | null)[]>([]); const enabled = items .map((item, index) => (item.disabled ? -1 : index)) .filter((index) => index >= 0); const selected = items.findIndex((item) => !item.disabled && item.value === value); const focusIndex = selected < 0 ? enabled[0] : selected; const moveFocus = (event: KeyboardEvent, index: number) => { const [previous, next] = orientation === 'horizontal' ? ['ArrowLeft', 'ArrowRight'] : ['ArrowUp', 'ArrowDown']; if (![previous, next, 'Home', 'End'].includes(event.key) || enabled.length === 0) return; event.preventDefault(); const current = enabled.indexOf(index); const target = event.key === 'Home' ? enabled[0] : event.key === 'End' ? enabled[enabled.length - 1] : enabled[(current + (event.key === next ? 1 : -1) + enabled.length) % enabled.length]; onChange(items[target].value); refs.current[target]?.focus(); }; return (
{items.map((item, index) => ( ))}
); }