Skip to content

refactor(ui): migrate budgets, skills, ui-theme to shadcn - #34465

Merged
yuneng-berri merged 3 commits into
litellm_internal_stagingfrom
litellm_/dazzling-gagarin-3d4c69
Jul 24, 2026
Merged

refactor(ui): migrate budgets, skills, ui-theme to shadcn#34465
yuneng-berri merged 3 commits into
litellm_internal_stagingfrom
litellm_/dazzling-gagarin-3d4c69

Conversation

@yuneng-berri

Copy link
Copy Markdown
Contributor

TLDR

Problem this solves:

  • Budgets, Skills and UI Theme still render antd and Tremor
  • Three tiny pages would otherwise cost three separate review cycles

How it solves it:

  • Swaps them onto installed shadcn primitives; markup only
  • Bundles the three into one PR since each owns one file
  • Pins behaviour with tests written against the old components first

Relevant issues

Linear ticket

Pre-Submission checklist

Please complete all items before asking a LiteLLM maintainer to review your PR

  • I have added meaningful tests
  • My PR passes all CI/CD checks (e.g., lint, format, unit tests)
  • My PR's scope is as isolated as possible; it only solves 1 specific problem
  • I have received a Greptile Confidence Score of at least 4/5 before requesting a maintainer review (Greptile reviews automatically once the PR is opened; only comment @greptileai to re-request a review after pushing changes)

Delays in PR merge?

If you're seeing a delay in your PR being merged, ping the LiteLLM Team on Slack (#pr-review).

Screenshots / Proof of Fix

Before is commit 64aad5877a (pre-migration), after is commit 39f0b56502 (the migration commit). Screenshots are attached in a comment below

The visual gate photographs all 35 dashboard routes at 1280x720 against a live proxy with a seeded database. It was calibrated on the untouched tree first (35/35 stable across two runs, then 35/35 identical across a full stack restart), the three migrated routes were re-baselined, and the gate was re-run: 35/35 passed, so the 32 routes not touched here are pixel-identical. That is the blast-radius check; tolerance is 0 differing pixels

The gate only ever photographs each route's default state, so the parts it cannot see were driven by hand against a live proxy with a seeded skill row

To reproduce, with a proxy on localhost:4000 and the dashboard dev server on localhost:3000

  1. Go to http://localhost:4000/ui/?page=budgets. The Budgets tab shows the budget list; "+ Create Budget" opens the create modal
  2. Click the Examples tab, then step through "Assign Budget to Customer", "Test it (Curl)" and "Test it (OpenAI SDK)". Each nested tab swaps the code block and the active underline follows the selected tab, with no horizontal scrollbar
  3. Go to http://localhost:4000/ui/?page=skills. Register a skill, then open the row's overflow menu and click Delete. Expect a confirmation naming the skill plus "This action cannot be undone."
  4. Click Cancel and expect nothing to be deleted. Reopen and click Delete; expect the success toast, the row to disappear, and the row to be gone from LiteLLM_ClaudeCodePluginTable
  5. Go to http://localhost:4000/ui/?page=ui-theme. Enter a logo URL and a favicon URL, click Save Changes, and expect the success toast. Confirm it persisted:
curl -s http://localhost:4000/get/ui_theme_settings -H "Authorization: Bearer sk-1234"
  1. Click Reset to Default and expect both inputs to clear and the same GET to return logo_url: null and favicon_url: null
  2. Shrink the window to roughly 1280x480 on the UI Theme page and confirm the content scrolls rather than clipping, so both buttons stay reachable

Verified locally on the seeded stack: the skills delete removed the row from postgres, and the UI Theme save then reset round-tripped through /get/ui_theme_settings as logo_url set then back to null

Type

🧹 Refactoring

Changes

Migrated, one route-exclusive file per route:

  • budgets/_components/budget_panel.tsx; Tremor TabGroup/TabList/Tab/TabPanels/TabPanel to ui/tabs, Tremor Button to ui/button, Tremor Text to plain elements with token classes
  • skills/_components/ClaudeCodePluginsPanel.tsx; the antd delete Modal to ui/alert-dialog and Tremor Button to ui/button. The confirm keeps its in-flight state by using a plain destructive Button in the footer rather than AlertDialogAction, which closes the dialog on click
  • ui-theme/UIThemeSettings.tsx; Tremor Card/Title/Text/TextInput/Button to ui/card, ui/input, ui/label, ui/button and plain elements. The two inputs gain real htmlFor label associations, which the Tremor version did not have

No new primitives were installed; every target was already in src/components/ui/. Buttons use the primitive's own variants so colour stays a token swap, and the now-obsolete no-restricted-imports suppressions for these three files are pruned from eslint-suppressions.json

