in src/theme/Tabs/index.tsx [19:106]
function TabList({
className,
block,
selectedValue,
selectValue,
tabValues,
}: Props & ReturnType<typeof useTabs>) {
const tabRefs: (HTMLLIElement | null)[] = [];
const {blockElementScrollPositionUntilNextRender} =
useScrollPositionBlocker();
const handleTabChange = (
event:
| React.FocusEvent<HTMLLIElement>
| React.MouseEvent<HTMLLIElement>
| React.KeyboardEvent<HTMLLIElement>,
) => {
const newTab = event.currentTarget;
const newTabIndex = tabRefs.indexOf(newTab);
const newTabValue = tabValues[newTabIndex]!.value;
if (newTabValue !== selectedValue) {
blockElementScrollPositionUntilNextRender(newTab);
selectValue(newTabValue);
}
};
const handleKeydown = (event: React.KeyboardEvent<HTMLLIElement>) => {
let focusElement: HTMLLIElement | null = null;
switch (event.key) {
case 'Enter': {
handleTabChange(event);
break;
}
case 'ArrowRight': {
const nextTab = tabRefs.indexOf(event.currentTarget) + 1;
focusElement = tabRefs[nextTab] ?? tabRefs[0]!;
break;
}
case 'ArrowLeft': {
const prevTab = tabRefs.indexOf(event.currentTarget) - 1;
focusElement = tabRefs[prevTab] ?? tabRefs[tabRefs.length - 1]!;
break;
}
default:
break;
}
focusElement?.focus();
};
return (
<ul
role="tablist"
aria-orientation="horizontal"
className={clsx(
'tabs',
{
'tabs--block': block,
},
className,
)}>
{tabValues.map(({value, label, attributes}) => (
<li
// TODO extract TabListItem
role="tab"
tabIndex={selectedValue === value ? 0 : -1}
aria-selected={selectedValue === value}
key={value}
ref={(tabControl) => tabRefs.push(tabControl)}
onKeyDown={handleKeydown}
onClick={handleTabChange}
{...attributes}
className={clsx(
'tabs__item',
styles.tabItem,
attributes?.className as string,
{
'tabs__item--active': selectedValue === value,
},
)}>
{label ?? value}
</li>
))}
</ul>
);
}