fix: Mispositioned TOC control on mobile due to merge conflict
fix: Show message in mobile TOC when no headings in document fix: MenuItem with level should still have background edge-to-edge fix: Show developer warning when creating incorrect menu item type
This commit is contained in:
@@ -87,9 +87,9 @@ const Spacer = styled.svg`
|
|||||||
export const MenuAnchor = styled.a`
|
export const MenuAnchor = styled.a`
|
||||||
display: flex;
|
display: flex;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
margin-left: ${(props) => props.level * 10}px;
|
|
||||||
border: 0;
|
border: 0;
|
||||||
padding: 12px;
|
padding: 12px;
|
||||||
|
padding-left: ${(props) => 12 + props.level * 10}px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
min-height: 32px;
|
min-height: 32px;
|
||||||
background: none;
|
background: none;
|
||||||
|
|||||||
@@ -13,47 +13,7 @@ import Header from "./Header";
|
|||||||
import MenuItem, { MenuAnchor } from "./MenuItem";
|
import MenuItem, { MenuAnchor } from "./MenuItem";
|
||||||
import Separator from "./Separator";
|
import Separator from "./Separator";
|
||||||
import ContextMenu from ".";
|
import ContextMenu from ".";
|
||||||
|
import { type MenuItem as TMenuItem } from "types";
|
||||||
type TMenuItem =
|
|
||||||
| {|
|
|
||||||
title: React.Node,
|
|
||||||
to: string,
|
|
||||||
visible?: boolean,
|
|
||||||
selected?: boolean,
|
|
||||||
disabled?: boolean,
|
|
||||||
|}
|
|
||||||
| {|
|
|
||||||
title: React.Node,
|
|
||||||
onClick: (event: SyntheticEvent<>) => void | Promise<void>,
|
|
||||||
visible?: boolean,
|
|
||||||
selected?: boolean,
|
|
||||||
disabled?: boolean,
|
|
||||||
|}
|
|
||||||
| {|
|
|
||||||
title: React.Node,
|
|
||||||
href: string,
|
|
||||||
visible?: boolean,
|
|
||||||
selected?: boolean,
|
|
||||||
disabled?: boolean,
|
|
||||||
level?: number,
|
|
||||||
|}
|
|
||||||
| {|
|
|
||||||
title: React.Node,
|
|
||||||
visible?: boolean,
|
|
||||||
disabled?: boolean,
|
|
||||||
style?: Object,
|
|
||||||
hover?: boolean,
|
|
||||||
items: TMenuItem[],
|
|
||||||
|}
|
|
||||||
| {|
|
|
||||||
type: "separator",
|
|
||||||
visible?: boolean,
|
|
||||||
|}
|
|
||||||
| {|
|
|
||||||
type: "heading",
|
|
||||||
visible?: boolean,
|
|
||||||
title: React.Node,
|
|
||||||
|};
|
|
||||||
|
|
||||||
type Props = {|
|
type Props = {|
|
||||||
items: TMenuItem[],
|
items: TMenuItem[],
|
||||||
@@ -174,6 +134,7 @@ function Template({ items, ...menu }: Props): React.Node {
|
|||||||
return <Header>{item.title}</Header>;
|
return <Header>{item.title}</Header>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.warn("Unrecognized menu item", item);
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,8 +72,6 @@ const Actions = styled(Flex)`
|
|||||||
flex-basis: 0;
|
flex-basis: 0;
|
||||||
min-width: auto;
|
min-width: auto;
|
||||||
padding-left: 8px;
|
padding-left: 8px;
|
||||||
position: fixed;
|
|
||||||
right: 12px;
|
|
||||||
|
|
||||||
${breakpoint("tablet")`
|
${breakpoint("tablet")`
|
||||||
position: unset;
|
position: unset;
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { MenuButton, useMenuState } from "reakit/Menu";
|
|||||||
import Button from "components/Button";
|
import Button from "components/Button";
|
||||||
import ContextMenu from "components/ContextMenu";
|
import ContextMenu from "components/ContextMenu";
|
||||||
import Template from "components/ContextMenu/Template";
|
import Template from "components/ContextMenu/Template";
|
||||||
|
import { type MenuItem } from "types";
|
||||||
|
|
||||||
type Props = {|
|
type Props = {|
|
||||||
headings: { title: string, level: number, id: string }[],
|
headings: { title: string, level: number, id: string }[],
|
||||||
@@ -27,6 +28,31 @@ function TableOfContentsMenu({ headings }: Props) {
|
|||||||
Infinity
|
Infinity
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const items: MenuItem[] = React.useMemo(() => {
|
||||||
|
let i = [
|
||||||
|
{
|
||||||
|
type: "heading",
|
||||||
|
visible: true,
|
||||||
|
title: t("Contents"),
|
||||||
|
},
|
||||||
|
...headings.map((heading) => ({
|
||||||
|
href: `#${heading.id}`,
|
||||||
|
title: t(heading.title),
|
||||||
|
level: heading.level - minHeading,
|
||||||
|
})),
|
||||||
|
];
|
||||||
|
|
||||||
|
if (i.length === 1) {
|
||||||
|
i.push({
|
||||||
|
href: "#",
|
||||||
|
title: t("Headings you add to the document will appear here"),
|
||||||
|
disabled: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}, [t, headings, minHeading]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<MenuButton {...menu}>
|
<MenuButton {...menu}>
|
||||||
@@ -41,23 +67,7 @@ function TableOfContentsMenu({ headings }: Props) {
|
|||||||
)}
|
)}
|
||||||
</MenuButton>
|
</MenuButton>
|
||||||
<ContextMenu {...menu} aria-label={t("Table of contents")}>
|
<ContextMenu {...menu} aria-label={t("Table of contents")}>
|
||||||
<Template
|
<Template {...menu} items={items} />
|
||||||
{...menu}
|
|
||||||
items={[
|
|
||||||
{
|
|
||||||
type: "heading",
|
|
||||||
visible: true,
|
|
||||||
title: t("Contents"),
|
|
||||||
},
|
|
||||||
...headings.map((heading) => {
|
|
||||||
return {
|
|
||||||
href: `#${heading.id}`,
|
|
||||||
title: t(heading.title),
|
|
||||||
level: heading.level - minHeading,
|
|
||||||
};
|
|
||||||
}),
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
</ContextMenu>
|
</ContextMenu>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -58,3 +58,44 @@ export type SearchResult = {
|
|||||||
context: string,
|
context: string,
|
||||||
document: Document,
|
document: Document,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type MenuItem =
|
||||||
|
| {|
|
||||||
|
title: React.Node,
|
||||||
|
to: string,
|
||||||
|
visible?: boolean,
|
||||||
|
selected?: boolean,
|
||||||
|
disabled?: boolean,
|
||||||
|
|}
|
||||||
|
| {|
|
||||||
|
title: React.Node,
|
||||||
|
onClick: (event: SyntheticEvent<>) => void | Promise<void>,
|
||||||
|
visible?: boolean,
|
||||||
|
selected?: boolean,
|
||||||
|
disabled?: boolean,
|
||||||
|
|}
|
||||||
|
| {|
|
||||||
|
title: React.Node,
|
||||||
|
href: string,
|
||||||
|
visible?: boolean,
|
||||||
|
selected?: boolean,
|
||||||
|
disabled?: boolean,
|
||||||
|
level?: number,
|
||||||
|
|}
|
||||||
|
| {|
|
||||||
|
title: React.Node,
|
||||||
|
visible?: boolean,
|
||||||
|
disabled?: boolean,
|
||||||
|
style?: Object,
|
||||||
|
hover?: boolean,
|
||||||
|
items: MenuItem[],
|
||||||
|
|}
|
||||||
|
| {|
|
||||||
|
type: "separator",
|
||||||
|
visible?: boolean,
|
||||||
|
|}
|
||||||
|
| {|
|
||||||
|
type: "heading",
|
||||||
|
visible?: boolean,
|
||||||
|
title: React.Node,
|
||||||
|
|};
|
||||||
|
|||||||
@@ -206,8 +206,9 @@
|
|||||||
"Share options": "Share options",
|
"Share options": "Share options",
|
||||||
"Go to document": "Go to document",
|
"Go to document": "Go to document",
|
||||||
"Revoke link": "Revoke link",
|
"Revoke link": "Revoke link",
|
||||||
"Table of contents": "Table of contents",
|
|
||||||
"Contents": "Contents",
|
"Contents": "Contents",
|
||||||
|
"Headings you add to the document will appear here": "Headings you add to the document will appear here",
|
||||||
|
"Table of contents": "Table of contents",
|
||||||
"By {{ author }}": "By {{ author }}",
|
"By {{ author }}": "By {{ author }}",
|
||||||
"Are you sure you want to make {{ userName }} an admin? Admins can modify team and billing information.": "Are you sure you want to make {{ userName }} an admin? Admins can modify team and billing information.",
|
"Are you sure you want to make {{ userName }} an admin? Admins can modify team and billing information.": "Are you sure you want to make {{ userName }} an admin? Admins can modify team and billing information.",
|
||||||
"Are you sure you want to make {{ userName }} a member?": "Are you sure you want to make {{ userName }} a member?",
|
"Are you sure you want to make {{ userName }} a member?": "Are you sure you want to make {{ userName }} a member?",
|
||||||
|
|||||||
Reference in New Issue
Block a user