Skip to content

Commit 1707701

Browse files
authored
fix: Dark Mode UI & UX Improvements (#45)
## Summary This PR implements a comprehensive dark mode overhaul to fix visibility issues, poor contrast, and hardcoded colors across the application. It also resolves a critical SSR crash related to localStorage access. ## Key Changes - **Theme Overhaul**: Switched from harsh pure black (`#000000`) to professional dark slate (`#0F172A`) for better eye comfort. - **Component Fixes**: - `TransactionTable`: Fixed invisible retention notices and row hover states. - `MilestoneCard` & `StatusBadge`: Replaced hardcoded colors with theme-aware tokens. - `Header` & `SearchCard`: Fixed text contrast and element visibility. - **SSR Fixes**: Implemented `safeLocalStorage` utility to prevent server-side crashes in `ThemeToggle` and `NetworkContext`. - **UX Improvements**: Added semantic color tokens for success/warning/error states that adapt to both light and dark modes. ## Testing - Verified on Desktop and Mobile views. - Checked all routes: Home, Escrow Details, Transaction History. - Validated contrast ratios for accessibility. Fixes #40 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Fixed theme toggle hydration and prevented dev-time localStorage crashes for more reliable behavior. * **New Features** * Safer preference persistence for theme and network selections to improve consistency across sessions. * **Style** * Broad dark-mode redesign: deeper slate tones, improved contrast, updated colors across navigation, tables, cards, badges, buttons, and escrow components; enhanced hover/focus visuals. <sub>✏️ Tip: You can customize this high-level summary in your review settings.</sub> <!-- end of auto-generated comment: release notes by coderabbit.ai -->
2 parents 6a1fd23 + fa3631e commit 1707701

24 files changed

+279
-196
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,4 @@ yarn-error.log*
3939
# typescript
4040
*.tsbuildinfo
4141
next-env.d.ts
42+

package-lock.json

Lines changed: 20 additions & 19 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/app/globals.css

Lines changed: 41 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -80,40 +80,51 @@
8080
}
8181

8282
.dark {
83-
--background: #000000;
84-
--foreground: #E2E8F0; /* bright neutral, readable text */
83+
/* Base: Professional dark slate - softer than pure black for eye comfort */
84+
--background: #0F172A; /* slate-900 - professional, not harsh */
85+
--foreground: #F8FAFC; /* slate-50 - bright, readable text */
8586

86-
--card: #070708;
87-
--card-foreground: #F1F5F9; /* bright text on cards */
87+
/* Cards: Elevated surfaces - clearly visible above background */
88+
--card: #1E293B; /* slate-800 - clear elevation above bg */
89+
--card-foreground: #F8FAFC; /* slate-50 - bright text on cards */
8890

89-
--popover: #080809;
90-
--popover-foreground: #F1F5F9;
91+
/* Popovers: Same elevation as cards */
92+
--popover: #1E293B;
93+
--popover-foreground: #F8FAFC;
9194

95+
/* Primary: Vibrant cyan-blue accent - good contrast in dark */
9296
--primary: #0EA5FF;
93-
--primary-foreground: #001219;
97+
--primary-foreground: #0F172A;
9498

95-
--secondary: #1E293B;
96-
--secondary-foreground: #E2E8F0;
99+
/* Secondary: Elevated surface for secondary actions */
100+
--secondary: #334155; /* slate-700 - visible secondary surfaces */
101+
--secondary-foreground: #F1F5F9;
97102

98-
--muted: #0f1b2d;
99-
--muted-foreground: #94A3B8; /* slate-400 for softer, still legible text */
103+
/* Muted: Subtle backgrounds and secondary text */
104+
--muted: #334155; /* slate-700 - visible muted backgrounds */
105+
--muted-foreground: #CBD5E1; /* slate-300 - readable secondary text */
100106

101-
--accent: #075985;
102-
--accent-foreground: #F1F5F9;
107+
/* Accent: Slightly brighter for visibility */
108+
--accent: #0EA5E9; /* sky-500 - visible accent color */
109+
--accent-foreground: #F8FAFC;
103110

111+
/* Destructive: Bright red for errors */
104112
--destructive: #EF4444;
105-
--border: #1E293B;
106-
--input: #1E293B;
107-
--ring: rgba(14,165,255,0.25);
113+
114+
/* Borders: Visible separators */
115+
--border: #334155; /* slate-700 - actually visible borders */
116+
--input: #334155; /* visible input borders */
117+
--ring: rgba(14, 165, 255, 0.35); /* brighter focus ring */
108118

109-
--sidebar: #0F172A;
110-
--sidebar-foreground: #E2E8F0;
111-
--sidebar-primary: #1E3A8A;
112-
--sidebar-primary-foreground: #E2E8F0;
113-
--sidebar-accent: #075985;
114-
--sidebar-accent-foreground: #F1F5F9;
115-
--sidebar-border: rgba(255,255,255,0.04);
116-
--sidebar-ring: rgba(14,165,255,0.18);
119+
/* Sidebar: Consistent with card elevation */
120+
--sidebar: #1E293B;
121+
--sidebar-foreground: #F8FAFC;
122+
--sidebar-primary: #0EA5FF;
123+
--sidebar-primary-foreground: #0F172A;
124+
--sidebar-accent: #0EA5E9;
125+
--sidebar-accent-foreground: #F8FAFC;
126+
--sidebar-border: #334155;
127+
--sidebar-ring: rgba(14, 165, 255, 0.25);
117128
}
118129

