Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Always closes sidebar animated on mobile #80

Merged
merged 5 commits into from
Oct 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/common/state/sidebarOpen.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { useSessionStorage } from "usehooks-ts"

export default function useSidebarOpen() {
return useSessionStorage("isSidebarOpen", true)
}
5 changes: 5 additions & 0 deletions src/common/state/useSidebarOpen.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { useSessionStorage } from "usehooks-ts"

export default function useSidebarOpen() {
return useSessionStorage("isSidebarOpen", true)
}
20 changes: 15 additions & 5 deletions src/features/projects/view/client/ProjectsPage.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use client"

import { useState, useEffect } from "react"
import { useEffect } from "react"
import { useRouter } from "next/navigation"
import { useTheme } from "@mui/material/styles"
import useMediaQuery from "@mui/material/useMediaQuery"
Expand All @@ -14,6 +14,7 @@ import getSelection from "../../domain/getSelection"
import projectNavigator from "../../domain/projectNavigator"
import updateWindowTitle from "../../domain/updateWindowTitle"
import useProjects from "../../data/useProjects"
import useSidebarOpen from "@/common/state/useSidebarOpen"

export default function ProjectsPage({
projects: serverProjects,
Expand All @@ -28,9 +29,9 @@ export default function ProjectsPage({
}) {
const router = useRouter()
const theme = useTheme()
const [isSidebarOpen, setSidebarOpen] = useSidebarOpen()
const isDesktopLayout = useMediaQuery(theme.breakpoints.up("sm"))
const { projects: clientProjects, error, isLoading: isClientLoading } = useProjects()
const [forceCloseSidebar, setForceCloseSidebar] = useState(false)
const projects = isClientLoading ? (serverProjects || []) : clientProjects
const { project, version, specification } = getSelection({
projects,
Expand All @@ -57,8 +58,16 @@ export default function ProjectsPage({
}
projectNavigator.navigateIfNeeded(router, urlSelection, selection)
}, [router, projectId, versionId, specificationId, project, version, specification])
useEffect(() => {
// Show the sidebar if no project is selected.
if (projectId === undefined) {
setSidebarOpen(true)
}
}, [projectId, setSidebarOpen])
const selectProject = (project: Project) => {
setForceCloseSidebar(!isDesktopLayout)
if (!isDesktopLayout) {
setSidebarOpen(false)
}
const version = project.versions[0]
const specification = version.specifications[0]
projectNavigator.navigate(router, project.id, version.id, specification.id)
Expand All @@ -71,8 +80,9 @@ export default function ProjectsPage({
}
return (
<SidebarContainer
canCloseDrawer={projectId !== undefined}
forceClose={forceCloseSidebar}
isCloseSidebarEnabled={projectId !== undefined}
isSidebarOpen={isSidebarOpen}
onToggleSidebarOpen={setSidebarOpen}
sidebar={
<ProjectList
isLoading={serverProjects === undefined && isClientLoading}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
"use client"

import { ReactNode } from "react"
import { Box } from "@mui/material"
import { useTheme } from "@mui/material/styles"
Expand Down
8 changes: 4 additions & 4 deletions src/features/sidebar/view/base/PrimaryHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ import { Box, IconButton } from "@mui/material"
import ChevronLeftIcon from "@mui/icons-material/ChevronLeft"

export default function PrimaryHeader({
canCloseDrawer,
isCloseEnabled,
width,
onClose,
children
}: {
canCloseDrawer: boolean,
isCloseEnabled: boolean,
width: number,
onClose: () => void
children?: ReactNode
Expand All @@ -18,10 +18,10 @@ export default function PrimaryHeader({
<IconButton
onClick={onClose}
edge="start"
disabled={!canCloseDrawer}
disabled={!isCloseEnabled}
sx={{
zIndex: 1000,
opacity: canCloseDrawer ? 1 : 0
opacity: isCloseEnabled ? 1 : 0
}}
>
<ChevronLeftIcon/>
Expand Down
12 changes: 6 additions & 6 deletions src/features/sidebar/view/base/SecondaryHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ import { useTheme } from "@mui/material/styles"
import MenuIcon from "@mui/icons-material/Menu"

export default function SecondaryHeader({
showOpenDrawer,
onOpenDrawer,
isOpenSidebarEnabled,
onOpenSidebar,
trailingItem,
children,
sx
}: {
showOpenDrawer: boolean
onOpenDrawer: () => void
isOpenSidebarEnabled: boolean
onOpenSidebar: () => void
trailingItem?: ReactNode
children?: ReactNode
sx?: SxProps
Expand All @@ -29,12 +29,12 @@ export default function SecondaryHeader({
<Box sx={{ display: "flex", alignItems: "center", padding: 2 }}>
<IconButton
color="inherit"
onClick={onOpenDrawer}
onClick={onOpenSidebar}
edge="start"
sx={{
mr: 2,
color: theme.palette.text.primary,
...(!showOpenDrawer && { visibility: "hidden" })
...(!isOpenSidebarEnabled && { visibility: "hidden" })
}}
>
<MenuIcon/>
Expand Down
24 changes: 12 additions & 12 deletions src/features/sidebar/view/base/SecondaryWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,19 @@ import { Stack } from "@mui/material"
import { styled } from "@mui/material/styles"

interface WrapperStackProps {
drawerWidth: number
isDrawerOpen: boolean
sidebarWidth: number
isSidebarOpen: boolean
}

const WrapperStack = styled(Stack, {
shouldForwardProp: (prop) => prop !== "isDrawerOpen"
})<WrapperStackProps>(({ theme, drawerWidth, isDrawerOpen }) => ({
shouldForwardProp: (prop) => prop !== "isSidebarOpen"
})<WrapperStackProps>(({ theme, sidebarWidth, isSidebarOpen }) => ({
transition: theme.transitions.create("margin", {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen
}),
marginLeft: `-${drawerWidth}px`,
...(isDrawerOpen && {
marginLeft: `-${sidebarWidth}px`,
...(isSidebarOpen && {
transition: theme.transitions.create("margin", {
easing: theme.transitions.easing.easeOut,
duration: theme.transitions.duration.enteringScreen,
Expand All @@ -26,22 +26,22 @@ const WrapperStack = styled(Stack, {
}))

export default function SecondaryWrapper({
drawerWidth,
isDrawerOpen,
sidebarWidth,
isSidebarOpen,
children,
sx
}: {
drawerWidth: number
isDrawerOpen: boolean
sidebarWidth: number
isSidebarOpen: boolean
children: ReactNode
sx?: SxProps
}) {
return (
<WrapperStack
direction="column"
spacing={0}
drawerWidth={drawerWidth}
isDrawerOpen={isDrawerOpen}
sidebarWidth={sidebarWidth}
isSidebarOpen={isSidebarOpen}
sx={{ ...sx, width: "100%", overflowY: "auto" }}
>
{children}
Expand Down
12 changes: 6 additions & 6 deletions src/features/sidebar/view/base/responsive/SecondaryHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@ import SecondaryHeader from "../SecondaryHeader"
import ExpandCircleDownIcon from "@mui/icons-material/ExpandCircleDown"

export default function ResponsiveSecondaryHeader({
showOpenDrawer,
onOpenDrawer,
isOpenSidebarEnabled,
onOpenSidebar,
showMobileToolbar,
onToggleMobileToolbar,
trailingItem,
mobileToolbar,
sx
}: {
showOpenDrawer: boolean
onOpenDrawer: () => void
isOpenSidebarEnabled: boolean
onOpenSidebar: () => void
showMobileToolbar: boolean
onToggleMobileToolbar: (showMobileToolbar: boolean) => void
trailingItem?: ReactNode
Expand All @@ -24,8 +24,8 @@ export default function ResponsiveSecondaryHeader({
return (
<SecondaryHeader
sx={sx}
showOpenDrawer={showOpenDrawer}
onOpenDrawer={onOpenDrawer}
isOpenSidebarEnabled={isOpenSidebarEnabled}
onOpenSidebar={onOpenSidebar}
trailingItem={
<Stack direction="row" alignItems="center">
{trailingItem}
Expand Down
14 changes: 7 additions & 7 deletions src/features/sidebar/view/base/responsive/SecondaryWrapper.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
import { ReactNode } from "react"
import SecondaryWrapper from "../SecondaryWrapper"

export default function ResponsiveDrawer({
drawerWidth,
export default function ResponsiveSecondaryWrapper({
sidebarWidth,
offsetContent,
children
}: {
drawerWidth: number
sidebarWidth: number
offsetContent: boolean
children: ReactNode
}) {
const sx = { overflow: "hidden" }
return (
<>
<SecondaryWrapper
drawerWidth={0}
isDrawerOpen={false}
sidebarWidth={0}
isSidebarOpen={false}
sx={{ ...sx, display: { xs: "flex", sm: "none" } }}
>
{children}
</SecondaryWrapper>
<SecondaryWrapper
drawerWidth={drawerWidth}
isDrawerOpen={offsetContent}
sidebarWidth={sidebarWidth}
isSidebarOpen={offsetContent}
sx={{ ...sx, display: { xs: "none", sm: "flex" } }}
>
{children}
Expand Down
28 changes: 14 additions & 14 deletions src/features/sidebar/view/base/responsive/SidebarContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,40 +5,40 @@ import PrimaryHeader from "../PrimaryHeader"
import SecondaryWrapper from "./SecondaryWrapper"

const SidebarContainer = ({
canCloseDrawer,
isDrawerOpen,
onToggleDrawerOpen,
isSidebarOpen,
isCloseSidebarEnabled,
onToggleSidebarOpen,
sidebarHeader,
sidebar,
header,
children
}: {
canCloseDrawer: boolean,
isDrawerOpen: boolean
onToggleDrawerOpen: (isDrawerOpen: boolean) => void
isSidebarOpen: boolean,
isCloseSidebarEnabled: boolean,
onToggleSidebarOpen: (isSidebarOpen: boolean) => void
sidebarHeader?: ReactNode
sidebar: ReactNode
header?: ReactNode
children?: ReactNode
}) => {
const drawerWidth = 320
const sidebarWidth = 320
return (
<Stack direction="row" spacing={0} sx={{ width: "100%", height: "100%" }}>
<Drawer
width={drawerWidth}
isOpen={isDrawerOpen}
onClose={() => onToggleDrawerOpen(false)}
width={sidebarWidth}
isOpen={isSidebarOpen}
onClose={() => onToggleSidebarOpen(false)}
>
<PrimaryHeader
width={drawerWidth}
canCloseDrawer={canCloseDrawer}
onClose={() => onToggleDrawerOpen(false)}
width={sidebarWidth}
isCloseEnabled={isCloseSidebarEnabled}
onClose={() => onToggleSidebarOpen(false)}
>
{sidebarHeader}
</PrimaryHeader>
{sidebar}
</Drawer>
<SecondaryWrapper drawerWidth={drawerWidth} offsetContent={isDrawerOpen}>
<SecondaryWrapper sidebarWidth={sidebarWidth} offsetContent={isSidebarOpen}>
{header}
<main style={{ flexGrow: "1", overflowY: "auto" }}>
{children}
Expand Down
33 changes: 12 additions & 21 deletions src/features/sidebar/view/client/SidebarContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,45 +1,36 @@
"use client"

import dynamic from "next/dynamic"
import { ReactNode, useEffect } from "react"
import { ReactNode } from "react"
import { useSessionStorage } from "usehooks-ts"
import ResponsiveSidebarContainer from "../base/responsive/SidebarContainer"
import ResponsiveSecondaryHeader from "../base/responsive/SecondaryHeader"
import Sidebar from "../Sidebar"
import SidebarHeader from "../SidebarHeader"

const SidebarContainer = ({
canCloseDrawer,
forceClose,
isSidebarOpen,
isCloseSidebarEnabled,
onToggleSidebarOpen,
sidebar,
children,
toolbarTrailingItem,
mobileToolbar
}: {
canCloseDrawer: boolean,
forceClose: boolean,
isSidebarOpen: boolean,
isCloseSidebarEnabled: boolean,
onToggleSidebarOpen: (isSidebarOpen: boolean) => void,
sidebar?: ReactNode
children?: ReactNode
toolbarTrailingItem?: ReactNode
mobileToolbar?: ReactNode
}) => {
const [open, setOpen] = useSessionStorage("isDrawerOpen", true)
const [showMobileToolbar, setShowMobileToolbar] = useSessionStorage("isMobileToolbarVisible", true)
useEffect(() => {
if (!canCloseDrawer) {
setOpen(true)
}
}, [canCloseDrawer, setOpen])
useEffect(() => {
if (forceClose) {
setOpen(false)
}
}, [forceClose, setOpen])
return (
<ResponsiveSidebarContainer
canCloseDrawer={canCloseDrawer}
isDrawerOpen={open || !canCloseDrawer}
onToggleDrawerOpen={setOpen}
isCloseSidebarEnabled={isCloseSidebarEnabled}
isSidebarOpen={isSidebarOpen}
onToggleSidebarOpen={onToggleSidebarOpen}
sidebarHeader={<SidebarHeader/>}
sidebar={
<Sidebar>
Expand All @@ -48,8 +39,8 @@ const SidebarContainer = ({
}
header={
<ResponsiveSecondaryHeader
showOpenDrawer={!open && canCloseDrawer}
onOpenDrawer={() => setOpen(true)}
isOpenSidebarEnabled={!isSidebarOpen}
onOpenSidebar={() => onToggleSidebarOpen(true)}
showMobileToolbar={showMobileToolbar}
onToggleMobileToolbar={setShowMobileToolbar}
trailingItem={toolbarTrailingItem}
Expand Down