From cf9fd767f3299ecbf17f841144a015f696a8bb3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi?= Date: Tue, 7 Jan 2025 16:58:34 +0100 Subject: [PATCH] feat: update Sidebar component for improved responsiveness and menu interaction; add showTitle prop to SidebarItem --- package.json | 2 +- src/app/admin/layout.tsx | 11 +- src/app/components/Sidebar/index.tsx | 153 ++++++++++----------------- src/app/components/Sidebar/item.tsx | 18 ++-- 4 files changed, 77 insertions(+), 107 deletions(-) diff --git a/package.json b/package.json index d32c0d4..26bc52e 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "version": "0.1.0", "private": true, "scripts": { - "dev": "next dev -p 4000", + "dev": "next dev --turbopack -p 4000", "build": "next build", "build:docker": "docker build -t toogether/webapp .", "start": "next start -p 4000", diff --git a/src/app/admin/layout.tsx b/src/app/admin/layout.tsx index 15678e0..e85e057 100644 --- a/src/app/admin/layout.tsx +++ b/src/app/admin/layout.tsx @@ -6,6 +6,7 @@ import { FaDoorClosed, FaRegUser } from "react-icons/fa"; import { FiSettings } from "react-icons/fi"; import { IoMdStats } from "react-icons/io"; import { MdInbox } from "react-icons/md"; +import { SidebarItemProps } from "../components/Sidebar/item"; export default function Layout({ children }: { children: React.ReactNode }) { const pathName = usePathname(); @@ -17,8 +18,14 @@ export default function Layout({ children }: { children: React.ReactNode }) { { href: "/admin/classes", title: "Classes", icon: }, { href: "/admin/rooms", title: "Rooms", icon: }, ], - [{ href: "/admin/settings", title: "Settings", icon: }], - ]; + [ + { + href: "/admin/settings", + title: "Settings", + icon: , + }, + ], + ] as SidebarItemProps[][]; return (
diff --git a/src/app/components/Sidebar/index.tsx b/src/app/components/Sidebar/index.tsx index 87ee3c1..76e6577 100644 --- a/src/app/components/Sidebar/index.tsx +++ b/src/app/components/Sidebar/index.tsx @@ -1,9 +1,10 @@ -"use client"; - import { Divider, Link } from "@nextui-org/react"; import { usePathname, useRouter } from "next/navigation"; -import { useEffect, useRef, useState } from "react"; -import { BsChevronDoubleRight } from "react-icons/bs"; +import { useEffect, useState } from "react"; +import { + BsLayoutSidebarInset, + BsReverseLayoutSidebarInsetReverse, +} from "react-icons/bs"; import { ThemeSwitcher } from "../ThemeSwitcher/ThemeSwitcher"; import { SidebarItem } from "./item"; @@ -18,141 +19,99 @@ export const Sidebar = ({ }) => { const router = useRouter(); const pathName = usePathname(); - const sidebarRef = useRef(null); // State to manage menu openness - const [open, setOpen] = useState(false); - const [startX, setStartX] = useState(0); - const [isSwiping, setIsSwiping] = useState(false); + const [open, setOpen] = useState(true); + const [isMobile, setIsMobile] = useState(false); - // Effect to manage responsiveness useEffect(() => { const handleResize = () => { - if (window.innerWidth >= 1024) { - setOpen(true); // Menu always open on larger screens - } else { - setOpen(false); // Menu closed by default on smaller screens + if (window.innerWidth <= 1024 && !isMobile) { + setIsMobile(true); + } else if (window.innerWidth > 1024 && isMobile) { + setIsMobile(false); } }; - handleResize(); // Set initial state based on current window size + handleResize(); window.addEventListener("resize", handleResize); - return () => window.removeEventListener("resize", handleResize); - }, []); + }); - // Effect to close the menu when clicking outside useEffect(() => { - const handleClickOutside = (event: MouseEvent) => { - if (sidebarRef.current && !sidebarRef.current.contains(event.target as Node)) { - setOpen(false); // Close the menu if clicked outside - } - }; - - document.addEventListener("click", handleClickOutside); - - // Cleanup the event listener when component unmounts - return () => { - document.removeEventListener("click", handleClickOutside); - }; - }, []); - - // Handle swipe start (touchstart event) - const handleTouchStart = (e: React.TouchEvent) => { - const touchStart = e.touches[0].clientX; - setStartX(touchStart); - setIsSwiping(true); - }; - - // Handle swipe move (touchmove event) - const handleTouchMove = (e: React.TouchEvent) => { - if (!isSwiping) return; - const touchMove = e.touches[0].clientX; - const distance = touchMove - startX; - - if (distance > 50 && !open) { - setOpen(true); // Open the menu if swiping right - } else if (distance < -50 && open) { - setOpen(false); // Close the menu if swiping left + if (isMobile) { + setOpen(false); } - }; - - // Handle swipe end (touchend event) - const handleTouchEnd = () => { - setIsSwiping(false); - }; + }, [isMobile]); return (