Skip to content

refactor(ui): migrate guardrails-monitor, projects, logs to shadcn#34606

Open
yuneng-berri wants to merge 2 commits into
litellm_internal_stagingfrom
litellm_/gracious-lovelace-422633
Open

refactor(ui): migrate guardrails-monitor, projects, logs to shadcn#34606
yuneng-berri wants to merge 2 commits into
litellm_internal_stagingfrom
litellm_/gracious-lovelace-422633

Conversation

@yuneng-berri

Copy link
Copy Markdown
Collaborator

TLDR

Problem this solves:

  • guardrails-monitor, projects and logs still render antd and Tremor
  • an antd-only spinner primitive sat inside the shadcn ui/ folder
  • three of the migrated components had no test at all

How it solves it:

  • migrates the files those three routes exclusively own onto shadcn
  • deletes AntDLoadingSpinner, moving its one call site to ui/ui-loading-spinner
  • pins behaviour with role and text tests first, then migrates without editing them

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

Verified against a live proxy with a seeded postgres, driving each migrated surface by hand at commit bb33bdba7a. Screenshots are attached as comments below.

The projects list and the logs page both moved visually. guardrails-monitor did not: its landing view is GuardrailsOverview, which is a table and stays on the old stack in this PR, so the two files migrated for that route (the detail view and its modal) both sit behind a click and never appear in the landing screenshot. That is expected, not a missed migration.

Click-through to reproduce, with a proxy on localhost:4000:

  1. Open http://localhost:4000/ui/?page=logs. Confirm the four tabs read Request Logs, Audit Logs, Deleted Keys, Deleted Teams, that they sit at their natural width, and that switching tabs does not remount the panel you came from
  2. On Audit Logs, click an Object ID to open the detail drawer. Confirm the action badge, the timestamp, the Details block with working copy buttons, and that Before/After show only the fields that actually changed
  3. Open http://localhost:4000/ui/?page=projects. Confirm the header, the search box with its clear button, and the table
  4. Click a project id. Confirm the detail page: status badge, copyable id, Project Details, Budget with its utilisation meter, Spend by Model, Keys and Team
  5. Shrink the window to roughly 1280x600 on that page and confirm it scrolls to the bottom rather than clipping
  6. Open http://localhost:4000/ui/?page=guardrails-monitor, click a guardrail, and confirm the detail header, the Overview and Logs tabs, and the metric cards
  7. Click the gear to open Evaluation Settings. At a short window the dialog should stay inside the viewport and scroll internally, with Run Evaluation reachable and disabled until a model is picked

Type

🧹 Refactoring

Changes

Migrated, grouped by the route that exclusively owns each file.

guardrails-monitor: EvaluationSettingsModal.tsx and GuardrailDetail.tsx. GuardrailsMonitorView.tsx is listed as in scope but has nothing to migrate; its only remaining Tremor reference is import type { DateRangePickerValue }, which is the prop type of the shared advanced_date_picker and cannot move until that shared component does.

projects: ProjectDetailsPage.tsx, ProjectKeysSection.tsx and ProjectsPage.tsx. antd Descriptions becomes a description list, Progress becomes ui/meter with its tone variants, and the hardcoded hex strokes are gone.

logs: DeletedKeysPage.tsx, DeletedTeamsPage.tsx, AuditLogDrawer.tsx and view_logs/index.tsx. The drawer becomes a ui/sheet and reuses the exported AUDIT_TABLE_NAME_DISPLAY instead of keeping its own copy of that map.

src/components/ui/AntDLoadingSpinner.tsx is deleted along with its test. It wrapped antd Spin and lived in the shadcn primitives folder despite not being one. view_logs/index.tsx was its only consumer repo-wide and now uses ui/ui-loading-spinner; its stale eslint-suppressions.json entry is pruned along with the antd import suppressions the migration retires.

Two changes are not purely markup, both flagged deliberately. The logs tab handler used to map every tab past the first to "audit logs", so the audit panel kept polling while Deleted Keys or Deleted Teams was on screen; each tab now reports its own value, and keepMounted preserves the previous mount-all behaviour so switching tabs loses no panel state. Separately, the evaluation settings dialog is now bounded to the viewport and scrolls internally: the antd Modal got that for free by being top-anchored on a scrolling page, and without it the title and the footer buttons were both unreachable below roughly 660px of window height.

Not touched, quoting the scope analysis: GuardrailsOverview.tsx is a TABLE and belongs to the simple-table migration; the project and guardrail modals plus check_openapi_schema.tsx are DEFERRED because they contain an antd Form; and everything under SHARED, including LogViewer, advanced_date_picker, the LogDetailsDrawer tree and DefaultProxyAdminTag, is reached by more than one route and is left alone.

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

…onents before migration

Adds role- and text-based characterisation tests for EvaluationSettingsModal,
GuardrailDetail and AuditLogDrawer, which had none, and moves the remaining
antd-specific assertions (.ant-spin, the icon role of an antd Spin indicator)
onto library-neutral ARIA queries. Also covers the enterprise banner on the
deleted keys and deleted teams pages, which no test reached.

All of these pass against the current antd and Tremor components.
Replaces antd and Tremor with installed shadcn primitives across the files
these three routes exclusively own. Markup only, except where noted below.

Deletes AntDLoadingSpinner, an antd-only primitive living in the shadcn ui/
folder, and moves its single call site onto ui/ui-loading-spinner.

Two behaviour notes. The logs tab handler previously mapped every tab past
the first to "audit logs", so the audit panel kept polling while Deleted
Keys or Deleted Teams was on screen; each tab now reports its own value and
panels stay mounted via keepMounted. The evaluation settings dialog is
bounded to the viewport and scrolls internally, which the antd Modal got
from being top-anchored on a scrolling page.

