Merge branch 'develop' of github.com:outline/outline into feat/mass-import

This commit is contained in:
Tom Moor
2020-12-19 16:01:10 -08:00
8 changed files with 127 additions and 7 deletions

View File

@@ -65,6 +65,11 @@ class Layout extends React.Component<Props> {
window.document.body.style.background = props.theme.background; window.document.body.style.background = props.theme.background;
} }
@keydown("meta+.")
handleToggleSidebar() {
this.props.ui.toggleCollapsedSidebar();
}
@keydown("shift+/") @keydown("shift+/")
handleOpenKeyboardShortcuts() { handleOpenKeyboardShortcuts() {
if (this.props.ui.editMode) return; if (this.props.ui.editMode) return;
@@ -119,7 +124,11 @@ class Layout extends React.Component<Props> {
</Switch> </Switch>
)} )}
<Content auto justify="center" editMode={ui.editMode}> <Content
auto
justify="center"
sidebarCollapsed={ui.editMode || ui.sidebarCollapsed}
>
{this.props.children} {this.props.children}
</Content> </Content>
@@ -159,7 +168,10 @@ const Content = styled(Flex)`
} }
${breakpoint("tablet")` ${breakpoint("tablet")`
margin-left: ${(props) => (props.editMode ? 0 : props.theme.sidebarWidth)}; margin-left: ${(props) =>
props.sidebarCollapsed
? props.theme.sidebarCollapsedWidth
: props.theme.sidebarWidth};
`}; `};
`; `;

View File

@@ -8,6 +8,7 @@ import styled from "styled-components";
import breakpoint from "styled-components-breakpoint"; import breakpoint from "styled-components-breakpoint";
import Fade from "components/Fade"; import Fade from "components/Fade";
import Flex from "components/Flex"; import Flex from "components/Flex";
import CollapseToggle, { Button } from "./components/CollapseToggle";
import usePrevious from "hooks/usePrevious"; import usePrevious from "hooks/usePrevious";
import useStores from "hooks/useStores"; import useStores from "hooks/useStores";
@@ -30,10 +31,14 @@ function Sidebar({ location, children }: Props) {
const content = ( const content = (
<Container <Container
editMode={ui.editMode}
mobileSidebarVisible={ui.mobileSidebarVisible} mobileSidebarVisible={ui.mobileSidebarVisible}
collapsed={ui.editMode || ui.sidebarCollapsed}
column column
> >
<CollapseToggle
collapsed={ui.sidebarCollapsed}
onClick={ui.toggleCollapsedSidebar}
/>
<Toggle <Toggle
onClick={ui.toggleMobileSidebar} onClick={ui.toggleMobileSidebar}
mobileSidebarVisible={ui.mobileSidebarVisible} mobileSidebarVisible={ui.mobileSidebarVisible}
@@ -63,7 +68,7 @@ const Container = styled(Flex)`
bottom: 0; bottom: 0;
width: 100%; width: 100%;
background: ${(props) => props.theme.sidebarBackground}; background: ${(props) => props.theme.sidebarBackground};
transition: left 100ms ease-out, transition: box-shadow, 100ms, ease-in-out, left 100ms ease-out,
${(props) => props.theme.backgroundTransition}; ${(props) => props.theme.backgroundTransition};
margin-left: ${(props) => (props.mobileSidebarVisible ? 0 : "-100%")}; margin-left: ${(props) => (props.mobileSidebarVisible ? 0 : "-100%")};
z-index: ${(props) => props.theme.depths.sidebar}; z-index: ${(props) => props.theme.depths.sidebar};
@@ -90,10 +95,33 @@ const Container = styled(Flex)`
} }
${breakpoint("tablet")` ${breakpoint("tablet")`
left: ${(props) => (props.editMode ? `-${props.theme.sidebarWidth}` : 0)}; left: ${(props) =>
props.collapsed
? `calc(-${props.theme.sidebarWidth} + ${props.theme.sidebarCollapsedWidth})`
: 0};
width: ${(props) => props.theme.sidebarWidth}; width: ${(props) => props.theme.sidebarWidth};
margin: 0; margin: 0;
z-index: 3; z-index: 3;
&:hover,
&:focus-within {
left: 0;
box-shadow: ${(props) =>
props.collapsed ? "rgba(0, 0, 0, 0.2) 1px 0 4px" : "none"};
& ${Button} {
opacity: .75;
}
& ${Button}:hover {
opacity: 1;
}
}
&:not(:hover):not(:focus-within) > div {
opacity: ${(props) => (props.collapsed ? "0" : "1")};
transition: opacity 100ms ease-in-out;
}
`}; `};
`; `;

View File

@@ -0,0 +1,59 @@
// @flow
import { NextIcon, BackIcon } from "outline-icons";
import * as React from "react";
import { useTranslation } from "react-i18next";
import styled from "styled-components";
import Tooltip from "components/Tooltip";
import { meta } from "utils/keyboard";
type Props = {|
collapsed: boolean,
onClick?: () => void,
|};
function CollapseToggle({ collapsed, ...rest }: Props) {
const { t } = useTranslation();
return (
<Tooltip
tooltip={collapsed ? t("Expand") : t("Collapse")}
shortcut={`${meta}+.`}
delay={500}
placement="bottom"
>
<Button {...rest} aria-hidden>
{collapsed ? (
<NextIcon color="currentColor" />
) : (
<BackIcon color="currentColor" />
)}
</Button>
</Tooltip>
);
}
export const Button = styled.button`
display: block;
position: absolute;
top: 28px;
right: 8px;
border: 0;
width: 24px;
height: 24px;
z-index: 1;
font-weight: 600;
color: ${(props) => props.theme.sidebarText};
background: ${(props) => props.theme.sidebarItemBackground};
transition: opacity 100ms ease-in-out;
border-radius: 4px;
opacity: 0;
cursor: pointer;
padding: 0;
&:hover {
color: ${(props) => props.theme.white};
background: ${(props) => props.theme.primary};
}
`;
export default CollapseToggle;

View File

@@ -61,7 +61,7 @@ const Header = styled.button`
display: flex; display: flex;
align-items: center; align-items: center;
flex-shrink: 0; flex-shrink: 0;
padding: 16px 24px; padding: 20px 24px;
position: relative; position: relative;
background: none; background: none;
line-height: inherit; line-height: inherit;

