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
+17 -11
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 {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, PanelLeftClose, PanelLeftOpen} from 'lucide-react';
const SIDEBAR_DEFAULT_BUTTONS = [
{icon: House, name: "Home", url: "/home"},
@@ -27,17 +26,19 @@ export default function Sidebar() {
return (
<Box css={styles.root}>
{/* Home Link Logo */}
{/* Logo Navigates to Home Page */}
<Button
as={NavLink}
to="/home"
css={styles.logo}
variant="plain"
>
{isOpen ? "🌋 VDAP" : "🌋"}
<Flex direction="row" justify="space-between">
<Text>🌋</Text>
<Text css={styles.logo_text}>VDAP</Text>
</Flex>
</Button>
{/* Navigation Buttons */}
{visibleButtons.map((button) => {
const Icon = button.icon;
@@ -55,8 +56,12 @@ export default function Sidebar() {
</Button>
);
})}
<Box css={styles.footer}>
{/* Menu Trigger */}
<Flex css={styles.footer}>
<Flex css={styles.closed_theme_button}>
<ColorModeButton _hover={{ bg: "transparent" }} />
</Flex>
<Flex direction="row" justify="space-between">
<IconButton
aria-label="Toggle Sidebar"
variant="plain"
@@ -66,10 +71,11 @@ export default function Sidebar() {
>
{isOpen ? <PanelLeftClose /> : <PanelLeftOpen />}
</IconButton>
{/* Theme Toggler */}
<Flex css={styles.opened_theme_button}>
<ColorModeButton _hover={{ bg: "transparent" }} />
</Box>
</Flex>
</Flex>
</Flex>
</Box>
);
}
+94 -65
View File
@@ -1,6 +1,6 @@
import {defineSlotRecipe, createSystem, defaultConfig, defineConfig, defineRecipe} from "@chakra-ui/react";
// RECIPES
//—————RECIPES—————//
const headerRecipe = defineRecipe({
base: {
bg: "{transparent}",
@@ -14,8 +14,9 @@ const headerRecipe = defineRecipe({
}
});
// CONSOLIDATED ✔
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: {
root: {
// 1. Semi-transparent backgrounds
@@ -47,7 +48,7 @@ const sidebarRecipe = defineSlotRecipe({
justifyContent: "start",
alignItems: "stretch",
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
pl: 2, // Keep left padding
@@ -62,7 +63,7 @@ const sidebarRecipe = defineSlotRecipe({
bg: "transparent",
justifyContent: "flex-start",
transition: "background-color 0.4s ease, color 0.4s ease",
transition: "background-color 0.3s ease, color 0.3s ease",
"& svg": {
transition: "stroke-width 0.4s ease",
@@ -131,41 +132,68 @@ const sidebarRecipe = defineSlotRecipe({
},
logo: {
width: "100%",
height: "auto",
height: "2.5rem",
justifyContent: "flex-start",
ml: 2,
textStyle: "4xl",
overflow: "hidden",
fontWeight: "bold",
fontSize: "2rem",
px: 0,
},
logo_text: {
transition: "opacity 0.3s ease, visibility 0.3s ease, margin 0.3s ease",
whiteSpace: "nowrap",
overflow: "hidden",
textOverflow: "clip",
},
footer: {
flexDirection: "column",
width: "100%",
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"
ml: 2,
},
button_text: {
transition: "opacity 0.3s ease, visibility 0.3s ease, margin 0.3s ease",
whiteSpace: "nowrap"
whiteSpace: "nowrap",
overflow: "hidden",
textOverflow: "clip",
},
collapse_button: {
"& 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: {
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"},
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: {
root: { width: "71px" },
logo: { justifyContent: "center", ml: -1, textStyle: "3xl" },
footer: { gap: 2, flexDirection: "column-reverse" },
button_text: {ml: 0, opacity: 0, visibility: "hidden"},
button_text: {opacity: 0, visibility: "hidden"},
logo_text: {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({
slots: ["root", "header", "canvas"],
base: {
root: {
flexDirection: "column",
gap: "1",
position: "relative",
bg: "base100",
borderRadius: "md",
p: "1",
paddingBottom: "2",
border: "1px solid",
borderColor: "{base300}",
textAlign: "center",
height: "100%",
position: "fixed"
},
header: {
flexShrink: "0",
bg: "{base300}",
color: "{text}",
cursor: "move",
borderRadius: "sm",
whiteSpace: "nowrap",
textAlign: "left",
pl: "2"
},
canvas: {
flex: "1 1 auto",
bg: "transparent",
color: "{text}",
cursor: "default",
borderRadius: "md",
overflow: "auto",
}
}
});
// const widgetRecipe = defineSlotRecipe({
// slots: ["root", "header", "canvas"],
// base: {
// root: {
// flexDirection: "column",
// gap: "1",
// position: "relative",
// bg: "base100",
// borderRadius: "md",
// p: "1",
// paddingBottom: "2",
// border: "1px solid",
// borderColor: "{base300}",
// textAlign: "center",
// height: "100%",
// // position: "fixed"
// },
// header: {
// flexShrink: "0",
// bg: "{base300}",
// color: "{text}",
// cursor: "move",
// borderRadius: "sm",
// whiteSpace: "nowrap",
// textAlign: "left",
// pl: "2"
// },
// canvas: {
// flex: "1 1 auto",
// bg: "transparent",
// color: "{text}",
// cursor: "default",
// borderRadius: "md",
// overflow: "auto",
// }
// }
// });
const glassPanelRecipe = defineSlotRecipe({
slots: ["root", "header", "body"],
@@ -423,16 +451,17 @@ const config = defineConfig({
theme: {
semanticTokens: {
colors: {
base100: {value: {base: "#f6f9faff", _dark: "#1617199e"}},
base200: {value: {base: "#e6ecf1ff", _dark: "#242424"}},
base300: {value: {base: "#d3dae4ff", _dark: "#0a0b0bff"}},
primary: {value: {base: "#2B98F8", _dark: "#2B98F8"}},
primaryLt: {value: {base: "#98cdffff", _dark: "#98cdffff"}},
secondaryBG: {value: {base: "#EDF1F1", _dark: "#121212"}},
border: {value: {base: "#000000", _dark: "#cbcbcb84"}},
text: {value: {base: "#000000", _dark: "#FFFFFF"}},
textInverted: {value: {base: "#000000", _dark: "#FFFFFF"}},
icon: {value: {base: "#000000", _dark: "#FFFFFF"}},
// base100: {value: {base: "#f6f9faff", _dark: "#1617199e"}},
// base200: {value: {base: "#e6ecf1ff", _dark: "#242424"}},
// base300: {value: {base: "#d3dae4ff", _dark: "#0a0b0bff"}},
// primary: {value: {base: "#2B98F8", _dark: "#2B98F8"}},
// primaryLt: {value: {base: "#98cdffff", _dark: "#98cdffff"}},
// secondaryBG: {value: {base: "#EDF1F1", _dark: "#121212"}},
// border: {value: {base: "#000000", _dark: "#cbcbcb84"}},
// text: {value: {base: "#000000", _dark: "#FFFFFF"}},
// textInverted: {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)"}},
MainBackground: {value: {base: "#F9F9F9", _dark: "#141414"}},
titleColor: {value: {base: "gray.800", _dark: "#FFFFFF"}},
@@ -453,7 +482,7 @@ const config = defineConfig({
},
slotRecipes: {
sidebar: sidebarRecipe,
widget: widgetRecipe,
// widget: widgetRecipe,
glassPanel: glassPanelRecipe,
},
},