diff --git a/app/(dashboard)/settings/page.tsx b/app/(dashboard)/settings/page.tsx index ba67c24..4ceb15b 100644 --- a/app/(dashboard)/settings/page.tsx +++ b/app/(dashboard)/settings/page.tsx @@ -1,6 +1,6 @@ "use client" -import { type SyntheticEvent, useMemo, useState } from "react" +import { type SyntheticEvent, useMemo, useState, useEffect } from "react" import { Bell, Eye, @@ -120,6 +120,22 @@ export default function SettingsPage() { const [walletAlias, setWalletAlias] = useState(true) const [copyWarning, setCopyWarning] = useState(true) const { soundEnabled, setSoundEnabled } = useSoundEnabled() + const [forceHighContrast, setHighContrast] = useState(() => { + if (typeof window !== "undefined") { + return localStorage.getItem("force-high-contrast") === "true" + } + return false + }) + + useEffect(() => { + const root = window.document.documentElement + if (forceHighContrast) { + root.classList.add("high-contrast") + } else { + root.classList.remove("high-contrast") + } + localStorage.setItem("force-high-contrast", forceHighContrast.toString()) + }, [forceHighContrast]) const selectedDensity = useMemo( () => densityOptions.find((option) => option.value === density), @@ -306,6 +322,13 @@ export default function SettingsPage() { checked={showWalletBadge} onCheckedChange={setShowWalletBadge} /> + diff --git a/app/globals.css b/app/globals.css index fdc0a85..6ea0e53 100644 --- a/app/globals.css +++ b/app/globals.css @@ -270,6 +270,73 @@ body { } } +/* ===== HIGH CONTRAST MODE (Accessibility) ===== */ + +/** + * Native Windows High Contrast Support (forced-colors: active) + * and manual override (html.high-contrast) + */ +@media (forced-colors: active) { + :root { + /* Respect system colors while ensuring borders are visible */ + --border: CanvasText; + --input: CanvasText; + --ring: CanvasText; + } + + * { + /* Ensure all elements have visible borders in forced-colors mode */ + forced-color-adjust: none; + border-color: CanvasText !important; + } + + button, a.btn, .badge { + border: 2px solid CanvasText !important; + } + + /* Status badges meaning without color */ + .badge-success::before { content: "✓ "; } + .badge-warning::before { content: "⚠ "; } + .badge-error::before { content: "✕ "; } +} + +/* Manual "Force high contrast" override */ +.high-contrast { + --background: 0 0% 0%; + --foreground: 0 0% 100%; + --card: 0 0% 0%; + --card-foreground: 0 0% 100%; + --primary: 0 0% 100%; + --primary-foreground: 0 0% 0%; + --secondary: 0 0% 15%; + --secondary-foreground: 0 0% 100%; + --muted: 0 0% 20%; + --muted-foreground: 0 0% 100%; + --accent: 0 0% 30%; + --accent-foreground: 0 0% 100%; + --border: 0 0% 100%; + --input: 0 0% 100%; + --ring: 0 0% 100%; +} + +.high-contrast * { + border-color: white !important; + text-shadow: none !important; + box-shadow: none !important; +} + +.high-contrast button, +.high-contrast a.btn, +.high-contrast .badge { + border: 2px solid white !important; +} + +/* Ensure icons are visible */ +.high-contrast svg { + fill: currentColor !important; + stroke: currentColor !important; +} + /* ===== PRINT STYLES ===== */ @media print { diff --git a/components/icons/Chat.tsx b/components/icons/Chat.tsx index a31c573..94849b9 100644 --- a/components/icons/Chat.tsx +++ b/components/icons/Chat.tsx @@ -5,7 +5,7 @@ type Props = { const Chat = (props: Props) => { return ( - + ) } diff --git a/components/icons/StellarIcon.tsx b/components/icons/StellarIcon.tsx index fb5f56c..759c97a 100644 --- a/components/icons/StellarIcon.tsx +++ b/components/icons/StellarIcon.tsx @@ -4,8 +4,8 @@ type Props = { const StellarIcon = (props: Props) => { return ( -
- +
+
diff --git a/tailwind.config.ts b/tailwind.config.ts index f299134..7758939 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -122,6 +122,11 @@ const config: Config = { } } }, - plugins: [require("tailwindcss-animate")], + plugins: [ + require("tailwindcss-animate"), + function({ addVariant }: { addVariant: Function }) { + addVariant('high-contrast', '.high-contrast &') + } + ], }; export default config;