Sidebar improvements from comments branch (#4419)
This commit is contained in:
@@ -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 (
|
||||||
|
|||||||
@@ -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);
|
|
||||||
@@ -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[] = [];
|
||||||
|
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
66
app/scenes/Document/components/SidebarLayout.tsx
Normal file
66
app/scenes/Document/components/SidebarLayout.tsx
Normal 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);
|
||||||
@@ -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`;
|
||||||
|
|||||||
@@ -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>.",
|
||||||
|
|||||||
Reference in New Issue
Block a user