119130
@layer base {
@@ -200,6 +211,11 @@
200211
box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.1);
201212
}
202213

214+
/* Dark mode hover shadow - more visible */
215+
.dark .hover-lift:hover {
216+
box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.4), 0 0 0 1px rgba(14, 165, 255, 0.1);
217+
}
218+
203219
/* Edge accent for cards: subtle inset highlight and depth that adapts to dark mode */
204220
.edge-accent {
205221
position: relative;
@@ -227,7 +243,7 @@
227243
}
228244

229245
.dark .edge-accent::after {
230-
background: linear-gradient(180deg, rgba(127,239,253,0.98), rgba(127,239,253,0.16));
246+
background: linear-gradient(180deg, rgba(14, 165, 255, 0.6), rgba(14, 165, 255, 0.2));
231247
background-size: 100% 200%;
232248
animation: edgeMove 6s linear infinite;
233249
mix-blend-mode: screen; /* keep screen for a brighter sheen on dark backgrounds */

src/app/layout.tsx

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,24 @@ import "./globals.css";
44
import { Suspense } from 'react'
55
import { NetworkProvider } from "@/contexts/NetworkContext";
66

7+
// Work around Node.js experimental localStorage mismatch in dev server
8+
// (prevents Next dev overlay from crashing when localStorage is non-standard)
9+
if (typeof window === 'undefined') {
10+
const storage = (globalThis as { localStorage?: unknown }).localStorage;
11+
if (!storage || typeof (storage as Storage).getItem !== 'function') {
12+
(globalThis as { localStorage?: Storage }).localStorage = {
13+
getItem: () => null,
14+
setItem: () => undefined,
15+
removeItem: () => undefined,
16+
clear: () => undefined,
17+
key: () => null,
18+
get length() {
19+
return 0;
20+
},
21+
} as Storage;
22+
}
23+
}
24+
725

826
const geistSans = Geist({
927
variable: "--font-geist-sans",

src/app/page.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,13 @@ const Home: NextPage = () => {
4444

4545
return (
4646
<TooltipProvider>
47-
<div className={`min-h-screen bg-gradient-to-b from-gray-50 to-blue-50 ${inter.className}`}>
47+
<div className={`min-h-screen bg-gradient-to-b from-gray-50 to-blue-50 dark:from-background dark:to-background ${inter.className}`}>
4848
<NavbarSimple />
4949

5050
<main className="container mx-auto px-4 py-12">
5151
{/* HERO */}
5252
<div className="relative">
53-
<div className="relative bg-white/95 dark:bg-card rounded-3xl p-8 md:p-12 shadow-2xl border border-gray-200/60 dark:border-[rgba(255,255,255,0.04)]">
53+
<div className="relative bg-white/95 dark:bg-card rounded-3xl p-8 md:p-12 shadow-2xl border border-gray-200/60 dark:border-border">
5454
<section className="flex flex-col-reverse md:flex-row items-center gap-8 md:gap-16">
5555

5656
{/* Left: text */}

src/components/Navbar.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ const inter = Inter({ subsets: ["latin"] });
1111
export function NavbarSimple() {
1212
return (
1313
<header
14-
className={`flex items-center justify-between gap-4 bg-white dark:bg-slate-900 rounded shadow-sm py-4 px-6 md:px-28 ${inter.className}`}
14+
className={`flex items-center justify-between gap-4 bg-white dark:bg-card rounded shadow-sm py-4 px-6 md:px-28 ${inter.className}`}
1515
>
1616
<div className="flex items-center gap-3">
1717
<Image

src/components/escrow/EscrowDetails.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,9 @@ useEffect(() => {
207207

208208
return (
209209
<TooltipProvider>
210+
210211
<div className={`min-h-screen bg-linear-to-b from-gray-50 to-blue-50 ${inter.className}`}>
212+
main
211213
<NavbarSimple />
212214

213215
<main className="container mx-auto px-4 py-6 md:py-10 max-w-7xl">
@@ -325,7 +327,7 @@ useEffect(() => {
325327
</div>
326328

327329
<div className="mb-4">
328-
<p className="text-sm text-gray-600 dark:text-[#6fbfe6]">Complete blockchain activity record for this escrow contract</p>
330+
<p className="text-sm text-muted-foreground">Complete blockchain activity record for this escrow contract</p>
329331
</div>
330332

331333
<div>
@@ -336,11 +338,11 @@ useEffect(() => {
336338
transition={{ delay: 0.05, duration: 0.4 }}
337339
>
338340
<motion.div
339-
className="absolute inset-0 bg-gradient-to-br from-blue-50/30 via-transparent to-purple-50/30 rounded-3xl -z-10"
341+
className="absolute inset-0 bg-gradient-to-br from-blue-50/30 via-transparent to-purple-50/30 dark:from-primary/5 dark:to-accent/5 rounded-3xl -z-10"
340342
animate={{ backgroundPosition: ["0% 0%", "100% 100%", "0% 0%"] }}
341343
transition={{ duration: 25, repeat: Infinity, ease: "linear" }}
342344
/>
343-
<div className="relative bg-white/95 dark:bg-[#070708] backdrop-blur-sm rounded-3xl shadow-2xl border border-gray-200/60 dark:border-[rgba(255,255,255,0.06)] dark:text-[#BFEFFD] overflow-hidden hover:shadow-3xl transition-all duration-700">
345+
<div className="relative bg-white/95 dark:bg-card backdrop-blur-sm rounded-3xl shadow-2xl border border-gray-200/60 dark:border-border overflow-hidden hover:shadow-3xl transition-all duration-700">
344346
<TransactionTable
345347
transactions={transactions}
346348
loading={transactionLoading}

src/components/escrow/LedgerBalancePanel.tsx

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,23 +17,23 @@ export function LedgerBalancePanel({
1717
animate={{ opacity: 1, y: 0 }}
1818
transition={{ duration: 0.3 }}
1919
>
20-
<div className="flex flex-col md:flex-row md:items-center md:justify-between gap-3 bg-white/80 backdrop-blur-sm border border-blue-100 rounded-2xl p-4 shadow-sm">
20+
<div className="flex flex-col md:flex-row md:items-center md:justify-between gap-3 bg-white/80 dark:bg-card backdrop-blur-sm border border-primary/20 rounded-2xl p-4 shadow-sm">
2121
<div className="flex items-center gap-3">
22-
<div className="w-2 h-8 bg-gradient-to-b from-blue-500 to-purple-500 rounded-full" />
22+
<div className="w-2 h-8 bg-gradient-to-b from-primary to-accent rounded-full" />
2323
<div>
24-
<div className="text-sm text-gray-600">Ledger balance (from token contract)</div>
25-
<div className="text-xl font-semibold text-gray-900">
24+
<div className="text-sm text-muted-foreground">Ledger balance (from token contract)</div>
25+
<div className="text-xl font-semibold text-foreground">
2626
{balance}
2727
{typeof decimals === "number" ? (
28-
<span className="ml-1 text-gray-500 text-sm">(d={decimals})</span>
28+
<span className="ml-1 text-muted-foreground text-sm">(d={decimals})</span>
2929
) : null}
3030
</div>
3131
</div>
3232
</div>
3333

3434
{mismatch && (
35-
<div className="inline-flex items-center gap-2 px-3 py-1 rounded-full bg-amber-100 text-amber-800 border border-amber-200">
36-
<span className="text-xs font-semibold">⚠️ Mismatch</span>
35+
<div className="inline-flex items-center gap-2 px-3 py-1 rounded-full bg-amber-100 dark:bg-amber-500/20 text-amber-800 dark:text-amber-300 border border-amber-200 dark:border-amber-500/30">
36+
<span className="text-xs font-semibold">Mismatch</span>
3737
<span className="text-xs">Stored contract balance differs</span>
3838
</div>
3939
)}

0 commit comments

Comments
 (0)