resizeable tree (#1084)

This commit is contained in:
Athou
2023-06-16 21:24:34 +02:00
parent 6944d4dc0b
commit d1ddcb6ace
6 changed files with 63 additions and 20 deletions

View File

@@ -16,7 +16,7 @@ import {
import { useViewportSize } from "@mantine/hooks"
import { Constants } from "app/constants"
import { redirectToAdd, redirectToRootCategory } from "app/slices/redirect"
import { reloadTree, setMobileMenuOpen } from "app/slices/tree"
import { reloadTree, setMobileMenuOpen, setSidebarWidth } from "app/slices/tree"
import { reloadProfile, reloadSettings, reloadTags } from "app/slices/user"
import { useAppDispatch, useAppSelector } from "app/store"
import { Loader } from "components/Loader"
@@ -26,28 +26,34 @@ import { OnMobile } from "components/responsive/OnMobile"
import { useAppLoading } from "hooks/useAppLoading"
import { useWebSocket } from "hooks/useWebSocket"
import { LoadingPage } from "pages/LoadingPage"
import { Resizable } from "re-resizable"
import { ReactNode, Suspense, useEffect } from "react"
import { TbPlus } from "react-icons/tb"
import { Outlet } from "react-router-dom"
interface LayoutProps {
sidebar: ReactNode
sidebarWidth: number
header: ReactNode
}
const sidebarPadding = DEFAULT_THEME.spacing.xs
const sidebarRightBorderWidth = "1px"
const useStyles = createStyles(theme => ({
const useStyles = createStyles((theme, props: LayoutProps) => ({
sidebarContentResizeWrapper: {
padding: sidebarPadding,
minHeight: "100vh",
},
sidebarContent: {
maxWidth: `calc(${Constants.layout.sidebarWidth}px - ${sidebarPadding} * 2 - ${sidebarRightBorderWidth})`,
maxWidth: `calc(${props.sidebarWidth}px - ${sidebarPadding} * 2 - ${sidebarRightBorderWidth})`,
[theme.fn.smallerThan(Constants.layout.mobileBreakpoint)]: {
maxWidth: `calc(100vw - ${sidebarPadding} * 2 - ${sidebarRightBorderWidth})`,
},
},
mainContentWrapper: {
paddingTop: Constants.layout.headerHeight,
paddingLeft: Constants.layout.sidebarWidth,
paddingLeft: props.sidebarWidth,
paddingRight: 0,
paddingBottom: 0,
[theme.fn.smallerThan(Constants.layout.mobileBreakpoint)]: {
@@ -55,7 +61,7 @@ const useStyles = createStyles(theme => ({
},
},
mainContent: {
maxWidth: `calc(100vw - ${Constants.layout.sidebarWidth}px)`,
maxWidth: `calc(100vw - ${props.sidebarWidth}px)`,
padding: theme.spacing.md,
[theme.fn.smallerThan(Constants.layout.mobileBreakpoint)]: {
maxWidth: "100vw",
@@ -76,8 +82,8 @@ function LogoAndTitle() {
)
}
export default function Layout({ sidebar, header }: LayoutProps) {
const { classes } = useStyles()
export default function Layout(props: LayoutProps) {
const { classes } = useStyles(props)
const theme = useMantineTheme()
const viewport = useViewportSize()
const { loading } = useAppLoading()
@@ -85,6 +91,8 @@ export default function Layout({ sidebar, header }: LayoutProps) {
const dispatch = useAppDispatch()
useWebSocket()
const handleResize = (element: HTMLElement) => dispatch(setSidebarWidth(element.offsetWidth))
useEffect(() => {
dispatch(reloadSettings())
dispatch(reloadProfile())
@@ -122,14 +130,30 @@ export default function Layout({ sidebar, header }: LayoutProps) {
navbar={
<Navbar
id="sidebar"
p={sidebarPadding}
hiddenBreakpoint={Constants.layout.mobileBreakpoint}
hidden={!mobileMenuOpen}
width={{ md: Constants.layout.sidebarWidth }}
width={{ md: props.sidebarWidth }}
>
<Navbar.Section grow component={ScrollArea} mx="-xs" px="xs">
<Box className={classes.sidebarContent}>{sidebar}</Box>
</Navbar.Section>
<Resizable
enable={{
top: false,
right: true,
bottom: false,
left: false,
topRight: false,
bottomRight: false,
bottomLeft: false,
topLeft: false,
}}
onResize={(e, dir, el) => handleResize(el)}
minWidth={120}
>
<Box className={classes.sidebarContentResizeWrapper}>
<Navbar.Section grow component={ScrollArea} mx="-xs" px="xs">
<Box className={classes.sidebarContent}>{props.sidebar}</Box>
</Navbar.Section>
</Box>
</Resizable>
</Navbar>
}
header={
@@ -147,19 +171,19 @@ export default function Layout({ sidebar, header }: LayoutProps) {
{!mobileMenuOpen && (
<Group>
<Box mr="sm">{burger}</Box>
<Box sx={{ flexGrow: 1 }}>{header}</Box>
<Box sx={{ flexGrow: 1 }}>{props.header}</Box>
</Group>
)}
</OnMobile>
<OnDesktop>
<Group>
<Group position="apart" sx={{ width: Constants.layout.sidebarWidth - 16 }}>
<Group position="apart" sx={{ width: props.sidebarWidth - 16 }}>
<Box>
<LogoAndTitle />
</Box>
<Box>{addButton}</Box>
</Group>
<Box sx={{ flexGrow: 1 }}>{header}</Box>
<Box sx={{ flexGrow: 1 }}>{props.header}</Box>
</Group>
</OnDesktop>
</Header>