mirror of
https://github.com/BerriAI/litellm.git
synced 2026-08-28 05:25:59 +00:00
* fix(ui): restore hover feedback and dark-mode variants lost in the token 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. * fix(ui): add an eslint rule that fails a hover: utility identical to 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.
40 lines
1.2 KiB
JavaScript
40 lines
1.2 KiB
JavaScript
const noopHovers = (value) => {
|
|
const tokens = value.split(/\s+/).filter(Boolean);
|
|
const bare = new Set(tokens.filter((t) => !t.includes(":")));
|
|
return tokens
|
|
.filter((t) => t.startsWith("hover:"))
|
|
.map((t) => [t, t.slice("hover:".length)])
|
|
.filter(([, base]) => bare.has(base));
|
|
};
|
|
|
|
const rule = {
|
|
meta: {
|
|
type: "problem",
|
|
docs: {
|
|
description:
|
|
"Disallow a hover: utility whose value is identical to the base utility in the same class string, which renders no hover feedback.",
|
|
},
|
|
schema: [],
|
|
messages: {
|
|
noop: "`{{hover}}` is identical to the base `{{base}}`, so hovering changes nothing. Give it a distinct value (e.g. `{{hover}}/80`) or drop it.",
|
|
},
|
|
},
|
|
create(context) {
|
|
const check = (node, value) => {
|
|
if (typeof value !== "string" || !value.includes("hover:")) return;
|
|
for (const [hover, base] of noopHovers(value)) {
|
|
context.report({ node, messageId: "noop", data: { hover, base } });
|
|
}
|
|
};
|
|
return {
|
|
Literal(node) {
|
|
check(node, node.value);
|
|
},
|
|
TemplateElement(node) {
|
|
check(node, node.value.cooked);
|
|
},
|
|
};
|
|
},
|
|
};
|
|
|
|
export default rule;
|