From cd5ad06a0794d425fc3d528efdc4a2b6123c4083 Mon Sep 17 00:00:00 2001 From: moe-berri Date: Wed, 4 Nov 2026 16:38:00 +0800 Subject: [PATCH] fix(ui): keep worker controls compact on narrow headers --- .../src/components/DashboardHeader.tsx | 11 +++- .../DeploymentHealth/DeploymentHealth.tsx | 1 - .../Navbar/ViewSwitcher.integration.test.tsx | 4 +- .../src/components/Navbar/ViewSwitcher.tsx | 55 +++---------------- .../WorkerDropdown/WorkerDropdown.test.tsx | 18 ++++++ .../Navbar/WorkerDropdown/WorkerDropdown.tsx | 28 +++++++--- .../src/components/leftnav.tsx | 2 +- 7 files changed, 60 insertions(+), 59 deletions(-) diff --git a/ui/litellm-dashboard/src/components/DashboardHeader.tsx b/ui/litellm-dashboard/src/components/DashboardHeader.tsx index dd9b9be42ec..044f677cb28 100644 --- a/ui/litellm-dashboard/src/components/DashboardHeader.tsx +++ b/ui/litellm-dashboard/src/components/DashboardHeader.tsx @@ -45,7 +45,16 @@ export function DashboardHeader({
- {showWorkerSelector && } + {showWorkerSelector && ( + <> +
+ +
+
+ +
+ + )} diff --git a/ui/litellm-dashboard/src/components/DeploymentHealth/DeploymentHealth.tsx b/ui/litellm-dashboard/src/components/DeploymentHealth/DeploymentHealth.tsx index 43311ce2508..2a16a442bb0 100644 --- a/ui/litellm-dashboard/src/components/DeploymentHealth/DeploymentHealth.tsx +++ b/ui/litellm-dashboard/src/components/DeploymentHealth/DeploymentHealth.tsx @@ -51,7 +51,6 @@ export const DeploymentHealthIcon = ({ handle }: { handle: DeploymentHealthHandl ); }; -/** Keeps ignored warnings reachable when the header has no active alerts. */ export const DeploymentHealthLink = ({ handle }: { handle: DeploymentHealthHandle }) => { const { canView } = useDeploymentHealthAccess(); if (!canView) return null; diff --git a/ui/litellm-dashboard/src/components/Navbar/ViewSwitcher.integration.test.tsx b/ui/litellm-dashboard/src/components/Navbar/ViewSwitcher.integration.test.tsx index 8786d7df631..64bb8f15585 100644 --- a/ui/litellm-dashboard/src/components/Navbar/ViewSwitcher.integration.test.tsx +++ b/ui/litellm-dashboard/src/components/Navbar/ViewSwitcher.integration.test.tsx @@ -162,7 +162,7 @@ describe("ViewSwitcher", () => { ); it.each(["/ui/moyai", "/ui/moyai/sessions/one"])( - "should show Moyai's icon at %s and let users switch to Chat", + "should identify Moyai at %s and let users switch to Chat", async (pathname) => { state.pathname = pathname; getUiSettingsMock.mockResolvedValue({ values: { enable_chat_ui: true } }); @@ -170,7 +170,7 @@ describe("ViewSwitcher", () => { renderSwitcher(); const trigger = screen.getByRole("button", { name: "Switch workspace, current: Moyai" }); - expect(within(trigger).getByAltText("")).toHaveAttribute("src", expect.stringContaining("moyai-head.svg")); + expect(trigger).toHaveTextContent("Moyai"); await user.click(trigger); await user.click(await screen.findByRole("menuitem", { name: "Chat Chat UI for using LLMs, MCPs, Agents" })); expect(assignSpy).toHaveBeenCalledWith("/ui/chat"); diff --git a/ui/litellm-dashboard/src/components/Navbar/ViewSwitcher.tsx b/ui/litellm-dashboard/src/components/Navbar/ViewSwitcher.tsx index b7ca47494ec..0dd83094e8f 100644 --- a/ui/litellm-dashboard/src/components/Navbar/ViewSwitcher.tsx +++ b/ui/litellm-dashboard/src/components/Navbar/ViewSwitcher.tsx @@ -1,6 +1,5 @@ import { useTerminology } from "@/contexts/TerminologyContext"; import React from "react"; -import Image from "next/image"; import { usePathname } from "next/navigation"; import { Button } from "@/components/ui/button"; import { @@ -9,17 +8,15 @@ import { DropdownMenuItem, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; -import { Check, ChevronsUpDown, LayoutGrid, MessageCircle } from "lucide-react"; +import { Check, ChevronsUpDown } from "lucide-react"; import { usePluginMode } from "@/contexts/PluginModeContext"; import { useUISettings } from "@/app/(dashboard)/hooks/uiSettings/useUISettings"; import { uiHref } from "@/utils/uiHref"; import { cn } from "@/lib/cva.config"; -import moyaiHead from "../../../public/assets/moyai/moyai-head.svg"; const GATEWAY = "ai-gateway"; const CHAT = "chat"; const MOYAI = "moyai"; -type WorkspaceIconName = typeof GATEWAY | typeof CHAT | typeof MOYAI; function isWorkspaceRoute(pathname: string, workspace: string): boolean { const routes = [uiHref(workspace)]; @@ -27,45 +24,15 @@ function isWorkspaceRoute(pathname: string, workspace: string): boolean { return routes.some((route) => pathname === route || pathname.startsWith(`${route}/`)); } -function activeWorkspaceFor( +function activeWorkspaceLabel( isChatRoute: boolean, isMoyaiRoute: boolean, pluginLabel: string | undefined, gatewayLabel: string, -): { label: string; icon: WorkspaceIconName } { - if (isChatRoute) return { label: "Chat", icon: CHAT }; - if (isMoyaiRoute) return { label: "Moyai", icon: MOYAI }; - return { label: pluginLabel ?? gatewayLabel, icon: GATEWAY }; -} - -function WorkspaceIcon({ workspace }: { workspace: WorkspaceIconName }) { - if (workspace === CHAT) { - return ( - - ); - } - if (workspace === MOYAI) { - return ( - - ); - } - return ( - - ); +): string { + if (isChatRoute) return "Chat"; + if (isMoyaiRoute) return "Moyai"; + return pluginLabel ?? gatewayLabel; } interface ViewSwitcherItem { @@ -95,7 +62,7 @@ export default function ViewSwitcher({ className, contentClassName }: ViewSwitch const isStandaloneRoute = isChatRoute || isMoyaiRoute; const gatewayLabel = term("AI Gateway"); - const { label: activeLabel, icon: activeIcon } = activeWorkspaceFor( + const activeLabel = activeWorkspaceLabel( isChatRoute, isMoyaiRoute, plugins.find((p) => p.name === mode)?.display_name, @@ -166,15 +133,9 @@ export default function ViewSwitcher({ className, contentClassName }: ViewSwitch +