Sidebar improvements from comments branch (#4419)

This commit is contained in:
Tom Moor
2022-11-13 18:26:53 -08:00
committed by GitHub
parent b60c66316a
commit 24a1eac804
7 changed files with 95 additions and 77 deletions

View File

@@ -8,6 +8,7 @@ import type { DocumentContextValue } from "~/components/DocumentContext";
import Layout from "~/components/Layout"; import Layout from "~/components/Layout";
import RegisterKeyDown from "~/components/RegisterKeyDown"; import RegisterKeyDown from "~/components/RegisterKeyDown";
import Sidebar from "~/components/Sidebar"; import Sidebar from "~/components/Sidebar";
import SidebarRight from "~/components/Sidebar/Right";
import SettingsSidebar from "~/components/Sidebar/Settings"; import SettingsSidebar from "~/components/Sidebar/Settings";
import type { Editor as TEditor } from "~/editor"; import type { Editor as TEditor } from "~/editor";
import usePolicy from "~/hooks/usePolicy"; import usePolicy from "~/hooks/usePolicy";
@@ -19,6 +20,7 @@ import {
newDocumentPath, newDocumentPath,
settingsPath, settingsPath,
matchDocumentHistory, matchDocumentHistory,
matchDocumentInsights,
} from "~/utils/routeHelpers"; } from "~/utils/routeHelpers";
import Fade from "./Fade"; import Fade from "./Fade";
@@ -90,32 +92,26 @@ const AuthenticatedLayout: React.FC = ({ children }) => {
</Fade> </Fade>
) : undefined; ) : undefined;
const showHistory = !!matchPath(location.pathname, {
path: matchDocumentHistory,
});
const showInsights = !!matchPath(location.pathname, {
path: matchDocumentInsights,
});
const sidebarRight = ( const sidebarRight = (
<React.Suspense fallback={null}> <AnimatePresence key={ui.activeDocumentId}>
<AnimatePresence key={ui.activeDocumentId}> {(showHistory || showInsights) && (
<Switch <Route path={`/doc/${slug}`}>
location={location} <SidebarRight>
key={ <React.Suspense fallback={null}>
matchPath(location.pathname, { {showHistory && <DocumentHistory />}
path: matchDocumentHistory, {showInsights && <DocumentInsights />}
}) </React.Suspense>
? "history" </SidebarRight>
: location.pathname </Route>
} )}
> </AnimatePresence>
<Route
key="document-history"
path={`/doc/${slug}/history/:revisionId?`}
component={DocumentHistory}
/>
<Route
key="document-history"
path={`/doc/${slug}/insights`}
component={DocumentInsights}
/>
</Switch>
</AnimatePresence>
</React.Suspense>
); );
return ( return (

View File

@@ -1,27 +1,19 @@
import { m } from "framer-motion"; import { m } from "framer-motion";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import { BackIcon } from "outline-icons";
import * as React from "react"; import * as React from "react";
import { useTranslation } from "react-i18next";
import styled, { useTheme } from "styled-components"; import styled, { useTheme } from "styled-components";
import breakpoint from "styled-components-breakpoint"; import breakpoint from "styled-components-breakpoint";
import Button from "~/components/Button";
import Flex from "~/components/Flex"; import Flex from "~/components/Flex";
import Scrollable from "~/components/Scrollable";
import ResizeBorder from "~/components/Sidebar/components/ResizeBorder"; import ResizeBorder from "~/components/Sidebar/components/ResizeBorder";
import Tooltip from "~/components/Tooltip";
import usePersistedState from "~/hooks/usePersistedState"; import usePersistedState from "~/hooks/usePersistedState";
type Props = React.HTMLAttributes<HTMLDivElement> & { type Props = React.HTMLAttributes<HTMLDivElement> & {
title: React.ReactNode;
children: React.ReactNode; children: React.ReactNode;
onClose: React.MouseEventHandler;
border?: boolean; border?: boolean;
}; };
function RightSidebar({ title, onClose, children, border, className }: Props) { function Right({ children, border, className }: Props) {
const theme = useTheme(); const theme = useTheme();
const { t } = useTranslation();
const [width, setWidth] = usePersistedState( const [width, setWidth] = usePersistedState(
"rightSidebarWidth", "rightSidebarWidth",
theme.sidebarWidth theme.sidebarWidth
@@ -101,18 +93,7 @@ function RightSidebar({ title, onClose, children, border, className }: Props) {
className={className} className={className}
> >
<Position style={style} column> <Position style={style} column>
<Header> {children}
<Title>{title}</Title>
<Tooltip tooltip={t("Close")} shortcut="Esc" delay={500}>
<Button
icon={<ForwardIcon />}
onClick={onClose}
borderOnHover
neutral
/>
</Tooltip>
</Header>
<Scrollable topShadow>{children}</Scrollable>
<ResizeBorder <ResizeBorder
onMouseDown={handleMouseDown} onMouseDown={handleMouseDown}
onDoubleClick={handleReset} onDoubleClick={handleReset}
@@ -123,11 +104,6 @@ function RightSidebar({ title, onClose, children, border, className }: Props) {
); );
} }
const ForwardIcon = styled(BackIcon)`
transform: rotate(180deg);
flex-shrink: 0;
`;
const Position = styled(Flex)` const Position = styled(Flex)`
position: fixed; position: fixed;
top: 0; top: 0;
@@ -149,26 +125,4 @@ const Sidebar = styled(m.div)<{ $border?: boolean }>`
`}; `};
`; `;
const Title = styled(Flex)` export default observer(Right);
font-size: 16px;
font-weight: 600;
text-align: center;
align-items: center;
justify-content: flex-start;
text-overflow: ellipsis;
white-space: nowrap;
user-select: none;
overflow: hidden;
width: 0;
flex-grow: 1;
`;
const Header = styled(Flex)`
align-items: center;
position: relative;
padding: 16px 12px 16px 16px;
color: ${(props) => props.theme.text};
flex-shrink: 0;
`;
export default observer(RightSidebar);

View File

@@ -9,7 +9,7 @@ import PaginatedEventList from "~/components/PaginatedEventList";
import useKeyDown from "~/hooks/useKeyDown"; import useKeyDown from "~/hooks/useKeyDown";
import useStores from "~/hooks/useStores"; import useStores from "~/hooks/useStores";
import { documentUrl } from "~/utils/routeHelpers"; import { documentUrl } from "~/utils/routeHelpers";
import Sidebar from "./RightSidebar"; import Sidebar from "./SidebarLayout";
const EMPTY_ARRAY: Event[] = []; const EMPTY_ARRAY: Event[] = [];

View File

@@ -17,7 +17,7 @@ import useKeyDown from "~/hooks/useKeyDown";
import useStores from "~/hooks/useStores"; import useStores from "~/hooks/useStores";
import useTextSelection from "~/hooks/useTextSelection"; import useTextSelection from "~/hooks/useTextSelection";
import { documentUrl } from "~/utils/routeHelpers"; import { documentUrl } from "~/utils/routeHelpers";
import Sidebar from "./RightSidebar"; import Sidebar from "./SidebarLayout";
function Insights() { function Insights() {
const { views, documents } = useStores(); const { views, documents } = useStores();

View File

@@ -0,0 +1,66 @@
import { observer } from "mobx-react";
import { BackIcon } from "outline-icons";
import * as React from "react";
import { useTranslation } from "react-i18next";
import styled from "styled-components";
import Button from "~/components/Button";
import Flex from "~/components/Flex";
import Scrollable from "~/components/Scrollable";
import Tooltip from "~/components/Tooltip";
type Props = React.HTMLAttributes<HTMLDivElement> & {
title: React.ReactNode;
children: React.ReactNode;
onClose: React.MouseEventHandler;
border?: boolean;
};
function SidebarLayout({ title, onClose, children }: Props) {
const { t } = useTranslation();
return (
<>
<Header>
<Title>{title}</Title>
<Tooltip tooltip={t("Close")} shortcut="Esc" delay={500}>
<Button
icon={<ForwardIcon />}
onClick={onClose}
borderOnHover
neutral
/>
</Tooltip>
</Header>
<Scrollable topShadow>{children}</Scrollable>
</>
);
}
const ForwardIcon = styled(BackIcon)`
transform: rotate(180deg);
flex-shrink: 0;
`;
const Title = styled(Flex)`
font-size: 16px;
font-weight: 600;
text-align: center;
align-items: center;
justify-content: flex-start;
text-overflow: ellipsis;
white-space: nowrap;
user-select: none;
overflow: hidden;
width: 0;
flex-grow: 1;
`;
const Header = styled(Flex)`
align-items: center;
position: relative;
padding: 16px 12px 16px 16px;
color: ${(props) => props.theme.text};
flex-shrink: 0;
`;
export default observer(SidebarLayout);

View File

@@ -139,3 +139,5 @@ export const matchDocumentSlug =
export const matchDocumentEdit = `/doc/${matchDocumentSlug}/edit`; export const matchDocumentEdit = `/doc/${matchDocumentSlug}/edit`;
export const matchDocumentHistory = `/doc/${matchDocumentSlug}/history/:revisionId?`; export const matchDocumentHistory = `/doc/${matchDocumentSlug}/history/:revisionId?`;
export const matchDocumentInsights = `/doc/${matchDocumentSlug}/insights`;

View File

@@ -465,7 +465,6 @@
"Deleted by {{userName}}": "Deleted by {{userName}}", "Deleted by {{userName}}": "Deleted by {{userName}}",
"Observing {{ userName }}": "Observing {{ userName }}", "Observing {{ userName }}": "Observing {{ userName }}",
"Backlinks": "Backlinks", "Backlinks": "Backlinks",
"Close": "Close",
"Anyone with the link <1></1>can view this document": "Anyone with the link <1></1>can view this document", "Anyone with the link <1></1>can view this document": "Anyone with the link <1></1>can view this document",
"Share": "Share", "Share": "Share",
"Share this document": "Share this document", "Share this document": "Share this document",
@@ -481,6 +480,7 @@
"Users with edit permission will be redirected to the main app": "Users with edit permission will be redirected to the main app", "Users with edit permission will be redirected to the main app": "Users with edit permission will be redirected to the main app",
"All users see the same publicly shared view": "All users see the same publicly shared view", "All users see the same publicly shared view": "All users see the same publicly shared view",
"More options": "More options", "More options": "More options",
"Close": "Close",
"{{ teamName }} is using Outline to share documents, please login to continue.": "{{ teamName }} is using Outline to share documents, please login to continue.", "{{ teamName }} is using Outline to share documents, please login to continue.": "{{ teamName }} is using Outline to share documents, please login to continue.",
"Are you sure you want to delete the <em>{{ documentTitle }}</em> template?": "Are you sure you want to delete the <em>{{ documentTitle }}</em> template?", "Are you sure you want to delete the <em>{{ documentTitle }}</em> template?": "Are you sure you want to delete the <em>{{ documentTitle }}</em> template?",
"Are you sure about that? Deleting the <em>{{ documentTitle }}</em> document will delete all of its history</em>.": "Are you sure about that? Deleting the <em>{{ documentTitle }}</em> document will delete all of its history</em>.", "Are you sure about that? Deleting the <em>{{ documentTitle }}</em> document will delete all of its history</em>.": "Are you sure about that? Deleting the <em>{{ documentTitle }}</em> document will delete all of its history</em>.",