From 5012d11a18a0cef17cb0a2be286604a4a342fa7f Mon Sep 17 00:00:00 2001 From: yuneng-jiang Date: Tue, 18 Aug 2026 18:52:41 -0700 Subject: [PATCH] refactor(ui): style the logging settings from semantic tokens (#37385) team/LoggingSettings.tsx carried 34 hardcoded palette classes and common_components/PremiumLoggingSettings.tsx another 9, so both render light-only regardless of theme. Map the neutrals onto foreground, muted-foreground, muted and border, the red affordances onto destructive, and swap the hand-rolled chips for the shadcn Badge primitive. The three event-type options carried decorative green, red and blue dots. The design system has no success or info token, so the dots are dropped and the option labels, which already say "Success Only", "Failure Only" and "Success & Failure", carry the meaning on their own. This is groundwork, not a visible change: nothing in the dashboard ever applies the .dark class today, so the dark palette is unreachable. The files no longer hardcode colour and will follow the theme once one exists. --- .../PremiumLoggingSettings.test.tsx | 39 ++++++++ .../PremiumLoggingSettings.tsx | 13 +-- .../components/team/LoggingSettings.test.tsx | 37 ++++++++ .../src/components/team/LoggingSettings.tsx | 88 +++++++------------ 4 files changed, 115 insertions(+), 62 deletions(-) create mode 100644 ui/litellm-dashboard/src/components/common_components/PremiumLoggingSettings.test.tsx diff --git a/ui/litellm-dashboard/src/components/common_components/PremiumLoggingSettings.test.tsx b/ui/litellm-dashboard/src/components/common_components/PremiumLoggingSettings.test.tsx new file mode 100644 index 00000000000..76b90bdca90 --- /dev/null +++ b/ui/litellm-dashboard/src/components/common_components/PremiumLoggingSettings.test.tsx @@ -0,0 +1,39 @@ +import { readFileSync } from "fs"; +import { resolve } from "path"; +import React from "react"; +import { describe, it, expect, vi } from "vitest"; +import { renderWithProviders, screen } from "../../../tests/test-utils"; +import PremiumLoggingSettings from "./PremiumLoggingSettings"; + +const SOURCE_PATH = resolve(process.cwd(), "src/components/common_components/PremiumLoggingSettings.tsx"); + +const HARDCODED_PALETTE = + /\b(?:text|bg|border|hover:bg|hover:text|hover:border|dark:bg|dark:text|dark:border|ring|divide|fill|stroke)-(?:gray|slate|zinc|neutral|stone|red|blue|green|yellow|amber|orange|indigo|purple|pink|rose|teal|cyan|sky|violet|fuchsia|lime|emerald)-\d+(?:\/\d+)?\b/g; + +const SEMANTIC_TOKEN = + /\b(?:text|bg|border|hover:bg|hover:text|ring|divide|fill|stroke)-(?:foreground|muted-foreground|muted|background|card|popover|primary|secondary|destructive|border|input|accent|ring)(?:-foreground)?(?:\/\d+)?\b/g; + +describe("PremiumLoggingSettings", () => { + it("styles itself from semantic tokens instead of hardcoded palette classes", () => { + const source = readFileSync(SOURCE_PATH, "utf8"); + + expect(source).toContain("export function PremiumLoggingSettings"); + expect(source.match(SEMANTIC_TOKEN) ?? []).not.toHaveLength(0); + expect(source.match(HARDCODED_PALETTE) ?? []).toHaveLength(0); + }); + + it("shows the enterprise notice and withholds the editor from a free user", () => { + renderWithProviders(); + + expect(screen.getByText(/LiteLLM Enterprise feature/)).toBeInTheDocument(); + expect(screen.getByText("✨ langfuse-logging")).toBeInTheDocument(); + expect(screen.queryByText("Logging Integrations")).not.toBeInTheDocument(); + }); + + it("renders the editor for a premium user", () => { + renderWithProviders(); + + expect(screen.getByText("Logging Integrations")).toBeInTheDocument(); + expect(screen.queryByText(/LiteLLM Enterprise feature/)).not.toBeInTheDocument(); + }); +}); diff --git a/ui/litellm-dashboard/src/components/common_components/PremiumLoggingSettings.tsx b/ui/litellm-dashboard/src/components/common_components/PremiumLoggingSettings.tsx index 62d2f182120..d1f3cfe6712 100644 --- a/ui/litellm-dashboard/src/components/common_components/PremiumLoggingSettings.tsx +++ b/ui/litellm-dashboard/src/components/common_components/PremiumLoggingSettings.tsx @@ -1,4 +1,5 @@ import React from "react"; +import { Badge } from "@/components/ui/badge"; import LoggingSettings from "../team/LoggingSettings"; interface PremiumLoggingSettingsProps { @@ -20,15 +21,15 @@ export function PremiumLoggingSettings({ return (
-
+ ✨ langfuse-logging -
-
+ + ✨ datadog-logging -
+
-
-

+

+

Setting Key/Team logging settings is a LiteLLM Enterprise feature. Global Logging Settings are available for all free users. Get a trial key{" "} diff --git a/ui/litellm-dashboard/src/components/team/LoggingSettings.test.tsx b/ui/litellm-dashboard/src/components/team/LoggingSettings.test.tsx index 17f20ad0dcc..ae02a26ddb0 100644 --- a/ui/litellm-dashboard/src/components/team/LoggingSettings.test.tsx +++ b/ui/litellm-dashboard/src/components/team/LoggingSettings.test.tsx @@ -1,9 +1,19 @@ +import { readFileSync } from "fs"; +import { resolve } from "path"; import React from "react"; import { describe, it, expect, vi, beforeEach } from "vitest"; import userEvent from "@testing-library/user-event"; import { renderWithProviders, screen, fireEvent } from "../../../tests/test-utils"; import LoggingSettings from "./LoggingSettings"; +const SOURCE_PATH = resolve(process.cwd(), "src/components/team/LoggingSettings.tsx"); + +const HARDCODED_PALETTE = + /\b(?:text|bg|border|hover:bg|hover:text|hover:border|dark:bg|dark:text|dark:border|ring|divide|fill|stroke)-(?:gray|slate|zinc|neutral|stone|red|blue|green|yellow|amber|orange|indigo|purple|pink|rose|teal|cyan|sky|violet|fuchsia|lime|emerald)-\d+(?:\/\d+)?\b/g; + +const SEMANTIC_TOKEN = + /\b(?:text|bg|border|hover:bg|hover:text|ring|divide|fill|stroke)-(?:foreground|muted-foreground|muted|background|card|popover|primary|secondary|destructive|border|input|accent|ring)(?:-foreground)?(?:\/\d+)?\b/g; + describe("LoggingSettings", () => { beforeEach(() => { vi.clearAllMocks(); @@ -163,6 +173,33 @@ describe("LoggingSettings", () => { expect(screen.getByText("C")).toBeInTheDocument(); }); + it("styles itself from semantic tokens instead of hardcoded palette classes", () => { + const source = readFileSync(SOURCE_PATH, "utf8"); + + expect(source).toContain("const LoggingSettings"); + expect(source.match(SEMANTIC_TOKEN) ?? []).not.toHaveLength(0); + expect(source.match(HARDCODED_PALETTE) ?? []).toHaveLength(0); + }); + + it("reports the chosen event type when a different option is picked", async () => { + const user = userEvent.setup({ delay: null }); + const mockOnChange = vi.fn(); + const initialValue = [ + { + callback_name: "langsmith", + callback_type: "success", + callback_vars: {}, + }, + ]; + + renderWithProviders(); + + await user.click(screen.getByTitle("Success Only")); + await user.click(await screen.findByTitle("Failure Only")); + + expect(mockOnChange).toHaveBeenCalledWith([expect.objectContaining({ callback_type: "failure" })]); + }); + it("correctly handles numerical input with decimal values", () => { const mockOnChange = vi.fn(); diff --git a/ui/litellm-dashboard/src/components/team/LoggingSettings.tsx b/ui/litellm-dashboard/src/components/team/LoggingSettings.tsx index eee6e76569d..0fc936159fa 100644 --- a/ui/litellm-dashboard/src/components/team/LoggingSettings.tsx +++ b/ui/litellm-dashboard/src/components/team/LoggingSettings.tsx @@ -3,6 +3,7 @@ import React from "react"; import { Select, Tooltip, Divider } from "antd"; import { InfoCircleOutlined } from "@ant-design/icons"; import { Button } from "@/components/ui/button"; +import { Badge } from "@/components/ui/badge"; import { Card } from "@/components/ui/card"; import { Input } from "@/components/ui/input"; import { InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput } from "@/components/ui/input-group"; @@ -142,30 +143,24 @@ const LoggingSettings: React.FC = ({ if (Object.keys(dynamicParams).length === 0) return null; return ( -

+
-
-
+
+
- Integration Parameters + Integration Parameters
{Object.entries(dynamicParams).map(([paramName, paramType]) => (
-