fix(theme): R10 S1 follow-ups — dedicated info token + restore collapsed hovers

- Add --info/--info-fg (blue; dark #60a5fa / light #2563eb) so info notifications
  stop borrowing --accent, which collided with a status colour in schemes whose
  accent shares its hue (YouTube red = error, Slate orange = warn, Matrix/Forest
  green = success). Toaster info tone accent -> info.
- Restore hover feedback the codemod flattened: 'bg-X ... hover:bg-X' /
  'text-X ... hover:text-X' collapsed to a no-op once both shades mapped to one
  shadeless token. Reuse the house hover:opacity-{80,90} idiom (ConfirmProvider
  danger button, DownloadCenter error link).
This commit is contained in:
2026-08-09 01:22:14 +02:00
parent d794524adf
commit bd2d001774
4 changed files with 10 additions and 4 deletions
+1 -1
View File
@@ -118,7 +118,7 @@ export function ConfirmProvider({ children }: { children: ReactNode }) {
multi ? "w-full" : "" multi ? "w-full" : ""
} ${ } ${
c.danger c.danger
? "bg-danger text-danger-fg hover:bg-danger" ? "bg-danger text-danger-fg hover:opacity-90"
: "bg-accent text-accent-fg hover:opacity-90" : "bg-accent text-accent-fg hover:opacity-90"
}`} }`}
> >
+1 -1
View File
@@ -253,7 +253,7 @@ function DownloadRow({
{job.status === "error" ? ( {job.status === "error" ? (
<button <button
onClick={() => onShowError?.(job)} onClick={() => onShowError?.(job)}
className="text-danger hover:text-danger inline-flex items-center gap-1 truncate" className="text-danger hover:opacity-80 inline-flex items-center gap-1 truncate"
title={t("downloads.errors.fail.title")} title={t("downloads.errors.fail.title")}
> >
· {t(`downloads.errors.fail.cat.${job.error_code || "unknown"}.short`)} · {t(`downloads.errors.fail.cat.${job.error_code || "unknown"}.short`)}
+1 -1
View File
@@ -4,7 +4,7 @@ import { AlertCircle, AlertTriangle, CheckCircle2, Info, X, XCircle } from "luci
import { dismiss, getActiveToasts, subscribe, type NotifLevel } from "../lib/notifications"; import { dismiss, getActiveToasts, subscribe, type NotifLevel } from "../lib/notifications";
export const LEVEL_STYLE: Record<NotifLevel, { icon: typeof Info; color: string; bar: string }> = { export const LEVEL_STYLE: Record<NotifLevel, { icon: typeof Info; color: string; bar: string }> = {
info: { icon: Info, color: "text-accent", bar: "bg-accent" }, info: { icon: Info, color: "text-info", bar: "bg-info" },
success: { icon: CheckCircle2, color: "text-success", bar: "bg-success" }, success: { icon: CheckCircle2, color: "text-success", bar: "bg-success" },
warning: { icon: AlertTriangle, color: "text-warn", bar: "bg-warn" }, warning: { icon: AlertTriangle, color: "text-warn", bar: "bg-warn" },
error: { icon: AlertCircle, color: "text-danger", bar: "bg-danger" }, error: { icon: AlertCircle, color: "text-danger", bar: "bg-danger" },
+7 -1
View File
@@ -4,7 +4,7 @@
bg-{status} fill always has a readable text-{status}-fg partner available bg-{status} fill always has a readable text-{status}-fg partner available
(Tailwind v4 only emits a utility when it sees it used; success-fg has no fill (Tailwind v4 only emits a utility when it sees it used; success-fg has no fill
consumer today). Keeps the semantic token set complete + future-proof. */ consumer today). Keeps the semantic token set complete + future-proof. */
@source inline("text-danger-fg text-warn-fg text-success-fg"); @source inline("text-danger-fg text-warn-fg text-success-fg text-info-fg");
/* `inline` is load-bearing: the color vars (--bg/--accent/… below) are redefined at /* `inline` is load-bearing: the color vars (--bg/--accent/… below) are redefined at
runtime per html[data-scheme]/[data-theme], so utilities must inline the value and runtime per html[data-scheme]/[data-theme], so utilities must inline the value and
@@ -20,6 +20,8 @@
--color-muted: var(--muted); --color-muted: var(--muted);
--color-accent: var(--accent); --color-accent: var(--accent);
--color-accent-fg: var(--accent-fg); --color-accent-fg: var(--accent-fg);
--color-info: var(--info);
--color-info-fg: var(--info-fg);
--color-danger: var(--danger); --color-danger: var(--danger);
--color-danger-fg: var(--danger-fg); --color-danger-fg: var(--danger-fg);
--color-warn: var(--warn); --color-warn: var(--warn);
@@ -683,6 +685,8 @@ html[data-theme="dark"] {
--warn-fg: #1f1400; --warn-fg: #1f1400;
--success: #34d399; --success: #34d399;
--success-fg: #052016; --success-fg: #052016;
--info: #60a5fa;
--info-fg: #08172e;
} }
html[data-theme="light"] { html[data-theme="light"] {
--danger: #dc2626; --danger: #dc2626;
@@ -691,6 +695,8 @@ html[data-theme="light"] {
--warn-fg: #ffffff; --warn-fg: #ffffff;
--success: #047857; --success: #047857;
--success-fg: #ffffff; --success-fg: #ffffff;
--info: #2563eb;
--info-fg: #ffffff;
} }
/* Toast auto-dismiss countdown bar (shrinks left-to-right to zero) */ /* Toast auto-dismiss countdown bar (shrinks left-to-right to zero) */