Deliberately not touched, quoting the scope analysis for these routes:

  • SHARED, reached by another page, refuse to edit: common_components/DeleteResourceModal.tsx (23 pages), molecules/message_manager.tsx (53 pages), molecules/notifications_manager.tsx (53 pages), claude_code_plugins/skill_detail.tsx (4 pages). These are migrated separately so a page PR cannot silently restyle up to 52 other pages
  • DEFERRED, contains an antd Form, do not touch until forms unblock: budgets/_components/budget_modal.tsx, budgets/_components/edit_budget_modal.tsx, skills/_components/add_plugin_form.tsx, common_components/check_openapi_schema.tsx

Because the shared components stay on antd, these routes still pull antd in through them; that goes away when those components are migrated on their own

Two notes for the reviewer. The primary buttons look darker because shadcn's default variant resolves --primary, matching the already-migrated Agents page rather than Tremor's indigo. And Base UI mounts only the active tab panel where Tremor mounted all of them, so the budgets Examples code blocks now render on demand

Final Attestation

  • The tests check the right things, including the edge cases, and regressions in the respective real-world customer use-cases are not possible after this PR

…ration

Adds a role/text-based characterisation test for UIThemeSettings, which had
none, and extends the skills panel test to cover the delete confirmation.
Both are green against the current antd/Tremor components so they can prove
the shadcn migration keeps behaviour identical without being edited.
Replaces antd and Tremor with the installed shadcn primitives on the three
route-exclusive panels: Tremor tabs, buttons and text on budgets; the antd
delete Modal and Tremor button on skills; the Tremor card, inputs and buttons
on ui-theme.

Markup only, no behaviour change. The characterisation tests added in the
previous commit are untouched and stay green, and the ui-theme inputs now
carry real label associations.

Shared components stay on antd; they are reached by other routes and are
migrated separately. The form-bearing files on these routes are left alone.
@greptile-apps

greptile-apps Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Migrates three dashboard surfaces from Ant Design and Tremor to existing shadcn primitives

  • Replaces the budgets page tabs, buttons, and text components
  • Replaces the skills deletion modal and expands confirmation-flow tests
  • Replaces UI theme form controls and adds save, reset, loading, and error tests
  • Removes obsolete restricted-import suppressions

Confidence Score: 5/5

The PR appears safe to merge with no concrete changed-code failures identified

The migrated components use supported local primitive APIs, preserve their existing data operations and authorization behavior, and add focused tests for the newly migrated interactions

Important Files Changed

Filename Overview
ui/litellm-dashboard/src/app/(dashboard)/budgets/_components/budget_panel.tsx Migrates nested budget and example tabs to supported local primitives without changing budget operations
ui/litellm-dashboard/src/app/(dashboard)/skills/_components/ClaudeCodePluginsPanel.tsx Migrates deletion confirmation to the controlled alert-dialog primitive while retaining confirmation and pending-state behavior
ui/litellm-dashboard/src/app/(dashboard)/skills/_components/ClaudeCodePluginsPanel.test.tsx Adds focused coverage for confirmation, cancellation, deletion, and list refresh behavior
ui/litellm-dashboard/src/app/(dashboard)/ui-theme/UIThemeSettings.tsx Migrates theme settings markup to local card, input, label, button, and spinner primitives while preserving persistence behavior
ui/litellm-dashboard/src/app/(dashboard)/ui-theme/UIThemeSettings.test.tsx Adds coverage for initial loading, saving, backend errors, reset persistence, and missing-token behavior

Reviews (1): Last reviewed commit: "Merge remote-tracking branch 'origin/lit..." | Re-trigger Greptile

@devin-ai-integration

Copy link
Copy Markdown
Contributor

QA: verified end-to-end, all runbook scenarios pass

Ran the dashboard dev server (npm run dev, :3000) against a local LiteLLM proxy on :4000 (master-key auth) and exercised the three migrated routes through the UI, cross-checking state via the proxy API. No behavioral change observed; the shadcn markup renders and functions correctly.

Skills delete (antd Modal → shadcn AlertDialog)

Confirmation names the skill and warns "This action cannot be undone." Cancel deletes nothing (API count stays 1); confirm shows a success toast and removes the row (API count 0, gone from LiteLLM_ClaudeCodePluginTable).

Delete confirmation
Deleted

Budgets (Tremor → ui/tabs, ui/button)

List + "+ Create Budget" modal render; Examples nested tabs swap the code block with the active underline following the selection and no horizontal scrollbar.

Create Budget modal
Examples tabs

UI Theme (Tremor → ui/card, ui/input, ui/label, ui/button)

Save persists (GET /get/ui_theme_settings returns the saved URLs); Reset clears both to null; at ~1280x480 the content scrolls and both buttons stay reachable.

Saved
Small viewport

Tested via Devin: https://app.devin.ai/sessions/06c407dfca0d455ab486fc83e359fff4

@yuneng-berri
yuneng-berri enabled auto-merge July 24, 2026 06:31
@yuneng-berri
yuneng-berri merged commit 2bd7c86 into litellm_internal_staging Jul 24, 2026
75 checks passed
@yuneng-berri
yuneng-berri deleted the litellm_/dazzling-gagarin-3d4c69 branch July 24, 2026 14:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants