mirror of
https://github.com/docmost/docmost.git
synced 2026-08-31 02:46:27 +08:00
feat(share): support resizing sidebar on shared pages
This commit is contained in:
@@ -6,6 +6,6 @@ import { SharedPageTreeNode } from "@/features/share/utils";
|
|||||||
export const sharedPageTreeAtom = atom<ISharedPageTree | null>(null);
|
export const sharedPageTreeAtom = atom<ISharedPageTree | null>(null);
|
||||||
export const sharedTreeDataAtom = atom<SharedPageTreeNode[] | null>(null);
|
export const sharedTreeDataAtom = atom<SharedPageTreeNode[] | null>(null);
|
||||||
export const sharedPageFullWidthAtom = atomWithStorage<boolean>(
|
export const sharedPageFullWidthAtom = atomWithStorage<boolean>(
|
||||||
"shared-page-full-width",
|
"sharedPageFullWidth",
|
||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, { useEffect, useMemo } from "react";
|
import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||||
import {
|
import {
|
||||||
ActionIcon,
|
ActionIcon,
|
||||||
AppShell,
|
AppShell,
|
||||||
@@ -23,6 +23,7 @@ import { buildSharedPageTree } from "@/features/share/utils";
|
|||||||
import {
|
import {
|
||||||
desktopSidebarAtom,
|
desktopSidebarAtom,
|
||||||
mobileSidebarAtom,
|
mobileSidebarAtom,
|
||||||
|
sidebarWidthAtom,
|
||||||
} from "@/components/layouts/global/hooks/atoms/sidebar-atom.ts";
|
} from "@/components/layouts/global/hooks/atoms/sidebar-atom.ts";
|
||||||
import SidebarToggle from "@/components/ui/sidebar-toggle-button.tsx";
|
import SidebarToggle from "@/components/ui/sidebar-toggle-button.tsx";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
@@ -60,6 +61,45 @@ export default function ShareShell({
|
|||||||
const toggleTocMobile = useToggleToc(mobileTableOfContentAsideAtom);
|
const toggleTocMobile = useToggleToc(mobileTableOfContentAsideAtom);
|
||||||
const toggleToc = useToggleToc(tableOfContentAsideAtom);
|
const toggleToc = useToggleToc(tableOfContentAsideAtom);
|
||||||
const [fullWidth, setFullWidth] = useAtom(sharedPageFullWidthAtom);
|
const [fullWidth, setFullWidth] = useAtom(sharedPageFullWidthAtom);
|
||||||
|
const [sidebarWidth, setSidebarWidth] = useAtom(sidebarWidthAtom);
|
||||||
|
const [isResizing, setIsResizing] = useState(false);
|
||||||
|
const sidebarRef = useRef<HTMLElement | null>(null);
|
||||||
|
|
||||||
|
const startResizing = useCallback((e: React.MouseEvent) => {
|
||||||
|
e.preventDefault();
|
||||||
|
setIsResizing(true);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const stopResizing = useCallback(() => {
|
||||||
|
setIsResizing(false);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const resize = useCallback(
|
||||||
|
(e: MouseEvent) => {
|
||||||
|
if (!isResizing || !sidebarRef.current) return;
|
||||||
|
const newWidth =
|
||||||
|
e.clientX - sidebarRef.current.getBoundingClientRect().left;
|
||||||
|
if (newWidth < 220) {
|
||||||
|
setSidebarWidth(220);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (newWidth > 600) {
|
||||||
|
setSidebarWidth(600);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setSidebarWidth(newWidth);
|
||||||
|
},
|
||||||
|
[isResizing, setSidebarWidth],
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
window.addEventListener("mousemove", resize);
|
||||||
|
window.addEventListener("mouseup", stopResizing);
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener("mousemove", resize);
|
||||||
|
window.removeEventListener("mouseup", stopResizing);
|
||||||
|
};
|
||||||
|
}, [resize, stopResizing]);
|
||||||
|
|
||||||
const { shareId } = useParams();
|
const { shareId } = useParams();
|
||||||
const { data } = useGetSharedPageTreeQuery(shareId);
|
const { data } = useGetSharedPageTreeQuery(shareId);
|
||||||
@@ -86,7 +126,7 @@ export default function ShareShell({
|
|||||||
header={{ height: 50 }}
|
header={{ height: 50 }}
|
||||||
{...(data?.pageTree?.length > 1 && {
|
{...(data?.pageTree?.length > 1 && {
|
||||||
navbar: {
|
navbar: {
|
||||||
width: 300,
|
width: sidebarWidth,
|
||||||
breakpoint: "sm",
|
breakpoint: "sm",
|
||||||
collapsed: {
|
collapsed: {
|
||||||
mobile: !mobileOpened,
|
mobile: !mobileOpened,
|
||||||
@@ -193,7 +233,11 @@ export default function ShareShell({
|
|||||||
</AppShell.Header>
|
</AppShell.Header>
|
||||||
|
|
||||||
{data?.pageTree?.length > 1 && (
|
{data?.pageTree?.length > 1 && (
|
||||||
<AppShell.Navbar p="md" className={classes.navbar}>
|
<AppShell.Navbar p="md" className={classes.navbar} ref={sidebarRef}>
|
||||||
|
<div
|
||||||
|
className={classes.resizeHandle}
|
||||||
|
onMouseDown={startResizing}
|
||||||
|
/>
|
||||||
<MemoizedSharedTree sharedPageTree={data} />
|
<MemoizedSharedTree sharedPageTree={data} />
|
||||||
</AppShell.Navbar>
|
</AppShell.Navbar>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -18,3 +18,26 @@
|
|||||||
width: 350px;
|
width: 350px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.resizeHandle {
|
||||||
|
width: 3px;
|
||||||
|
cursor: col-resize;
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
z-index: 1;
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
&:active {
|
||||||
|
width: 5px;
|
||||||
|
background: light-dark(
|
||||||
|
var(--mantine-color-gray-4),
|
||||||
|
var(--mantine-color-dark-5)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: $mantine-breakpoint-sm) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user