@redocly/theme
Version:
Shared UI components lib
63 lines (53 loc) • 1.9 kB
text/typescript
import { useCallback, useRef, useState } from 'react';
type UseTabsProps = {
initialTab: string;
totalTabs: number;
};
export function useTabs({ initialTab, totalTabs }: UseTabsProps) {
const [activeTab, setActiveTab] = useState(initialTab);
const tabRefs = useRef<(HTMLButtonElement | null)[]>([]);
const setTabRef = useCallback((element: HTMLButtonElement | null, index: number) => {
tabRefs.current[index] = element;
}, []);
const getTabId = useCallback((label: string, index: number) => {
const cleanLabel = label.replace(/\s+/g, '-').toLowerCase();
return `${cleanLabel}-${index}`;
}, []);
const focusTab = (index: number) => {
const currentElement = tabRefs.current[index];
if (currentElement) {
currentElement.focus();
}
};
const onTabSelect = useCallback((index: number) => {
focusTab(index);
const label = tabRefs.current[index]?.getAttribute('data-label');
if (label) setActiveTab(label);
}, []);
const onTabClick = useCallback((label: string) => {
setActiveTab(label);
const tabIndex = tabRefs.current.findIndex((ref) => ref?.getAttribute('data-label') === label);
focusTab(tabIndex);
}, []);
const handleKeyboard = useCallback(
(event: React.KeyboardEvent, index: number) => {
let newIndex = index;
if (event.key === 'ArrowRight') {
newIndex = (index + 1) % totalTabs;
} else if (event.key === 'ArrowLeft') {
newIndex = (index - 1 + totalTabs) % totalTabs;
} else if (event.key === 'Home') {
event.preventDefault();
newIndex = 0;
} else if (event.key === 'End') {
event.preventDefault();
newIndex = totalTabs - 1;
} else {
return;
}
onTabSelect(newIndex);
},
[totalTabs, onTabSelect],
);
return { activeTab, setActiveTab, setTabRef, onTabClick, handleKeyboard, getTabId };
}