fixed sidebar animation issues by truncating btn text and using css transitions on footer icons

This commit is contained in:
2026-09-03 11:21:50 -07:00
parent 60f71485da
commit 1c6951d245
2 changed files with 121 additions and 86 deletions
+26 -20
View File
@@ -1,9 +1,8 @@
import {useSlotRecipe, Box, Button, IconButton} from "@chakra-ui/react"; import {useSlotRecipe, Box, Button, IconButton, Text, Flex} from "@chakra-ui/react";
import {ColorModeButton} from "@/components/ui/color-mode.jsx"; import {ColorModeButton} from "@/components/ui/color-mode.jsx";
import {useState} from "react"; import {useState} from "react";
import {NavLink} from "react-router-dom"; import {NavLink} from "react-router-dom";
import Tooltip from "../ui/Tooltip.jsx"; import {Mountain, House, Earth, MapPin, ShieldUser, PanelLeftClose, PanelLeftOpen} from 'lucide-react';
import {Mountain, House, Earth, MapPin, ShieldUser, Menu, PanelLeftClose, PanelLeftOpen} from 'lucide-react';
const SIDEBAR_DEFAULT_BUTTONS = [ const SIDEBAR_DEFAULT_BUTTONS = [
{icon: House, name: "Home", url: "/home"}, {icon: House, name: "Home", url: "/home"},
@@ -27,17 +26,19 @@ export default function Sidebar() {
return ( return (
<Box css={styles.root}> <Box css={styles.root}>
{/* Home Link Logo */} {/* Logo Navigates to Home Page */}
<Button <Button
as={NavLink} as={NavLink}
to="/home" to="/home"
css={styles.logo} css={styles.logo}
variant="plain" variant="plain"
> >
{isOpen ? "🌋 VDAP" : "🌋"} <Flex direction="row" justify="space-between">
<Text>🌋</Text>
<Text css={styles.logo_text}>VDAP</Text>
</Flex>
</Button> </Button>
{/* Navigation Buttons */} {/* Navigation Buttons */}
{visibleButtons.map((button) => { {visibleButtons.map((button) => {
const Icon = button.icon; const Icon = button.icon;
@@ -55,21 +56,26 @@ export default function Sidebar() {
</Button> </Button>
); );
})} })}
<Box css={styles.footer}>
{/* Menu Trigger */}
<IconButton
aria-label="Toggle Sidebar"
variant="plain"
size="md"
onClick={toggleSidebar}
css={styles.collapse_button}
>
{isOpen ? <PanelLeftClose /> : <PanelLeftOpen />}
</IconButton>
{/* Theme Toggler */} <Flex css={styles.footer}>
<Flex css={styles.closed_theme_button}>
<ColorModeButton _hover={{ bg: "transparent" }} /> <ColorModeButton _hover={{ bg: "transparent" }} />
</Box> </Flex>
</Box> <Flex direction="row" justify="space-between">
<IconButton
aria-label="Toggle Sidebar"
variant="plain"
size="md"
onClick={toggleSidebar}
css={styles.collapse_button}
>
{isOpen ? <PanelLeftClose /> : <PanelLeftOpen />}
</IconButton>
<Flex css={styles.opened_theme_button}>
<ColorModeButton _hover={{ bg: "transparent" }} />
</Flex>
</Flex>
</Flex>
</Box>
); );
} }
+95 -66
View File
@@ -1,6 +1,6 @@
import {defineSlotRecipe, createSystem, defaultConfig, defineConfig, defineRecipe} from "@chakra-ui/react"; import {defineSlotRecipe, createSystem, defaultConfig, defineConfig, defineRecipe} from "@chakra-ui/react";
// RECIPES //—————RECIPES—————//
const headerRecipe = defineRecipe({ const headerRecipe = defineRecipe({
base: { base: {
bg: "{transparent}", bg: "{transparent}",
@@ -14,8 +14,9 @@ const headerRecipe = defineRecipe({
} }
}); });
// CONSOLIDATED ✔
const sidebarRecipe = defineSlotRecipe({ const sidebarRecipe = defineSlotRecipe({
slots: ["root", "logo", "footer", "button_text","buttons", "collapse_button"], slots: ["root", "logo", "logo_text", "footer", "button_text", "buttons", "collapse_button", "opened_theme_button", "closed_theme_button"],
base: { base: {
root: { root: {
// 1. Semi-transparent backgrounds // 1. Semi-transparent backgrounds
@@ -47,7 +48,7 @@ const sidebarRecipe = defineSlotRecipe({
justifyContent: "start", justifyContent: "start",
alignItems: "stretch", alignItems: "stretch",
gap: 4, gap: 4,
transition: "width 0.4s ease", transition: "width 0.5s ease",
// CRITICAL: Adjust padding and overflow to allow the button to touch the right edge // CRITICAL: Adjust padding and overflow to allow the button to touch the right edge
pl: 2, // Keep left padding pl: 2, // Keep left padding
@@ -62,7 +63,7 @@ const sidebarRecipe = defineSlotRecipe({
bg: "transparent", bg: "transparent",
justifyContent: "flex-start", justifyContent: "flex-start",
transition: "background-color 0.4s ease, color 0.4s ease", transition: "background-color 0.3s ease, color 0.3s ease",
"& svg": { "& svg": {
transition: "stroke-width 0.4s ease", transition: "stroke-width 0.4s ease",
@@ -131,41 +132,68 @@ const sidebarRecipe = defineSlotRecipe({
}, },
logo: { logo: {
width: "100%", width: "100%",
height: "auto", height: "2.5rem",
justifyContent: "flex-start",
ml: 2,
textStyle: "4xl",
overflow: "hidden", overflow: "hidden",
fontWeight: "bold", fontWeight: "bold",
fontSize: "2rem",
px: 0, px: 0,
}, },
logo_text: {
transition: "opacity 0.3s ease, visibility 0.3s ease, margin 0.3s ease",
whiteSpace: "nowrap",
overflow: "hidden",
textOverflow: "clip",
},
footer: { footer: {
flexDirection: "column",
width: "100%",
mt: "auto", mt: "auto",
display: "flex", ml: 2,
justifyContent: "center",
alignItems: "center",
pb: 4,
pr: 2,
transition: "opacity 0.3s ease, visibility 0.3s ease, margin 0.3s ease"
}, },
button_text: { button_text: {
transition: "opacity 0.3s ease, visibility 0.3s ease, margin 0.3s ease", transition: "opacity 0.3s ease, visibility 0.3s ease, margin 0.3s ease",
whiteSpace: "nowrap" whiteSpace: "nowrap",
overflow: "hidden",
textOverflow: "clip",
}, },
collapse_button: { collapse_button: {
"& svg": { flexShrink: "0" }, "& svg": { flexShrink: "0" },
}, },
opened_theme_button: {
width: "100%" ,
align: "center",
justifyContent: "right",
mr: 6,
"& button": {
alignSelf: "center",
transition: "opacity 0.3s ease, visibility 0.3s ease, margin 0.3s ease",
}
},
closed_theme_button: {
ml: 0.9,
"& button": {
transition: "opacity 0.3s ease, visibility 0.3s ease, margin 0.3s ease",
}
},
}, },
variants: { variants: {
state: { state: {
open: { open: {
root: { width: "190px" }, root: { width: "190px" },
logo: { justifyContent: "flex-start", ml: 2, textStyle: "4xl" },
footer: { gap: 16, flexDirection: "row" },
button_text: {ml: 3, opacity: 1, visibility: "visible"}, button_text: {ml: 3, opacity: 1, visibility: "visible"},
logo_text: {ml: 3, opacity: 1, visibility: "visible"},
opened_theme_button: {"& button": {opacity: 1, visibility: "visible"}},
closed_theme_button: {"& button": {opacity: 0, visibility: "hidden"}},
}, },
closed: { closed: {
root: { width: "71px" }, root: { width: "71px" },
logo: { justifyContent: "center", ml: -1, textStyle: "3xl" }, button_text: {opacity: 0, visibility: "hidden"},
footer: { gap: 2, flexDirection: "column-reverse" }, logo_text: {opacity: 0, visibility: "hidden"},
button_text: {ml: 0, opacity: 0, visibility: "hidden"}, opened_theme_button: {"& button": {opacity: 0, visibility: "hidden"}},
closed_theme_button: {"& button": {opacity: 1, visibility: "visible"}},
} }
} }
} }
@@ -185,43 +213,43 @@ const canvasRecipe = defineRecipe({
} }
}); });
const widgetRecipe = defineSlotRecipe({ // const widgetRecipe = defineSlotRecipe({
slots: ["root", "header", "canvas"], // slots: ["root", "header", "canvas"],
base: { // base: {
root: { // root: {
flexDirection: "column", // flexDirection: "column",
gap: "1", // gap: "1",
position: "relative", // position: "relative",
bg: "base100", // bg: "base100",
borderRadius: "md", // borderRadius: "md",
p: "1", // p: "1",
paddingBottom: "2", // paddingBottom: "2",
border: "1px solid", // border: "1px solid",
borderColor: "{base300}", // borderColor: "{base300}",
textAlign: "center", // textAlign: "center",
height: "100%", // height: "100%",
position: "fixed" // // position: "fixed"
}, // },
header: { // header: {
flexShrink: "0", // flexShrink: "0",
bg: "{base300}", // bg: "{base300}",
color: "{text}", // color: "{text}",
cursor: "move", // cursor: "move",
borderRadius: "sm", // borderRadius: "sm",
whiteSpace: "nowrap", // whiteSpace: "nowrap",
textAlign: "left", // textAlign: "left",
pl: "2" // pl: "2"
}, // },
canvas: { // canvas: {
flex: "1 1 auto", // flex: "1 1 auto",
bg: "transparent", // bg: "transparent",
color: "{text}", // color: "{text}",
cursor: "default", // cursor: "default",
borderRadius: "md", // borderRadius: "md",
overflow: "auto", // overflow: "auto",
} // }
} // }
}); // });
const glassPanelRecipe = defineSlotRecipe({ const glassPanelRecipe = defineSlotRecipe({
slots: ["root", "header", "body"], slots: ["root", "header", "body"],
@@ -348,7 +376,7 @@ const glassTabRecipe = defineRecipe({
} }
}); });
const config = defineConfig({ const config= defineConfig({
globalCss: { globalCss: {
".react-grid-placeholder": { ".react-grid-placeholder": {
background: "#c0d2e3ff !important", background: "#c0d2e3ff !important",
@@ -423,16 +451,17 @@ const config = defineConfig({
theme: { theme: {
semanticTokens: { semanticTokens: {
colors: { colors: {
base100: {value: {base: "#f6f9faff", _dark: "#1617199e"}}, // base100: {value: {base: "#f6f9faff", _dark: "#1617199e"}},
base200: {value: {base: "#e6ecf1ff", _dark: "#242424"}}, // base200: {value: {base: "#e6ecf1ff", _dark: "#242424"}},
base300: {value: {base: "#d3dae4ff", _dark: "#0a0b0bff"}}, // base300: {value: {base: "#d3dae4ff", _dark: "#0a0b0bff"}},
primary: {value: {base: "#2B98F8", _dark: "#2B98F8"}}, // primary: {value: {base: "#2B98F8", _dark: "#2B98F8"}},
primaryLt: {value: {base: "#98cdffff", _dark: "#98cdffff"}}, // primaryLt: {value: {base: "#98cdffff", _dark: "#98cdffff"}},
secondaryBG: {value: {base: "#EDF1F1", _dark: "#121212"}}, // secondaryBG: {value: {base: "#EDF1F1", _dark: "#121212"}},
border: {value: {base: "#000000", _dark: "#cbcbcb84"}}, // border: {value: {base: "#000000", _dark: "#cbcbcb84"}},
text: {value: {base: "#000000", _dark: "#FFFFFF"}}, // text: {value: {base: "#000000", _dark: "#FFFFFF"}},
textInverted: {value: {base: "#000000", _dark: "#FFFFFF"}}, // textInverted: {value: {base: "#000000", _dark: "#FFFFFF"}},
icon: {value: {base: "#000000", _dark: "#FFFFFF"}}, // icon: {value: {base: "#000000", _dark: "#FFFFFF"}},
gooeyButtonBackground: {value: {base: "rgba(255, 255, 255, 0.1)", _dark: "rgba(255, 255, 255, 0.1)"}}, gooeyButtonBackground: {value: {base: "rgba(255, 255, 255, 0.1)", _dark: "rgba(255, 255, 255, 0.1)"}},
MainBackground: {value: {base: "#F9F9F9", _dark: "#141414"}}, MainBackground: {value: {base: "#F9F9F9", _dark: "#141414"}},
titleColor: {value: {base: "gray.800", _dark: "#FFFFFF"}}, titleColor: {value: {base: "gray.800", _dark: "#FFFFFF"}},
@@ -453,7 +482,7 @@ const config = defineConfig({
}, },
slotRecipes: { slotRecipes: {
sidebar: sidebarRecipe, sidebar: sidebarRecipe,
widget: widgetRecipe, // widget: widgetRecipe,
glassPanel: glassPanelRecipe, glassPanel: glassPanelRecipe,
}, },
}, },