diff --git a/client/src/components/layout/Sidebar.jsx b/client/src/components/layout/Sidebar.jsx index 5188882..2ea67ef 100644 --- a/client/src/components/layout/Sidebar.jsx +++ b/client/src/components/layout/Sidebar.jsx @@ -1,22 +1,24 @@ -import { useSlotRecipe, Box, Button, IconButton } from "@chakra-ui/react"; -import { ColorModeButton } from "@/components/ui/color-mode.jsx"; -import { useState } from "react"; -import { NavLink } from "react-router-dom"; +import {useSlotRecipe, Box, Button, IconButton} from "@chakra-ui/react"; +import {ColorModeButton} from "@/components/ui/color-mode.jsx"; +import {useState} from "react"; +import {NavLink} from "react-router-dom"; import Tooltip from "../ui/Tooltip.jsx"; -import { Mountain, House, Earth, MapPin, ShieldUser, Menu, PanelLeftClose, PanelLeftOpen } from 'lucide-react'; +import {Mountain, House, Earth, MapPin, ShieldUser, Menu, PanelLeftClose, PanelLeftOpen} from 'lucide-react'; const SIDEBAR_DEFAULT_BUTTONS = [ - { icon: House, name: "Home", url: "/home" }, - { icon: Earth, name: "Global Map", url: "/global-map" }, - { icon: MapPin, name: "Regional Map", url: "/regional-map" }, - { icon: Mountain, name: "Volcano", url: "/volcano" }, - { icon: ShieldUser, name: "Admin", url: "/admin" } // TODO remove in the future as default should not have admin + {icon: House, name: "Home", url: "/home"}, + {icon: Earth, name: "Global Map", url: "/global-map"}, + {icon: MapPin, name: "Regional Map", url: "/regional-map"}, + {icon: Mountain, name: "Volcano", url: "/volcano"}, + {icon: ShieldUser, name: "Admin", url: "/admin"} // TODO remove in the future as default should not have admin ]; export default function Sidebar() { + const [isOpen, setIsOpen] = useState(true); - const recipe = useSlotRecipe({ key: "sidebar" }); - const styles = recipe(); + + const recipe = useSlotRecipe({key: "sidebar"}); + const styles = recipe({state: isOpen ? "open" : "closed"}); // TODO we will need to call buttons here by authorized user, for now we update the visible buttons as simply the default buttons const visibleButtons = SIDEBAR_DEFAULT_BUTTONS; @@ -24,87 +26,46 @@ export default function Sidebar() { const toggleSidebar = () => setIsOpen((prev) => !prev); return ( - + {/* Home Link Logo */} + - - - - {/* Navigation Buttons */} - {visibleButtons.map((button) => { - const Icon = button.icon; - return ( - // - - // - ); - })} - - {/* Menu Trigger */} - - {isOpen ? : } - + {/* Navigation buttons are [icon text] */} + + + {button.name} + + + ); + })} + + {/* Menu Trigger */} + + {isOpen ? : } + {/* Theme Toggler */} diff --git a/client/src/theme.js b/client/src/theme.js index d59c24f..a68768d 100644 --- a/client/src/theme.js +++ b/client/src/theme.js @@ -29,7 +29,7 @@ const canvasRecipe = defineRecipe({ }); const sidebarRecipe = defineSlotRecipe({ - slots: ["root", "close_button", "buttons", "dark_mode_button"], + slots: ["root", "logo", "footer", "button_text","buttons", "collapse_button"], base: { root: { // 1. Semi-transparent backgrounds @@ -57,14 +57,17 @@ const sidebarRecipe = defineSlotRecipe({ margin: "8px", display: "flex", flexDirection: "column", + position: "relative", justifyContent: "start", alignItems: "stretch", - gap: 2, + gap: 4, + transition: "width 0.4s ease", // CRITICAL: Adjust padding and overflow to allow the button to touch the right edge pl: 2, // Keep left padding py: 2, // Keep top/bottom padding pr: 0, // Remove right padding + pt: 4, // Added top padding to give the logo room to breathe overflow: "visible", // Allows the curved corner patches to render outside the button zIndex: 10, }, @@ -72,10 +75,12 @@ const sidebarRecipe = defineSlotRecipe({ position: "relative", // Required to anchor the corner patches bg: "transparent", + justifyContent: "flex-start", transition: "background-color 0.4s ease, color 0.4s ease", "& svg": { - transition: "stroke-width 0.4s ease" + transition: "stroke-width 0.4s ease", + flexShrink: "0" }, _hover: { @@ -138,6 +143,45 @@ const sidebarRecipe = defineSlotRecipe({ } }, }, + logo: { + width: "100%", + height: "auto", + overflow: "hidden", + fontWeight: "bold", + px: 0, + }, + footer: { + mt: "auto", + display: "flex", + justifyContent: "center", + alignItems: "center", + pb: 4, + pr: 2, + transition: "opacity 0.3s ease, visibility 0.3s ease, margin 0.3s ease" + }, + button_text: { + transition: "opacity 0.3s ease, visibility 0.3s ease, margin 0.3s ease", + whiteSpace: "nowrap" + }, + collapse_button: { + "& svg": { flexShrink: "0" }, + }, + }, + variants: { + state: { + open: { + root: { width: "190px" }, + logo: { justifyContent: "flex-start", ml: 2, textStyle: "4xl" }, + footer: { gap: 16, flexDirection: "row" }, + button_text: {ml: 3, opacity: 1, visibility: "visible"}, + }, + closed: { + root: { width: "71px" }, + logo: { justifyContent: "center", ml: -1, textStyle: "3xl" }, + footer: { gap: 2, flexDirection: "column-reverse" }, + button_text: {ml: 0, opacity: 0, visibility: "hidden"}, + } + } } });