feat: Improved table of contents (#1223)
* feat: New table of contents * fix: Hide TOC in edit mode * feat: Highlight follows scroll position * scroll tracking * UI * fix: Unrelated css fix with long doc titles * Improve responsiveness * feat: Add keyboard shortcut access to TOC * fix: Headings should reflect content correctly when viewing old document revision * flow * fix: Persist TOC choice between sessions
This commit is contained in:
@@ -6,7 +6,7 @@ import { observer, inject } from 'mobx-react';
|
||||
import { Redirect } from 'react-router-dom';
|
||||
import styled from 'styled-components';
|
||||
import breakpoint from 'styled-components-breakpoint';
|
||||
import { EditIcon, PlusIcon } from 'outline-icons';
|
||||
import { TableOfContentsIcon, EditIcon, PlusIcon } from 'outline-icons';
|
||||
import { transparentize, darken } from 'polished';
|
||||
import Document from 'models/Document';
|
||||
import AuthStore from 'stores/AuthStore';
|
||||
@@ -14,7 +14,7 @@ import { documentEditUrl } from 'utils/routeHelpers';
|
||||
import { meta } from 'utils/keyboard';
|
||||
|
||||
import Flex from 'shared/components/Flex';
|
||||
import Breadcrumb from 'shared/components/Breadcrumb';
|
||||
import Breadcrumb, { Slash } from 'shared/components/Breadcrumb';
|
||||
import DocumentMenu from 'menus/DocumentMenu';
|
||||
import NewChildDocumentMenu from 'menus/NewChildDocumentMenu';
|
||||
import DocumentShare from 'scenes/DocumentShare';
|
||||
@@ -26,8 +26,11 @@ import Badge from 'components/Badge';
|
||||
import Collaborators from 'components/Collaborators';
|
||||
import { Action, Separator } from 'components/Actions';
|
||||
import PoliciesStore from 'stores/PoliciesStore';
|
||||
import UiStore from 'stores/UiStore';
|
||||
|
||||
type Props = {
|
||||
auth: AuthStore,
|
||||
ui: UiStore,
|
||||
policies: PoliciesStore,
|
||||
document: Document,
|
||||
isDraft: boolean,
|
||||
@@ -43,7 +46,6 @@ type Props = {
|
||||
publish?: boolean,
|
||||
autosave?: boolean,
|
||||
}) => void,
|
||||
auth: AuthStore,
|
||||
};
|
||||
|
||||
@observer
|
||||
@@ -80,7 +82,9 @@ class Header extends React.Component<Props> {
|
||||
|
||||
handleShareLink = async (ev: SyntheticEvent<>) => {
|
||||
const { document } = this.props;
|
||||
if (!document.shareUrl) await document.share();
|
||||
if (!document.shareUrl) {
|
||||
await document.share();
|
||||
}
|
||||
this.showShareModal = true;
|
||||
};
|
||||
|
||||
@@ -108,6 +112,7 @@ class Header extends React.Component<Props> {
|
||||
isSaving,
|
||||
savingIsDisabled,
|
||||
publishingIsDisabled,
|
||||
ui,
|
||||
auth,
|
||||
} = this.props;
|
||||
|
||||
@@ -134,7 +139,33 @@ class Header extends React.Component<Props> {
|
||||
onSubmit={this.handleCloseShareModal}
|
||||
/>
|
||||
</Modal>
|
||||
<Breadcrumb document={document} />
|
||||
<BreadcrumbAndContents align="center" justify="flex-start">
|
||||
<Breadcrumb document={document} />
|
||||
{!isEditing && (
|
||||
<React.Fragment>
|
||||
<Slash />
|
||||
<Tooltip
|
||||
tooltip={ui.tocVisible ? 'Hide contents' : 'Show contents'}
|
||||
shortcut={`ctrl+${meta}+h`}
|
||||
delay={250}
|
||||
placement="bottom"
|
||||
>
|
||||
<Button
|
||||
onClick={
|
||||
ui.tocVisible
|
||||
? ui.hideTableOfContents
|
||||
: ui.showTableOfContents
|
||||
}
|
||||
icon={<TableOfContentsIcon />}
|
||||
iconColor="currentColor"
|
||||
borderOnHover
|
||||
neutral
|
||||
small
|
||||
/>
|
||||
</Tooltip>
|
||||
</React.Fragment>
|
||||
)}
|
||||
</BreadcrumbAndContents>
|
||||
{this.isScrolled && (
|
||||
<Title onClick={this.handleClickTitle}>
|
||||
<Fade>
|
||||
@@ -273,6 +304,14 @@ const Status = styled.div`
|
||||
color: ${props => props.theme.slate};
|
||||
`;
|
||||
|
||||
const BreadcrumbAndContents = styled(Flex)`
|
||||
display: none;
|
||||
|
||||
${breakpoint('tablet')`
|
||||
display: flex;
|
||||
`};
|
||||
`;
|
||||
|
||||
const Wrapper = styled(Flex)`
|
||||
width: 100%;
|
||||
align-self: flex-end;
|
||||
@@ -289,7 +328,7 @@ const Actions = styled(Flex)`
|
||||
right: 0;
|
||||
left: 0;
|
||||
z-index: 1;
|
||||
background: ${props => transparentize(0.1, props.theme.background)};
|
||||
background: ${props => transparentize(0.2, props.theme.background)};
|
||||
box-shadow: 0 1px 0
|
||||
${props =>
|
||||
props.isCompact
|
||||
@@ -298,7 +337,7 @@ const Actions = styled(Flex)`
|
||||
padding: 12px;
|
||||
transition: all 100ms ease-out;
|
||||
transform: translate3d(0, 0, 0);
|
||||
-webkit-backdrop-filter: blur(20px);
|
||||
backdrop-filter: blur(20px);
|
||||
|
||||
@media print {
|
||||
display: none;
|
||||
@@ -327,4 +366,4 @@ const Title = styled.div`
|
||||
`};
|
||||
`;
|
||||
|
||||
export default inject('auth', 'policies')(Header);
|
||||
export default inject('auth', 'ui', 'policies')(Header);
|
||||
|
||||
Reference in New Issue
Block a user