refactor(v2): update tabs to follow WAI-ARIA (#4193)

This commit is contained in:
Alexey Pyltsyn 2021-02-08 20:46:50 +03:00 committed by GitHub
parent fc071b0c2f
commit 00c1e8d852
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -23,10 +23,10 @@ function Tabs(props: Props): JSX.Element {
const {lazy, block, defaultValue, values, groupId, className} = props; const {lazy, block, defaultValue, values, groupId, className} = props;
const {tabGroupChoices, setTabGroupChoices} = useUserPreferencesContext(); const {tabGroupChoices, setTabGroupChoices} = useUserPreferencesContext();
const [selectedValue, setSelectedValue] = useState(defaultValue); const [selectedValue, setSelectedValue] = useState(defaultValue);
const children = Children.toArray(props.children) as ReactElement< const children = Children.toArray(props.children) as ReactElement<
TabItemProps TabItemProps
>[]; >[];
const tabRefs: (HTMLLIElement | null)[] = [];
if (groupId != null) { if (groupId != null) {
const relevantTabGroupChoice = tabGroupChoices[groupId]; const relevantTabGroupChoice = tabGroupChoices[groupId];
@ -39,46 +39,35 @@ function Tabs(props: Props): JSX.Element {
} }
} }
const changeSelectedValue = (newValue) => { const handleTabChange = (event) => {
setSelectedValue(newValue); const selectedTab = event.target;
const selectedTabIndex = tabRefs.indexOf(selectedTab);
const selectedTabValue = children[selectedTabIndex].props.value;
setSelectedValue(selectedTabValue);
if (groupId != null) { if (groupId != null) {
setTabGroupChoices(groupId, newValue); setTabGroupChoices(groupId, selectedTabValue);
} }
}; };
const tabRefs: (HTMLLIElement | null)[] = []; const handleKeydown = (event) => {
let focusElement;
const focusNextTab = (tabs, target) => {
const next = tabs.indexOf(target) + 1;
if (!tabs[next]) {
tabs[0].focus();
} else {
tabs[next].focus();
}
};
const focusPreviousTab = (tabs, target) => {
const prev = tabs.indexOf(target) - 1;
if (!tabs[prev]) {
tabs[tabs.length - 1].focus();
} else {
tabs[prev].focus();
}
};
const handleKeydown = (tabs, target, event) => {
switch (event.keyCode) { switch (event.keyCode) {
case keys.right: case keys.right:
focusNextTab(tabs, target); const nextTab = tabRefs.indexOf(event.target) + 1;
focusElement = tabRefs[nextTab] || tabRefs[0];
break; break;
case keys.left: case keys.left:
focusPreviousTab(tabs, target); const prevTab = tabRefs.indexOf(event.target) - 1;
focusElement = tabRefs[prevTab] || tabRefs[tabRefs.length - 1];
break; break;
default: default:
break; break;
} }
focusElement?.focus();
}; };
return ( return (
@ -96,20 +85,16 @@ function Tabs(props: Props): JSX.Element {
{values.map(({value, label}) => ( {values.map(({value, label}) => (
<li <li
role="tab" role="tab"
tabIndex={0} tabIndex={selectedValue === value ? 0 : -1}
aria-selected={selectedValue === value} aria-selected={selectedValue === value}
className={clsx('tabs__item', styles.tabItem, { className={clsx('tabs__item', styles.tabItem, {
'tabs__item--active': selectedValue === value, 'tabs__item--active': selectedValue === value,
})} })}
key={value} key={value}
ref={(tabControl) => tabRefs.push(tabControl)} ref={(tabControl) => tabRefs.push(tabControl)}
onKeyDown={(event) => { onKeyDown={handleKeydown}
handleKeydown(tabRefs, event.target, event); onFocus={handleTabChange}
}} onClick={handleTabChange}>
onFocus={() => changeSelectedValue(value)}
onClick={() => {
changeSelectedValue(value);
}}>
{label} {label}
</li> </li>
))} ))}