From edbb3429a339cde214e77860c29f31d470bbec9e Mon Sep 17 00:00:00 2001 From: yuneng-jiang Date: Thu, 20 Aug 2026 11:26:10 -0700 Subject: [PATCH] feat(ui): serve a dark-mode variant of the LiteLLM logo (#37656) The bundled logo is a JPEG, so it carries no alpha and its white background renders as a bright slab against a dark sidebar. Making it transparent alone would not be enough either: the wordmark is near-black and would disappear on dark. Adds logo_dark.png, derived from the light logo. The sky-blue disc and train are kept as they are behind a circular alpha mask, and the wordmark's antialiasing is un-flattened from white into straight alpha and repainted in the dark theme's own foreground colour. Both files are 1000x257, so swapping between them cannot shift the sidebar header. /get_image gains a theme query param. The default response is byte for byte what it was, and a logo configured through UI_LOGO_PATH is served unchanged in both themes, since custom logos have no dark variant yet. --- litellm/proxy/logo_dark.png | Bin 0 -> 35771 bytes litellm/proxy/proxy_server.py | 13 +++-- .../proxy/proxy_server/test_routes_misc.py | 48 ++++++++++++++++++ .../src/components/leftnav.test.tsx | 15 ++++++ .../src/components/leftnav.tsx | 10 ++-- ui/litellm-dashboard/src/lib/http/schema.d.ts | 13 ++++- 6 files changed, 89 insertions(+), 10 deletions(-) create mode 100644 litellm/proxy/logo_dark.png diff --git a/litellm/proxy/logo_dark.png b/litellm/proxy/logo_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..f92fbefdd22801d359d0c48900482c1776184ab8 GIT binary patch literal 35771 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 wi4;f(TmX6xXcmkQkplC { expect(screen.getByRole("link", { name: /litellm home/i })).toHaveAttribute("href", "/ui"); }); + it("pairs the logo with a dark-mode variant that swaps on the dark class", () => { + renderWithProviders(); + + const [light, dark] = Array.from(screen.getByRole("link", { name: /litellm home/i }).querySelectorAll("img")); + const classesOf = (el: Element) => new Set(el.className.split(/\s+/)); + + const lightSrc = light.getAttribute("src") ?? ""; + expect(light).toHaveAttribute("src", expect.stringMatching(/\/get_image$/)); + expect(dark).toHaveAttribute("src", `${lightSrc}?theme=dark`); + expect(classesOf(light).has("dark:hidden")).toBe(true); + expect(classesOf(light).has("hidden")).toBe(false); + expect(classesOf(dark).has("hidden")).toBe(true); + expect(classesOf(dark).has("dark:block")).toBe(true); + }); + it("renders all top-level (non-nested) tabs for admin", () => { renderWithProviders(); diff --git a/ui/litellm-dashboard/src/components/leftnav.tsx b/ui/litellm-dashboard/src/components/leftnav.tsx index 2ece64271f8..aa1b97116f5 100644 --- a/ui/litellm-dashboard/src/components/leftnav.tsx +++ b/ui/litellm-dashboard/src/components/leftnav.tsx @@ -81,6 +81,8 @@ import { MIGRATED_PAGES, migratedHref, legacyPageHref } from "@/utils/migratedPa const ICON = { strokeWidth: 1.75 } as const; +const LOGO_CLASS_NAME = "h-7 w-auto max-w-[150px] object-contain group-data-[collapsed=true]/sidebar:w-7"; + interface SidebarProps { setPage: (page: string) => void; defaultSelectedKey: string; @@ -603,6 +605,7 @@ const Sidebar_: React.FC = ({ }; const logoSrc = logoUrl || `${baseUrl}/get_image`; + const darkLogoSrc = logoUrl || `${baseUrl}/get_image?theme=dark`; return ( @@ -610,11 +613,8 @@ const Sidebar_: React.FC = ({
- LiteLLM + LiteLLM + {version && (