feat(theme): R10 S1 — semantic status colors (danger/warn/success)

Add theme-scoped --danger/--warn/--success (+ -fg) tokens wired into the v4
@theme inline, replacing ~110 raw red/amber/emerald/green palette refs across
34 files. Fixes light-theme contrast failures (fixed Tailwind shades fell to
~1.7-3:1 on white). Status colors are scheme-independent — recognised by hue,
shifting only by theme to hold contrast (bright on dark bg, darkened on light).
Solid fills use the paired -fg text; @source inline guarantees the full -fg set
exists. IMDb rating gold kept as a deliberate decorative non-status exception.
This commit is contained in:
2026-08-09 01:03:53 +02:00
parent 9ca0c61ea9
commit d794524adf
35 changed files with 123 additions and 85 deletions
+9 -9
View File
@@ -46,9 +46,9 @@ function fmtCountdown(s: number): string {
const DOT_CLASS: Record<string, string> = {
running: "bg-accent animate-pulse",
ok: "bg-emerald-500",
error: "bg-red-500",
skipped: "bg-amber-500",
ok: "bg-success",
error: "bg-danger",
skipped: "bg-warn",
idle: "bg-border",
};
@@ -178,7 +178,7 @@ function JobRow({
<button
onClick={save}
disabled={saving}
className="text-emerald-400 hover:opacity-80 disabled:opacity-50"
className="text-success hover:opacity-80 disabled:opacity-50"
aria-label={t("common.save")}
>
<Check className="w-3.5 h-3.5" />
@@ -210,7 +210,7 @@ function JobRow({
? t("scheduler.lastRun", { time: relativeTime(job.last_finished) })
: t("scheduler.neverRun")}
{job.last_error ? (
<span className="text-red-400"> · {job.last_error}</span>
<span className="text-danger"> · {job.last_error}</span>
) : job.last_result ? (
<span> · {job.last_result}</span>
) : null}
@@ -448,7 +448,7 @@ export default function Scheduler() {
<span className="inline-flex items-center gap-1">
<span
className={`w-2 h-2 rounded-full ${
data.paused ? "bg-amber-500" : data.running_here ? "bg-emerald-500" : "bg-border"
data.paused ? "bg-warn" : data.running_here ? "bg-success" : "bg-border"
}`}
/>
{data.paused
@@ -502,8 +502,8 @@ export default function Scheduler() {
</div>
{!data.running_here && (
<div className="flex items-center gap-2 text-sm bg-amber-500/15 border border-amber-500/30 rounded-xl px-3 py-2">
<AlertTriangle className="w-4 h-4 text-amber-500 shrink-0" />
<div className="flex items-center gap-2 text-sm bg-warn/15 border border-warn/30 rounded-xl px-3 py-2">
<AlertTriangle className="w-4 h-4 text-warn shrink-0" />
<span className="text-muted">{t("scheduler.notHereNote")}</span>
</div>
)}
@@ -591,7 +591,7 @@ export default function Scheduler() {
</div>
<div className="mt-2 h-2 rounded-full bg-border overflow-hidden">
<div
className={`h-full rounded-full ${quotaPct > 90 ? "bg-red-500" : "bg-accent"}`}
className={`h-full rounded-full ${quotaPct > 90 ? "bg-danger" : "bg-accent"}`}
style={{ width: `${quotaPct}%` }}
/>
</div>