fix(theme): contrast on primary buttons and muted text in light mode

- introduce --color-on-primary (navy-950 in dark, white in light)
  so text on bg-teal-500 reads clearly regardless of mode; swap
  hardcoded text-navy-950 occurrences on teal fills for text-on-primary
- darken --color-fg-muted in light mode from slate-400 (#94a3b8) to
  slate-500 (#64748b); slate-400 failed AA on the tinted page
- deepen page tint to #eef2f7 and strengthen line/line-strong so
  white cards have real edges, not invisible hairlines

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Bryan Helmkamp 2026-04-19 17:12:01 -04:00
parent d0e23848d8
commit b448a4e246
No known key found for this signature in database
9 changed files with 24 additions and 19 deletions

View file

@ -53,6 +53,10 @@
--color-line: rgba(255, 255, 255, 0.06);
--color-line-strong: rgba(255, 255, 255, 0.12);
--color-focus: rgba(103, 178, 215, 0.4);
/* Text color that sits on --color-teal-500 primary fills.
Dark mode: teal-500 is light (#67B2D7) so dark text reads best.
Light mode: teal-500 is dark (#0e7490) so white reads best. */
--color-on-primary: #0F1729;
}
/* ── Light theme overrides ── */
@ -60,18 +64,19 @@
.light {
/* Semantic tokens page is softly tinted so panels/cards (white)
read as the lighter surface, mirroring the dark-theme hierarchy. */
--color-page: #f3f6fa;
--color-page: #eef2f7;
--color-panel: #ffffff;
--color-panel-alt: #e9eef5;
--color-overlay: rgba(15, 23, 41, 0.04);
--color-overlay-strong: rgba(15, 23, 41, 0.08);
--color-panel-alt: #e4eaf1;
--color-overlay: rgba(15, 23, 41, 0.05);
--color-overlay-strong: rgba(15, 23, 41, 0.10);
--color-fg: #0f172a;
--color-fg-2: #1e293b;
--color-fg-3: #475569;
--color-fg-muted: #94a3b8;
--color-line: rgba(15, 23, 41, 0.08);
--color-line-strong: rgba(15, 23, 41, 0.14);
--color-fg-muted: #64748b;
--color-line: rgba(15, 23, 41, 0.10);
--color-line-strong: rgba(15, 23, 41, 0.18);
--color-focus: rgba(14, 116, 144, 0.5);
--color-on-primary: #ffffff;
/* Accent — darkened for WCAG AA on white */
--color-mint: #0d9488;

View file

@ -6,7 +6,7 @@ export const INPUT_CLASS =
"block w-full rounded-lg bg-panel-alt px-3.5 py-2.5 text-base text-fg outline-1 -outline-offset-1 outline-white/10 placeholder:text-fg-muted focus:outline-2 focus:-outline-offset-1 focus:outline-teal-500 sm:text-sm";
export const PRIMARY_BUTTON_CLASS =
"inline-flex items-center justify-center gap-2 rounded-lg bg-teal-500 px-4 py-2 text-sm font-medium text-navy-950 transition-colors hover:bg-teal-300 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-teal-500 disabled:cursor-not-allowed disabled:opacity-60 disabled:hover:bg-teal-500";
"inline-flex items-center justify-center gap-2 rounded-lg bg-teal-500 px-4 py-2 text-sm font-medium text-on-primary transition-colors hover:bg-teal-300 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-teal-500 disabled:cursor-not-allowed disabled:opacity-60 disabled:hover:bg-teal-500";
export const SECONDARY_BUTTON_CLASS =
"inline-flex items-center justify-center gap-2 rounded-lg bg-transparent px-3.5 py-2 text-sm font-medium text-fg-2 outline-1 -outline-offset-1 outline-white/10 hover:bg-overlay hover:text-fg focus-visible:outline-2 focus-visible:-outline-offset-1 focus-visible:outline-teal-500";

View file

@ -708,9 +708,9 @@ function Stepper({
const isLast = index === STEPPER_STEPS.length - 1;
const isLinkable = isComplete || isCurrent;
const circleClass = isComplete
? "bg-mint text-navy-950"
? "bg-mint text-on-primary"
: isCurrent
? "bg-teal-500 text-navy-950"
? "bg-teal-500 text-on-primary"
: "bg-overlay text-fg-muted outline-1 -outline-offset-1 outline-white/10";
const labelClass = isCurrent
? "text-fg"

View file

@ -113,7 +113,7 @@ export default function RunDetail({ loaderData, params }: any) {
<button
type="submit"
disabled={previewFetcher.state !== "idle"}
className="inline-flex shrink-0 items-center justify-center gap-2 rounded-lg bg-teal-500 px-3.5 py-1.5 text-sm font-medium text-navy-950 transition-colors hover:bg-teal-300 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-teal-500 disabled:cursor-not-allowed disabled:opacity-60 disabled:hover:bg-teal-500"
className="inline-flex shrink-0 items-center justify-center gap-2 rounded-lg bg-teal-500 px-3.5 py-1.5 text-sm font-medium text-on-primary transition-colors hover:bg-teal-300 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-teal-500 disabled:cursor-not-allowed disabled:opacity-60 disabled:hover:bg-teal-500"
>
<svg viewBox="0 0 20 20" fill="currentColor" className="size-3.5 shrink-0" aria-hidden="true">
<path d="M10 12.5a2.5 2.5 0 1 0 0-5 2.5 2.5 0 0 0 0 5Z" />

View file

@ -131,7 +131,7 @@ export default function Start({ loaderData }: any) {
<button
onClick={handleSubmit}
disabled={!prompt.trim()}
className="flex items-center justify-center size-8 rounded-lg bg-teal-500 text-navy-950 transition-all duration-200 hover:bg-teal-300 disabled:opacity-30 disabled:hover:bg-teal-500 disabled:cursor-default"
className="flex items-center justify-center size-8 rounded-lg bg-teal-500 text-on-primary transition-all duration-200 hover:bg-teal-300 disabled:opacity-30 disabled:hover:bg-teal-500 disabled:cursor-default"
>
<ArrowUpIcon className="size-4" />
</button>

File diff suppressed because one or more lines are too long

View file

@ -17,7 +17,7 @@
(function(){try{var t=localStorage.getItem("fabro-theme");if(t!=="light"&&t!=="dark")t="dark";document.documentElement.classList.add(t)}catch(e){document.documentElement.classList.add("dark")}})()
</script>
<link rel="stylesheet" href="/assets/app.css" />
<link rel="stylesheet" href="/assets/entry-gcen40sq.css" />
<link rel="stylesheet" href="/assets/entry-g7fj8z7g.css" />
</head>
<body class="h-full font-sans antialiased">
<div id="root"></div>
@ -61,7 +61,7 @@
<script type="module" src="/assets/chunk-sadshphz.js"></script>
<script type="module" src="/assets/chunk-pmthkscp.js"></script>
<script type="module" src="/assets/chunk-v61ks9f7.js"></script>
<script type="module" src="/assets/entry-nsnsy3sn.js"></script>
<script type="module" src="/assets/entry-h24h4gjh.js"></script>
<script type="module" src="/assets/chunk-n1k68xa8.js"></script>
<script type="module" src="/assets/chunk-rsph5pvm.js"></script>
<script type="module" src="/assets/chunk-9t57pdty.js"></script>