fix: Keyboard accessible context menus (#1768)

- Makes menus fully accessible and keyboard driven
- Currently adds 2.8% to initial bundle size due to the inclusion of Reakit and its dependency, popperjs.
- Converts all menus to functional components
- Remove old custom menu system
- Various layout and flow improvements around the menus

closes #1766
This commit is contained in:
Tom Moor
2021-01-13 22:00:25 -08:00
committed by GitHub
parent 47369dd968
commit e8b7782f5e
54 changed files with 1788 additions and 1881 deletions

View File

@ -3,29 +3,25 @@ import { observer } from "mobx-react";
import { AlphabeticalSortIcon, ManualSortIcon } from "outline-icons";
import * as React from "react";
import { useTranslation } from "react-i18next";
import { useMenuState, MenuButton } from "reakit/Menu";
import Collection from "models/Collection";
import { DropdownMenu } from "components/DropdownMenu";
import DropdownMenuItems from "components/DropdownMenu/DropdownMenuItems";
import ContextMenu from "components/ContextMenu";
import Template from "components/ContextMenu/Template";
import NudeButton from "components/NudeButton";
type Props = {
position?: "left" | "right" | "center",
type Props = {|
collection: Collection,
onOpen?: () => void,
onClose?: () => void,
};
|};
function CollectionSortMenu({
collection,
position,
onOpen,
onClose,
...rest
}: Props) {
function CollectionSortMenu({ collection, onOpen, onClose, ...rest }: Props) {
const { t } = useTranslation();
const menu = useMenuState({ modal: true });
const handleChangeSort = React.useCallback(
(field: string) => {
menu.hide();
return collection.save({
sort: {
field,
@ -33,38 +29,43 @@ function CollectionSortMenu({
},
});
},
[collection]
[collection, menu]
);
const alphabeticalSort = collection.sort.field === "title";
return (
<DropdownMenu
onOpen={onOpen}
onClose={onClose}
label={
<NudeButton aria-label={t("Sort in sidebar")} aria-haspopup="true">
{alphabeticalSort ? <AlphabeticalSortIcon /> : <ManualSortIcon />}
</NudeButton>
}
position={position}
{...rest}
>
<DropdownMenuItems
items={[
{
title: t("Alphabetical sort"),
onClick: () => handleChangeSort("title"),
selected: alphabeticalSort,
},
{
title: t("Manual sort"),
onClick: () => handleChangeSort("index"),
selected: !alphabeticalSort,
},
]}
/>
</DropdownMenu>
<>
<MenuButton {...menu}>
{(props) => (
<NudeButton {...props}>
{alphabeticalSort ? <AlphabeticalSortIcon /> : <ManualSortIcon />}
</NudeButton>
)}
</MenuButton>
<ContextMenu
{...menu}
onOpen={onOpen}
onClose={onClose}
aria-label={t("Sort in sidebar")}
>
<Template
{...menu}
items={[
{
title: t("Alphabetical sort"),
onClick: () => handleChangeSort("title"),
selected: alphabeticalSort,
},
{
title: t("Manual sort"),
onClick: () => handleChangeSort("index"),
selected: !alphabeticalSort,
},
]}
/>
</ContextMenu>
</>
);
}