The tests added in the previous commit pass unedited against these
components.
@greptile-apps

greptile-apps Bot commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Migrates the guardrails monitor, projects, and logs interfaces from Ant Design and Tremor to shared shadcn primitives

  • Replaces legacy dialogs, tabs, drawers, cards, badges, progress indicators, and loading states
  • Preserves logs tab panel state while assigning each tab its own active value
  • Adds and updates component tests for migrated behavior
  • Removes the obsolete Ant Design loading-spinner wrapper and stale lint suppressions

Confidence Score: 5/5

The PR appears safe to merge with no additional follow-up failures identified

No blocking failures remain

Important Files Changed

Filename Overview
ui/litellm-dashboard/src/components/view_logs/index.tsx Replaces Tremor tabs and the Ant Design spinner with shared shadcn primitives while preserving mounted panel state
ui/litellm-dashboard/src/app/(dashboard)/guardrails-monitor/_components/EvaluationSettingsModal.tsx Migrates evaluation settings to the shared dialog, select, textarea, and button components with viewport-bounded scrolling
ui/litellm-dashboard/src/app/(dashboard)/guardrails-monitor/_components/GuardrailDetail.tsx Migrates guardrail detail controls, status presentation, loading state, metrics layout, and tabs to shared primitives
ui/litellm-dashboard/src/app/(dashboard)/projects/_components/ProjectDetailsPage.tsx Rebuilds the project details layout with shared cards, badges, copy controls, meters, and loading components
ui/litellm-dashboard/src/components/view_logs/AuditLogDrawer/AuditLogDrawer.tsx Migrates audit-log details from an Ant Design drawer to the shared sheet implementation
ui/litellm-dashboard/src/components/DeletedKeysPage/DeletedKeysPage.tsx Migrates deleted-key presentation controls to shared UI primitives
ui/litellm-dashboard/src/components/DeletedTeamsPage/DeletedTeamsPage.tsx Migrates deleted-team presentation controls to shared UI primitives

Reviews (2): Last reviewed commit: "refactor(ui): migrate guardrails-monitor..." | Re-trigger Greptile

Comment on lines +64 to +69
<TabsContent value="deleted keys" keepMounted>
<DeletedKeysPage />
</TabsContent>
<TabsContent value="deleted teams" keepMounted>
<DeletedTeamsPage />
</TabsContent>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Hidden tabs issue background queries

Using keepMounted mounts the deleted-key and deleted-team panels when the logs page opens, and those panels do not gate their queries on the active tab. This sends two unnecessary API requests even when the user never opens either tab, adding avoidable network traffic and server work.

@yuneng-berri

Copy link
Copy Markdown
Collaborator Author

@greptile this PR did not introduce the behavior and migrating it will be out of scope. Review again

@devin-ai-integration

Copy link
Copy Markdown
Contributor

QA'd this live against a local proxy (python litellm/proxy/proxy_cli.py --config ... --port 4000, Postgres in Docker, two litellm_content_filter guardrails, real claude-haiku-4-5 traffic) with the dashboard dev server on :3000, seeded with three projects, three teams (one deleted), several keys (two deleted, one updated first) and 16 audit rows. All six scenarios from the test plan pass; the only caveat is the budget meter, which I could never drive above 0% (details below)

Note for anyone repeating this: the standalone dev server serves App Router paths, so it's http://localhost:3000/logs/, /projects/ and /guardrails-monitor/; the ?page= form from the description 404s there

  • Logs tabs render on shadcn at natural width, each tab owns its value, and panels keep their state across switches: passed
  • Audit drawer opens as the shared Sheet with the action badge, timestamp, copy controls and changed-fields-only Before/After: passed
  • Projects search narrows to one row and the X clears it back to three: passed
  • Project detail shows the status badge, copyable id, budget meter, Spend by Model, Keys and Team, and scrolls to the last card at 1280x600: passed, with the meter only ever observed at 0%
  • Guardrail detail header, Overview/Logs tabs and metric cards match the overview row (Requests Evaluated 6): passed
  • Evaluation Settings stays inside a 600px-tall viewport, scrolls internally, and Run Evaluation is disabled until a model is picked: passed
  • Audit polling stops while another tab is active: no GET /audit for 60s parked on Deleted Keys, resumes on switching back: passed
Audit drawer: changed fields only

The updated team's After panel contains just max_budget; unchanged fields aren't repeated

Updated team drawer

The deleted team shows the red badge, the object in Before and N/A in After

Deleted team drawer

Evaluation Settings at 1280x600

Dialog stays inside the viewport with the footer reachable, and Run Evaluation is disabled with no model

Dialog bounded, Run Evaluation disabled

After selecting anthropic-haiku-4-5 it enables

Run Evaluation enabled

Logs tabs and Deleted Keys / Deleted Teams panels

Request Logs

Deleted Keys

Deleted Teams

Projects search and clear

Filtered to billing-service

Cleared

Project detail, full width and at 1280x600

Project detail

Short window, top

Short window, scrolled to the last cards

Guardrail detail

Overview tab

Logs tab

Two things I could not prove and that aren't regressions from this diff. The budget meter never rendered a filled state: I pushed three real completions through a key attached to checkout-service, but project-level spend stayed at 0.0 on /project/list, so only the empty track was exercised. Separately, the Guardrails Monitor summary still reports Blocked Requests 0 / Pass Rate 100% even though two requests were blocked by the content filter; that's the untouched overview surface reading the usage endpoints, worth a look on its own

CI is green apart from osv-scan, which flags gitpython, brace-expansion and postcss in lockfiles this PR doesn't touch

Devin session: https://app.devin.ai/sessions/67fa12c8ed474130bf6266b0f57aa021

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.

1 participant