Skip to content

Commit 00c1e8d

Browse files
authored
refactor(v2): update tabs to follow WAI-ARIA (#4193)
1 parent fc071b0 commit 00c1e8d

File tree

1 file changed

+20
-35
lines changed
  • packages/docusaurus-theme-classic/src/theme/Tabs

1 file changed

+20
-35
lines changed

packages/docusaurus-theme-classic/src/theme/Tabs/index.tsx

+20-35
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,10 @@ function Tabs(props: Props): JSX.Element {
2323
const {lazy, block, defaultValue, values, groupId, className} = props;
2424
const {tabGroupChoices, setTabGroupChoices} = useUserPreferencesContext();
2525
const [selectedValue, setSelectedValue] = useState(defaultValue);
26-
2726
const children = Children.toArray(props.children) as ReactElement<
2827
TabItemProps
2928
>[];
29+
const tabRefs: (HTMLLIElement | null)[] = [];
3030

3131
if (groupId != null) {
3232
const relevantTabGroupChoice = tabGroupChoices[groupId];
@@ -39,46 +39,35 @@ function Tabs(props: Props): JSX.Element {
3939
}
4040
}
4141

42-
const changeSelectedValue = (newValue) => {
43-
setSelectedValue(newValue);
44-
if (groupId != null) {
45-
setTabGroupChoices(groupId, newValue);
46-
}
47-
};
48-
49-
const tabRefs: (HTMLLIElement | null)[] = [];
42+
const handleTabChange = (event) => {
43+
const selectedTab = event.target;
44+
const selectedTabIndex = tabRefs.indexOf(selectedTab);
45+
const selectedTabValue = children[selectedTabIndex].props.value;
5046

51-
const focusNextTab = (tabs, target) => {
52-
const next = tabs.indexOf(target) + 1;
47+
setSelectedValue(selectedTabValue);
5348

54-
if (!tabs[next]) {
55-
tabs[0].focus();
56-
} else {
57-
tabs[next].focus();
49+
if (groupId != null) {
50+
setTabGroupChoices(groupId, selectedTabValue);
5851
}
5952
};
6053

61-
const focusPreviousTab = (tabs, target) => {
62-
const prev = tabs.indexOf(target) - 1;
63-
64-
if (!tabs[prev]) {
65-
tabs[tabs.length - 1].focus();
66-
} else {
67-
tabs[prev].focus();
68-
}
69-
};
54+
const handleKeydown = (event) => {
55+
let focusElement;
7056

71-
const handleKeydown = (tabs, target, event) => {
7257
switch (event.keyCode) {
7358
case keys.right:
74-
focusNextTab(tabs, target);
59+
const nextTab = tabRefs.indexOf(event.target) + 1;
60+
focusElement = tabRefs[nextTab] || tabRefs[0];
7561
break;
7662
case keys.left:
77-
focusPreviousTab(tabs, target);
63+
const prevTab = tabRefs.indexOf(event.target) - 1;
64+
focusElement = tabRefs[prevTab] || tabRefs[tabRefs.length - 1];
7865
break;
7966
default:
8067
break;
8168
}
69+
70+
focusElement?.focus();
8271
};
8372

8473
return (
@@ -96,20 +85,16 @@ function Tabs(props: Props): JSX.Element {
9685
{values.map(({value, label}) => (
9786
<li
9887
role="tab"
99-
tabIndex={0}
88+
tabIndex={selectedValue === value ? 0 : -1}
10089
aria-selected={selectedValue === value}
10190
className={clsx('tabs__item', styles.tabItem, {
10291
'tabs__item--active': selectedValue === value,
10392
})}
10493
key={value}
10594
ref={(tabControl) => tabRefs.push(tabControl)}
106-
onKeyDown={(event) => {
107-
handleKeydown(tabRefs, event.target, event);
108-
}}
109-
onFocus={() => changeSelectedValue(value)}
110-
onClick={() => {
111-
changeSelectedValue(value);
112-
}}>
95+
onKeyDown={handleKeydown}
96+
onFocus={handleTabChange}
97+
onClick={handleTabChange}>
11398
{label}
11499
</li>
115100
))}

0 commit comments

Comments
 (0)