View File

@@ -23,6 +23,7 @@ class UiStore {
@observable editMode: boolean = false; @observable editMode: boolean = false;
@observable tocVisible: boolean = false; @observable tocVisible: boolean = false;
@observable mobileSidebarVisible: boolean = false; @observable mobileSidebarVisible: boolean = false;
@observable sidebarCollapsed: boolean = false;
@observable toasts: Map<string, Toast> = new Map(); @observable toasts: Map<string, Toast> = new Map();
constructor() { constructor() {
@@ -51,6 +52,7 @@ class UiStore {
// persisted keys // persisted keys
this.languagePromptDismissed = data.languagePromptDismissed; this.languagePromptDismissed = data.languagePromptDismissed;
this.sidebarCollapsed = data.sidebarCollapsed;
this.tocVisible = data.tocVisible; this.tocVisible = data.tocVisible;
this.theme = data.theme || "system"; this.theme = data.theme || "system";
@@ -107,6 +109,21 @@ class UiStore {
this.activeCollectionId = undefined; this.activeCollectionId = undefined;
}; };
@action
collapseSidebar = () => {
this.sidebarCollapsed = true;
};
@action
expandSidebar = () => {
this.sidebarCollapsed = false;
};
@action
toggleCollapsedSidebar = () => {
this.sidebarCollapsed = !this.sidebarCollapsed;
};
@action @action
showTableOfContents = () => { showTableOfContents = () => {
this.tocVisible = true; this.tocVisible = true;
@@ -190,6 +207,7 @@ class UiStore {
get asJson(): string { get asJson(): string {
return JSON.stringify({ return JSON.stringify({
tocVisible: this.tocVisible, tocVisible: this.tocVisible,
sidebarCollapsed: this.sidebarCollapsed,
languagePromptDismissed: this.languagePromptDismissed, languagePromptDismissed: this.languagePromptDismissed,
theme: this.theme, theme: this.theme,
}); });

View File

@@ -59,7 +59,7 @@ export const makePolicy = (
expiration: format(tomorrow, "YYYY-MM-DDTHH:mm:ss\\Z"), expiration: format(tomorrow, "YYYY-MM-DDTHH:mm:ss\\Z"),
}; };
return new Buffer(JSON.stringify(policy)).toString("base64"); return Buffer.from(JSON.stringify(policy)).toString("base64");
}; };
export const getSignature = (policy: any) => { export const getSignature = (policy: any) => {

View File

@@ -82,6 +82,8 @@
"Change Language": "Change Language", "Change Language": "Change Language",
"Dismiss": "Dismiss", "Dismiss": "Dismiss",
"Keyboard shortcuts": "Keyboard shortcuts", "Keyboard shortcuts": "Keyboard shortcuts",
"Expand": "Expand",
"Collapse": "Collapse",
"New collection": "New collection", "New collection": "New collection",
"Collections": "Collections", "Collections": "Collections",
"Untitled": "Untitled", "Untitled": "Untitled",

View File

@@ -48,6 +48,7 @@ const spacing = {
vpadding: "1.5vw", vpadding: "1.5vw",
hpadding: "1.875vw", hpadding: "1.875vw",
sidebarWidth: "280px", sidebarWidth: "280px",
sidebarCollapsedWidth: "16px",
sidebarMinWidth: "250px", sidebarMinWidth: "250px",
sidebarMaxWidth: "350px", sidebarMaxWidth: "350px",
}; };