From 5c3fa165c84fb60178739a2017be58b04f2a930e Mon Sep 17 00:00:00 2001 From: yuneng-jiang Date: Mon, 24 Aug 2026 10:12:16 -0700 Subject: [PATCH 01/15] fix(ui): theme the created-key box so it follows dark mode (#37985) The virtual key shown after creating a key sits in a div with a hardcoded #f8f8f8 inline background, so in dark mode the box keeps the light background while the key text inherits the light foreground color, leaving the key nearly unreadable. Swap the inline styles for the bg-muted and text-foreground tokens, which resolve per theme. (cherry picked from commit 5f56be3294b753e8418defafe36e99f669263720) --- .../src/components/shared/CreatedKeyDisplay.test.tsx | 9 +++++++++ .../src/components/shared/CreatedKeyDisplay.tsx | 11 ++--------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/ui/litellm-dashboard/src/components/shared/CreatedKeyDisplay.test.tsx b/ui/litellm-dashboard/src/components/shared/CreatedKeyDisplay.test.tsx index 6c8cdae6deb..0e10d32f8d1 100644 --- a/ui/litellm-dashboard/src/components/shared/CreatedKeyDisplay.test.tsx +++ b/ui/litellm-dashboard/src/components/shared/CreatedKeyDisplay.test.tsx @@ -19,6 +19,15 @@ describe("CreatedKeyDisplay", () => { expect(screen.getByText("sk-test-123")).toBeInTheDocument(); }); + it("should theme the key box with tokens instead of a hardcoded light background", () => { + render(); + + const keyBox = screen.getByText("sk-test-123").parentElement as HTMLElement; + + expect(keyBox).not.toHaveAttribute("style"); + expect(keyBox).toHaveClass("bg-muted"); + }); + it("should display the security warning", () => { render(); expect(screen.getByText(/you will not be able to view it again/i)).toBeInTheDocument(); diff --git a/ui/litellm-dashboard/src/components/shared/CreatedKeyDisplay.tsx b/ui/litellm-dashboard/src/components/shared/CreatedKeyDisplay.tsx index c14379378d3..5dbc17b13bf 100644 --- a/ui/litellm-dashboard/src/components/shared/CreatedKeyDisplay.tsx +++ b/ui/litellm-dashboard/src/components/shared/CreatedKeyDisplay.tsx @@ -29,15 +29,8 @@ const CreatedKeyDisplay: React.FC = ({ apiKey }) => {

Virtual Key:

-
-
{apiKey}
+
+
{apiKey}
From 6b2901698702509e9f3d8d8e7d2ab057fa3f7858 Mon Sep 17 00:00:00 2001 From: yuneng-jiang Date: Mon, 24 Aug 2026 10:12:46 -0700 Subject: [PATCH 02/15] fix(ui): restore the public model name tooltip layout in the add model flow (#37986) The tooltip popup is an inline-flex row, so the four sibling blocks passed as a fragment laid out side by side in four columns. Wrap them in a single flex-col container instead. The inline code samples also used bg-muted, which is defined against the page surface, not the inverted tooltip surface, so they rendered as near-white chips carrying near-white text. Tint them from the popup's own token instead. (cherry picked from commit 6db5a5d6605114c672e2ef3c0fff6a5f76f56721) --- .../conditional_public_model_name.tsx | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/ui/litellm-dashboard/src/components/add_model/conditional_public_model_name.tsx b/ui/litellm-dashboard/src/components/add_model/conditional_public_model_name.tsx index b9c128a3d51..c58b177a6e1 100644 --- a/ui/litellm-dashboard/src/components/add_model/conditional_public_model_name.tsx +++ b/ui/litellm-dashboard/src/components/add_model/conditional_public_model_name.tsx @@ -34,6 +34,8 @@ const modelMappingsRule = { }, }; +const tooltipCodeClassName = "rounded-sm bg-background/20 px-1 py-0.5 font-mono text-xs"; + const ConditionalPublicModelName: React.FC = () => { const form = useFormContext(); @@ -123,22 +125,22 @@ const ConditionalPublicModelName: React.FC = () => { if (!showPublicModelName) return null; const publicNameTooltipContent = ( - <> -
The name you specify in your API calls to LiteLLM Proxy
-
+
+
The name you specify in your API calls to LiteLLM Proxy
+
Example: If you name your public model{" "} - example-name, and choose{" "} - openai/qwen-plus-latest as the LiteLLM model + example-name, and choose{" "} + openai/qwen-plus-latest as the LiteLLM model
-
+
Usage: You make an API call to the LiteLLM proxy with{" "} - model = "example-name" + model = "example-name"
-
- Result: LiteLLM sends{" "} - qwen-plus-latest to the provider +
+ Result: LiteLLM sends qwen-plus-latest to the + provider
- +
); const liteLLMModelTooltipContent =
The model name LiteLLM will send to the LLM API
; From c4867ccd18e43fadbab1c7756e784ab00204b1ec Mon Sep 17 00:00:00 2001 From: yuneng-jiang Date: Mon, 24 Aug 2026 10:13:24 -0700 Subject: [PATCH 03/15] fix(ui): make playground chat bubbles theme-aware (#37978) The playground message bubble painted its fill, border and avatar circle from inline hex values, so in dark mode both bubbles stayed near-white while the text inherited the dark foreground: the message body was unreadable. The MCP-events placeholder bubble in ChatUI carried the same three fills. They move onto the tokens the rest of the sweep already uses, so the assistant surface is bg-card over border-border and the user surface is the info tint at the same weight the other selected-state surfaces take. Light mode keeps the same colour family it had. The regression test asserts the token classes and that no inline style survives on either surface, which is the exact shape the bug took. (cherry picked from commit 3fb1009f816fbe96e90c6cc14d4a2ea36463f5eb) --- .../chat_ui/ChatMessageBubble.test.tsx | 15 +++++++++++++++ .../components/chat_ui/ChatMessageBubble.tsx | 16 ++++++---------- .../playground/components/chat_ui/ChatUI.tsx | 14 ++------------ 3 files changed, 23 insertions(+), 22 deletions(-) diff --git a/ui/litellm-dashboard/src/app/(dashboard)/playground/components/chat_ui/ChatMessageBubble.test.tsx b/ui/litellm-dashboard/src/app/(dashboard)/playground/components/chat_ui/ChatMessageBubble.test.tsx index c218db5b914..a83c11d1444 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/playground/components/chat_ui/ChatMessageBubble.test.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/playground/components/chat_ui/ChatMessageBubble.test.tsx @@ -87,6 +87,21 @@ describe("ChatMessageBubble", () => { expect(screen.getByText("Hi there")).toBeInTheDocument(); }); + it.each([ + { role: "user" as const, bubble: ["bg-info/10", "border-info/20"], avatar: "bg-info/20" }, + { role: "assistant" as const, bubble: ["bg-card", "border-border"], avatar: "bg-muted" }, + ])("should paint the $role surface from theme tokens, not fixed colours", ({ role, bubble, avatar }) => { + render(); + + const header = screen.getByText(role).closest("div") as HTMLElement; + const surface = header.parentElement as HTMLElement; + + expect(surface).toHaveClass(...bubble); + expect(surface).not.toHaveAttribute("style"); + expect(header.firstElementChild).toHaveClass(avatar); + expect(header.firstElementChild).not.toHaveAttribute("style"); + }); + it("should show model badge for assistant messages when model is provided", () => { render(); diff --git a/ui/litellm-dashboard/src/app/(dashboard)/playground/components/chat_ui/ChatMessageBubble.tsx b/ui/litellm-dashboard/src/app/(dashboard)/playground/components/chat_ui/ChatMessageBubble.tsx index eb24463cfd3..8c54d9e89fa 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/playground/components/chat_ui/ChatMessageBubble.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/playground/components/chat_ui/ChatMessageBubble.tsx @@ -46,20 +46,16 @@ function ChatMessageBubble({ return (
{/* Header: role icon + name + model badge */}
{isUser ? (