fix(ui): restore hover feedback and dark-mode variants lost in the token migration - #37579
Conversation
…ken migration PR #37576 mapped hardcoded Tailwind palette classes onto semantic tokens. Two-tone hover pairs collapsed onto a single token, so 116 hover utilities across 49 files became identical to their base class and produced no visible feedback, and in seven files a dark: variant was dropped while its hardcoded light partner survived, leaving those elements stuck light in dark mode. Hover states now follow the alpha-step idiom the shadcn primitives already use (hover:bg-primary/80, hover:bg-success/20): a duplicated hover:text-X or hover:bg-X becomes /80, hover:border-border becomes hover:border-ring, and a duplicate is dropped where another hover utility on the element already carries the change. One transition-colors that no longer animated anything is removed. For the dark-mode gaps, indigo maps onto info and amber onto warning. There is no purple token in globals.css, so the purple sites keep their palette classes and get their dark: partner back.
…itellm_/relaxed-pasteur-5b9529
…its base The token migration collapsed two-tone hover pairs by hand, so nothing catches the next one. `local/no-noop-hover-variant` reads every string literal and template chunk and errors when a `hover:X` sits alongside a bare `X`, which is exactly the shape that renders no hover feedback. It ships at error with no suppression baseline, so the eleven sites that already carried a dead hover before the migration are fixed here too. The rule reads one class string at a time, so a base class supplied by a different ternary branch than its hover partner is left alone: a selected row whose resting colour already matches its hover colour is deliberate, not a bug.
tin-berri
left a comment
There was a problem hiding this comment.
done — #37579 approved. Purely presentational fix (66 files, mostly one-line Tailwind class swaps): dead hover: variants where the hover value matched the base (e.g. hover:text-destructive → hover:text-destructive/80) and hardcoded light-mode colors (indigo-*, near-white blues) swapped for semantic tokens (info, warning) or explicit dark: variants where no semantic token exists (purple, called out in the PR's own caveats). The new no-noop-hover-variant eslint rule is a solid regression guard — it flags exactly this class of bug (hover utility identical to the base) going forward, and correctly scoped out of the rule's own test fixtures. No auth/billing/security surface, no logic changes. CI green aside from non-blocking pending checks (semgrep, code-quality, external Veria bot review).
Greptile SummaryThe PR restores dashboard hover feedback, adds dark-mode variants and semantic color tokens, and introduces an ESLint regression guard.
Confidence Score: 4/5The PR appears safe to merge, with one non-blocking destructive-button hover inconsistency worth correcting. The semantic tokens and dark variants are supported by the dashboard theme, and the new lint rule has focused coverage; the only accepted issue is a remove button inheriting the generic ghost foreground color on hover. Files Needing Attention: ui/litellm-dashboard/src/components/team/LoggingSettings.tsx
|
| Filename | Overview |
|---|---|
| ui/litellm-dashboard/scripts/eslint-rules/no-noop-hover-variant.mjs | Adds a narrowly scoped lexical check for identical bare and hover-prefixed utilities; no concrete false positive was established. |
| ui/litellm-dashboard/tests/eslint-rules/no-noop-hover-variant.test.ts | Covers valid distinct hover values, static strings, template elements, and multiple no-op utility categories. |
| ui/litellm-dashboard/src/components/team/LoggingSettings.tsx | Removes a redundant-looking hover class, but this exposes the ghost button’s generic foreground hover color and weakens the destructive affordance. |
| ui/litellm-dashboard/src/app/(dashboard)/mcp-servers/_components/MCPToolsetsTab.tsx | Adds matching dark-mode backgrounds, borders, and text colors to selected purple tool states. |
| ui/litellm-dashboard/src/app/(dashboard)/policies/_components/add_policy_form.tsx | Replaces fixed indigo selection styling with semantic info tokens that resolve in both themes. |
| ui/litellm-dashboard/src/components/shared/advanced_date_picker.tsx | Replaces no-op border hover states with the distinct ring border token. |
Reviews (1): Last reviewed commit: "fix(ui): add an eslint rule that fails a..." | Re-trigger Greptile
| onClick={() => removeLoggingConfig(index)} | ||
| size="sm" | ||
| className="text-destructive hover:bg-destructive/10 hover:text-destructive" | ||
| className="text-destructive hover:bg-destructive/10" |
There was a problem hiding this comment.
Destructive hover color is lost
Removing the explicit hover text color exposes the ghost button’s hover:text-foreground style, so the red remove icon changes to the normal foreground color on hover and weakens the destructive affordance.
| className="text-destructive hover:bg-destructive/10" | |
| className="text-destructive hover:bg-destructive/10 hover:text-destructive/80" |
Knowledge Base Used: Admin dashboard (ui/litellm-dashboard)
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
…cleanup (#37580) PR #37579 read `text-X hover:text-X` on a shadcn Button as dead weight and removed the hover half. On the ghost and outline variants it was not dead: both carry their own `hover:text-foreground`, and the duplicate in the className was the thing displacing it through tailwind-merge. Dropping it handed the hover back to the variant, so the Remove button in a team's logging settings, the chat storage banner's dismiss control, and the collapsed enterprise-usage rail all lose their colour the moment you point at them. Each of the three now carries a distinct hover value, following the alpha-step idiom the rest of that migration used, which restores the colour and keeps `local/no-noop-hover-variant` satisfied. Every other hover utility that PR dropped sits on a plain element or a variant with no competing `hover:text-`, so those stay as they are.
TLDR
Problem this solves:
How it solves it:
User Flow
Before: an admin picking an MCP transport gets no feedback from anything they point at, and the panel above stays bright white once they switch to dark mode
After: every control they point at responds, and the same screens follow the dark theme
Relevant issues
Linear ticket
Pre-Submission checklist
uv run pytest tests/test_litellm/<your_test_file>.py -v. Leave the suites (make test-unit-*,make test-unit) to CI: it finishes in ~15 minutes where a laptop takes an hour or more@greptileaito 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
Setup: run the dashboard dev server against a local proxy so the screens below render live
Dark mode has no in-app toggle yet, so switch it on from the browser console on each page:
Before (47a7e17)
Hover feedback
Dark mode
After (e96074f)
Hover feedback
Dark mode
Type
🐛 Bug Fix
Caveats (if any)
dark:classesinfo, which is a slightly different hueFinal Attestation