From 7d5fbeb7b024c06259961c4536d9f63e029fba07 Mon Sep 17 00:00:00 2001 From: Saumya Pandey Date: Fri, 9 Jul 2021 17:20:27 +0530 Subject: [PATCH] fix: Add access to document TOC on mobile (#2279) * Add TOC button for mobile * Undo NewDocumentMenu changes * Place the toc button in the correct position. * Pass menu props to menuitem * Update app/menus/TableOfContentsMenu.js Co-authored-by: Tom Moor * Update app/menus/TableOfContentsMenu.js Co-authored-by: Tom Moor * Use the existing prop type * Write menu inside actions prop * Prevent blank webpage behaviour for toc * Use href instead of level to determine target * Update app/scenes/Document/components/Header.js Co-authored-by: Tom Moor * Add heading to menu items * Use existing Heading component Co-authored-by: Tom Moor --- app/components/ContextMenu/MenuItem.js | 2 + app/components/ContextMenu/Template.js | 9 ++- app/menus/TableOfContentsMenu.js | 66 ++++++++++++++++++++++ app/scenes/Document/components/Document.js | 1 + app/scenes/Document/components/Header.js | 13 +++++ shared/i18n/locales/en_US/translation.json | 2 +- 6 files changed, 91 insertions(+), 2 deletions(-) create mode 100644 app/menus/TableOfContentsMenu.js diff --git a/app/components/ContextMenu/MenuItem.js b/app/components/ContextMenu/MenuItem.js index a82d9222..7ebc4bc9 100644 --- a/app/components/ContextMenu/MenuItem.js +++ b/app/components/ContextMenu/MenuItem.js @@ -15,6 +15,7 @@ type Props = {| target?: "_blank", as?: string | React.ComponentType<*>, hide?: () => void, + level?: number, |}; const MenuItem = ({ @@ -86,6 +87,7 @@ const Spacer = styled.svg` export const MenuAnchor = styled.a` display: flex; margin: 0; + margin-left: ${(props) => props.level * 10}px; border: 0; padding: 12px; width: 100%; diff --git a/app/components/ContextMenu/Template.js b/app/components/ContextMenu/Template.js index bbd3bd12..f8a2507c 100644 --- a/app/components/ContextMenu/Template.js +++ b/app/components/ContextMenu/Template.js @@ -9,6 +9,7 @@ import { MenuItem as BaseMenuItem, } from "reakit/Menu"; import styled from "styled-components"; +import Header from "./Header"; import MenuItem, { MenuAnchor } from "./MenuItem"; import Separator from "./Separator"; import ContextMenu from "."; @@ -34,6 +35,7 @@ type TMenuItem = visible?: boolean, selected?: boolean, disabled?: boolean, + level?: number, |} | {| title: React.Node, @@ -128,7 +130,8 @@ function Template({ items, ...menu }: Props): React.Node { key={index} disabled={item.disabled} selected={item.selected} - target="_blank" + level={item.level} + target={item.href.startsWith("#") ? undefined : "_blank"} {...menu} > {item.title} @@ -167,6 +170,10 @@ function Template({ items, ...menu }: Props): React.Node { return ; } + if (item.type === "heading") { + return
{item.title}
; + } + return null; }); } diff --git a/app/menus/TableOfContentsMenu.js b/app/menus/TableOfContentsMenu.js new file mode 100644 index 00000000..abe1f978 --- /dev/null +++ b/app/menus/TableOfContentsMenu.js @@ -0,0 +1,66 @@ +// @flow +import { observer } from "mobx-react"; +import { TableOfContentsIcon } from "outline-icons"; +import * as React from "react"; +import { useTranslation } from "react-i18next"; +import { MenuButton, useMenuState } from "reakit/Menu"; +import Button from "components/Button"; +import ContextMenu from "components/ContextMenu"; +import Template from "components/ContextMenu/Template"; + +type Props = {| + headings: { title: string, level: number, id: string }[], +|}; + +function TableOfContentsMenu({ headings }: Props) { + const menu = useMenuState({ + modal: true, + unstable_preventOverflow: true, + unstable_fixed: true, + unstable_flip: true, + }); + + const { t } = useTranslation(); + + const minHeading = headings.reduce( + (memo, heading) => (heading.level < memo ? heading.level : memo), + Infinity + ); + + return ( + <> + + {(props) => ( +