mirror of
https://github.com/facebook/docusaurus.git
synced 2025-06-24 05:28:01 +02:00
refactor(v2): update tabs to follow WAI-ARIA (#4193)
This commit is contained in:
parent
fc071b0c2f
commit
00c1e8d852
1 changed files with 21 additions and 36 deletions
|
@ -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>
|
||||||
))}
|
))}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue