2025-07-28 15:10:57 -07:00
|
|
|
import { useSlotRecipe, Box, Button, IconButton } from "@chakra-ui/react";
|
2026-06-10 14:00:37 -07:00
|
|
|
import { ColorModeButton } from "@/components/ui/color-mode.jsx";
|
2026-06-04 15:30:01 -07:00
|
|
|
import { useState } from "react";
|
|
|
|
|
import { NavLink } from "react-router-dom";
|
2026-06-10 14:00:37 -07:00
|
|
|
import Tooltip from "../ui/Tooltip.jsx";
|
2026-06-05 13:38:35 -07:00
|
|
|
import { Mountain, House, Earth, MapPin, ShieldUser, Menu } 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
|
|
|
|
|
];
|
2025-07-16 15:02:57 -07:00
|
|
|
|
2026-06-04 15:30:01 -07:00
|
|
|
export default function Sidebar() {
|
2025-07-16 15:02:57 -07:00
|
|
|
const [isOpen, setIsOpen] = useState(true);
|
2025-07-29 11:08:36 -07:00
|
|
|
const recipe = useSlotRecipe({ key: "sidebar" });
|
|
|
|
|
const styles = recipe();
|
2025-07-17 09:45:36 -07:00
|
|
|
|
2026-06-05 13:38:35 -07:00
|
|
|
// 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;
|
2026-06-04 15:30:01 -07:00
|
|
|
|
2026-06-05 13:38:35 -07:00
|
|
|
const toggleSidebar = () => setIsOpen((prev) => !prev);
|
2025-07-16 15:02:57 -07:00
|
|
|
|
|
|
|
|
return (
|
2026-07-22 10:37:01 -07:00
|
|
|
<Box
|
|
|
|
|
css={styles.root}
|
|
|
|
|
width={isOpen ? "210px" : "71px"}
|
|
|
|
|
transition="width 0.4s ease"
|
|
|
|
|
position="relative"
|
|
|
|
|
display="flex"
|
|
|
|
|
flexDirection="column"
|
|
|
|
|
gap={4} // Increased gap slightly to help with the squashed look
|
|
|
|
|
pt={4} // Added top padding to give the logo room to breathe
|
2026-06-05 13:38:35 -07:00
|
|
|
>
|
2026-07-22 10:37:01 -07:00
|
|
|
{/* Home Link Logo */}
|
|
|
|
|
<Button
|
|
|
|
|
as={NavLink}
|
|
|
|
|
to="/home"
|
|
|
|
|
color="color"
|
|
|
|
|
variant="plain"
|
|
|
|
|
fontWeight="bold"
|
|
|
|
|
height="auto" // Prevents the large text from squashing vertically
|
|
|
|
|
overflow="hidden"
|
|
|
|
|
px={0}
|
2026-07-22 14:58:59 -07:00
|
|
|
justifyContent={isOpen ? "center" : "center"} // Center the 'V' when collapsed
|
2026-07-22 10:37:01 -07:00
|
|
|
ml={isOpen ? 3 : 0} // Align with other buttons when open
|
2026-07-22 14:58:59 -07:00
|
|
|
textStyle={isOpen ? "4xl" : "3xl"} // Scale down slightly when closed
|
2026-07-22 10:37:01 -07:00
|
|
|
>
|
2026-07-22 14:58:59 -07:00
|
|
|
{isOpen ? "🌋 VDAP" : "🌋"}
|
2026-07-22 10:37:01 -07:00
|
|
|
</Button>
|
|
|
|
|
|
2026-06-05 13:38:35 -07:00
|
|
|
{/* Menu Trigger */}
|
2026-07-22 10:37:01 -07:00
|
|
|
<IconButton
|
|
|
|
|
aria-label="Toggle Sidebar"
|
|
|
|
|
variant="plain"
|
|
|
|
|
size="md"
|
|
|
|
|
onClick={toggleSidebar}
|
|
|
|
|
width="54px"
|
|
|
|
|
alignSelf={isOpen ? "flex-start" : "center"} // Center the icon when collapsed
|
|
|
|
|
ml={isOpen ? 3 : 0} // Align with other buttons when open
|
2026-06-05 13:38:35 -07:00
|
|
|
>
|
|
|
|
|
<Menu />
|
|
|
|
|
</IconButton>
|
2025-07-17 09:45:36 -07:00
|
|
|
|
2026-06-05 13:38:35 -07:00
|
|
|
{/* Navigation Buttons */}
|
|
|
|
|
{visibleButtons.map((button) => {
|
|
|
|
|
const Icon = button.icon;
|
|
|
|
|
return (
|
|
|
|
|
<Tooltip key={button.name} content={button.name} sidebarIsOpen={isOpen}>
|
|
|
|
|
<Button
|
|
|
|
|
as={NavLink}
|
|
|
|
|
to={button.url}
|
|
|
|
|
css={styles.buttons}
|
|
|
|
|
justifyContent="flex-start"
|
|
|
|
|
width="100%"
|
|
|
|
|
overflow="hidden" // Prevents text popout on collapse
|
|
|
|
|
>
|
|
|
|
|
<Icon style={{ flexShrink: 0 }} /> {/* Prevents icon from squishing */}
|
|
|
|
|
|
|
|
|
|
{/* Cleaned conditional transition styling */}
|
|
|
|
|
<Box
|
|
|
|
|
as="span"
|
|
|
|
|
ml={isOpen ? 3 : 0}
|
|
|
|
|
opacity={isOpen ? 1 : 0}
|
|
|
|
|
visibility={isOpen ? "visible" : "hidden"} // Prevents phantom width calculations and overflow into canvas
|
|
|
|
|
transition="opacity 0.3s ease, visibility 0.3s ease, margin 0.3s ease"
|
|
|
|
|
whiteSpace="nowrap"
|
|
|
|
|
>
|
|
|
|
|
{button.name}
|
|
|
|
|
</Box>
|
|
|
|
|
</Button>
|
|
|
|
|
</Tooltip>
|
|
|
|
|
);
|
|
|
|
|
})}
|
|
|
|
|
|
|
|
|
|
{/* Theme Toggler */}
|
|
|
|
|
<ColorModeButton
|
|
|
|
|
position="absolute"
|
|
|
|
|
bottom="4"
|
2026-07-22 10:37:01 -07:00
|
|
|
left={isOpen ? "4" : "50%"} // Center the toggle when collapsed
|
|
|
|
|
transform={isOpen ? "none" : "translateX(-50%)"} // Exact centering logic
|
2026-06-05 13:38:35 -07:00
|
|
|
/>
|
|
|
|
|
</Box>
|
2025-07-16 15:02:57 -07:00
|
|
|
);
|
2025-07-17 09:45:36 -07:00
|
|
|
}
|