Rebuilding code block menus (#5569)

This commit is contained in:
Tom Moor
2023-07-17 21:25:22 -04:00
committed by GitHub
parent 60b456f35a
commit 2427f4747a
42 changed files with 474 additions and 469 deletions

View File

@@ -1,7 +1,13 @@
import { ExpandedIcon } from "outline-icons";
import * as React from "react";
import { useMenuState } from "reakit";
import { MenuButton } from "reakit/Menu";
import styled from "styled-components";
import { MenuItem } from "@shared/editor/types";
import { s } from "@shared/styles";
import ContextMenu from "~/components/ContextMenu";
import Template from "~/components/ContextMenu/Template";
import { MenuItem as TMenuItem } from "~/types";
import { useEditor } from "./EditorContext";
import ToolbarButton from "./ToolbarButton";
import ToolbarSeparator from "./ToolbarSeparator";
@@ -12,11 +18,59 @@ type Props = {
};
const FlexibleWrapper = styled.div`
color: ${s("toolbarItem")};
color: ${s("textSecondary")};
display: flex;
gap: 8px;
`;
/*
* Renders a dropdown menu in the floating toolbar.
*/
function ToolbarDropdown(props: { item: MenuItem }) {
const menu = useMenuState();
const { commands, view } = useEditor();
const { item } = props;
const { state } = view;
const items: TMenuItem[] = React.useMemo(() => {
const handleClick = (item: MenuItem) => () => {
if (!item.name) {
return;
}
commands[item.name](
typeof item.attrs === "function" ? item.attrs(state) : item.attrs
);
};
return item.children
? item.children.map((child) => ({
type: "button",
title: child.label,
icon: child.icon,
selected: child.active ? child.active(state) : false,
onClick: handleClick(child),
}))
: [];
}, [item.children, commands, state]);
return (
<>
<MenuButton {...menu}>
{(props) => (
<ToolbarButton {...props} hovering={menu.visible}>
{item.label && <Label>{item.label}</Label>}
<Arrow />
</ToolbarButton>
)}
</MenuButton>
<ContextMenu aria-label={item.label} {...menu}>
<Template {...menu} items={items} />
</ContextMenu>
</>
);
}
function ToolbarMenu(props: Props) {
const { commands, view } = useEditor();
const { items } = props;
@@ -27,10 +81,9 @@ function ToolbarMenu(props: Props) {
return;
}
const attrs =
typeof item.attrs === "function" ? item.attrs(state) : item.attrs;
commands[item.name](attrs);
commands[item.name](
typeof item.attrs === "function" ? item.attrs(state) : item.attrs
);
};
return (
@@ -49,10 +102,14 @@ function ToolbarMenu(props: Props) {
tooltip={item.label === item.tooltip ? undefined : item.tooltip}
key={index}
>
<ToolbarButton onClick={handleClick(item)} active={isActive}>
{item.label && <Label>{item.label}</Label>}
{item.icon}
</ToolbarButton>
{item.children ? (
<ToolbarDropdown item={item} />
) : (
<ToolbarButton onClick={handleClick(item)} active={isActive}>
{item.label && <Label>{item.label}</Label>}
{item.icon}
</ToolbarButton>
)}
</Tooltip>
);
})}
@@ -60,6 +117,11 @@ function ToolbarMenu(props: Props) {
);
}
const Arrow = styled(ExpandedIcon)`
margin-right: -4px;
color: ${s("textSecondary")};
`;
const Label = styled.span`
font-size: 15px;
font-weight: 500;