From 3cf62c89db1b92ca550c0d2d41fc2b37c738d66d Mon Sep 17 00:00:00 2001 From: Jeff Gu Date: Wed, 15 Apr 2026 10:39:05 +0800 Subject: [PATCH] =?UTF-8?q?feat(sidebar):=20=E6=B7=BB=E5=8A=A0=E4=B8=8B?= =?UTF-8?q?=E6=8B=89=E8=8F=9C=E5=8D=95=E4=BB=A5=E9=80=89=E6=8B=A9=E4=B8=BB?= =?UTF-8?q?=E9=A2=98=E5=92=8C=E8=AF=AD=E8=A8=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/package.json | 2 + frontend/src/components/layout/Sidebar.tsx | 196 +++++++++++-------- frontend/src/components/ui/dropdown-menu.tsx | 49 +++++ frontend/src/components/ui/tooltip.tsx | 34 ++++ frontend/src/i18n/locales/en.json | 2 + frontend/src/i18n/locales/zh-CN.json | 2 + frontend/src/i18n/locales/zh-TW.json | 2 + 7 files changed, 203 insertions(+), 84 deletions(-) create mode 100644 frontend/src/components/ui/dropdown-menu.tsx create mode 100644 frontend/src/components/ui/tooltip.tsx diff --git a/frontend/package.json b/frontend/package.json index 2f78ce9..e673692 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -27,7 +27,9 @@ }, "dependencies": { "@radix-ui/react-dialog": "^1.1.15", + "@radix-ui/react-dropdown-menu": "^2.1.16", "@radix-ui/react-slot": "^1.2.4", + "@radix-ui/react-tooltip": "^1.2.8", "@tailwindcss/postcss": "^4.2.2", "@tanstack/react-query": "^5.97.0", "class-variance-authority": "^0.7.1", diff --git a/frontend/src/components/layout/Sidebar.tsx b/frontend/src/components/layout/Sidebar.tsx index 1ed7f2b..2d49572 100644 --- a/frontend/src/components/layout/Sidebar.tsx +++ b/frontend/src/components/layout/Sidebar.tsx @@ -11,6 +11,7 @@ import { Languages, Moon, Sun, + Check, LogOut, X, PanelLeftClose, @@ -22,6 +23,13 @@ import { useAuthStore } from "@/store/auth"; import { useState } from "react"; import { useTranslation } from "react-i18next"; import { changeLanguage, SUPPORTED_LANGUAGES, type SupportedLanguage } from "@/i18n"; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu"; +import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip"; type NavGroup = "overview" | "management" | "tools" | "system"; @@ -77,11 +85,10 @@ export function Sidebar({ return "light"; }); - const toggleTheme = () => { - const newTheme = theme === "light" ? "dark" : "light"; - setTheme(newTheme); - localStorage.setItem("theme", newTheme); - if (newTheme === "dark") { + const setThemeMode = (nextTheme: "light" | "dark") => { + setTheme(nextTheme); + localStorage.setItem("theme", nextTheme); + if (nextTheme === "dark") { document.documentElement.classList.add("dark"); } else { document.documentElement.classList.remove("dark"); @@ -91,16 +98,17 @@ export function Sidebar({ const langLabels: Record = { "zh-CN": t("language.zhCN"), "zh-TW": t("language.zhTW"), - "en": t("language.en"), + en: t("language.en"), }; - const cycleLang = () => { - const currentIndex = SUPPORTED_LANGUAGES.indexOf(i18n.language as SupportedLanguage); - const nextIndex = (currentIndex + 1) % SUPPORTED_LANGUAGES.length; - changeLanguage(SUPPORTED_LANGUAGES[nextIndex]); - }; - - const currentLangLabel = langLabels[i18n.language as SupportedLanguage] || langLabels["zh-CN"]; + const currentLanguage = SUPPORTED_LANGUAGES.includes(i18n.language as SupportedLanguage) + ? (i18n.language as SupportedLanguage) + : "zh-CN"; + const currentLangLabel = langLabels[currentLanguage]; + const actionButtonClassName = cn( + "flex h-9 items-center justify-center rounded-md text-muted-foreground transition-colors duration-150 hover:bg-muted/70 hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/50 data-[state=open]:bg-muted/80 data-[state=open]:text-foreground", + collapsed ? "w-10" : "w-full", + ); const handleLogout = async () => { await logout(); @@ -185,7 +193,10 @@ export function Sidebar({ {/* Navigation */}