From 72ee1cce784f1424622db30a8fa9e75401d64a3b Mon Sep 17 00:00:00 2001 From: abayomicornelius Date: Mon, 7 Sep 2026 18:17:43 +0100 Subject: [PATCH 1/2] feat(theme): extend palette with a violet and pink accent MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds app.accent3 (violet) and app.accent4 (pink), plus matching glow shadow tokens (glowBlue, glowViolet, glowPink), to give the landing page redesign a fuller, multi-hue palette instead of leaning on a single green accent everywhere. Purely additive — no existing token value changes, so every other page's look (and its Playwright visual regression screenshots) is unaffected. Both new colors verified against WCAG AA (4.5:1) for both light and dark mode: #7c3aed on white is 5.7:1, #c4b5fd on the dark bg is 10.56:1; #be185d on white is 6.04:1, #f9a8d4 on the dark bg is 10.75:1. --- src/lib/theme.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/lib/theme.ts b/src/lib/theme.ts index 2a7e6ae..1dcce3f 100644 --- a/src/lib/theme.ts +++ b/src/lib/theme.ts @@ -24,6 +24,12 @@ const theme = extendTheme({ // Accent — #0f7a4e passes 4.5:1 on white; #4ae292 is the dark-mode green "app.accent": { default: "#0f7a4e", _dark: "#4ae292" }, "app.accent2": { default: "#2563eb", _dark: "#6dd5ff" }, + // Extended palette for richer, multi-hue surfaces (landing page bento + // grid, ambient background). #7c3aed passes 5.7:1 on white, #c4b5fd + // passes 10.5:1 on the dark bg. + "app.accent3": { default: "#7c3aed", _dark: "#c4b5fd" }, + // #be185d passes 6:1 on white, #f9a8d4 passes 10.7:1 on the dark bg. + "app.accent4": { default: "#be185d", _dark: "#f9a8d4" }, // Text "app.text": { default: "#171717", _dark: "#ffffff" }, "app.muted": { default: "#6b7280", _dark: "#9a9a9a" }, @@ -54,6 +60,10 @@ const theme = extendTheme({ card: "0 1px 2px rgba(0,0,0,0.04), 0 8px 24px -8px rgba(0,0,0,0.35)", cardHover: "0 1px 2px rgba(0,0,0,0.06), 0 16px 40px -12px rgba(74,226,146,0.25)", glow: "0 0 0 1px rgba(74,226,146,0.4), 0 0 32px rgba(74,226,146,0.25)", + // Multi-hue glows for the bento-grid stat cards on the landing page. + glowBlue: "0 0 0 1px rgba(109,213,255,0.4), 0 0 32px rgba(109,213,255,0.25)", + glowViolet: "0 0 0 1px rgba(196,181,253,0.4), 0 0 32px rgba(196,181,253,0.25)", + glowPink: "0 0 0 1px rgba(249,168,212,0.4), 0 0 32px rgba(249,168,212,0.25)", }, radii: { card: "1.25rem", From ace8598c3155710cd23c43a52cc077dd4fbd2d0e Mon Sep 17 00:00:00 2001 From: abayomicornelius Date: Mon, 7 Sep 2026 18:17:43 +0100 Subject: [PATCH 2/2] feat(home): redesign the landing page MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The dashboard read as a generic dark-mode/single-accent SaaS template — flat cards in a plain row, one gradient. Reworked the visual layer without touching any data-fetching logic or the shared AppShell/Navbar chrome (both are screenshotted by other routes' Playwright visual regression tests, so they're deliberately untouched): - Ambient background: three slow-drifting, blurred gradient orbs in the theme's green/violet/blue accents, plus a faint dot-grid masked to fade out below the hero. Scoped to this page's own stacking context (position: relative + z-index), so it can't bleed into other routes. - Hero heading now spans the full green -> violet -> blue accent gradient instead of a single accent, at a noticeably larger size. The literal text "SmartDrop Dashboard" is unchanged — the 404 page's "back to home" Playwright test asserts on it being visible. - Stat cards moved from four equal-width cards to an asymmetric bento grid: Total Value Locked and Users Online are the featured 2-column cards, Active Pools and Total Users are single cards, each with its own accent hue, its own glow-on-hover shadow, and a small inline SVG icon (no new icon-package dependency — four glyphs, hand-drawn). - The credits panel gets a soft radial accent glow and a two-tone gradient on the credit total instead of a flat accent color. Data bindings (usePlatformStats, useTotalUserCredits, useStellarWallet, the toast error handling) are untouched. --- src/app/page.tsx | 540 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 400 insertions(+), 140 deletions(-) diff --git a/src/app/page.tsx b/src/app/page.tsx index 3c35f81..59d03dd 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -6,6 +6,8 @@ import { Text, Spinner, Box, + Grid, + GridItem, Skeleton, useToast, Alert, @@ -31,58 +33,260 @@ const fadeInUp = { }), }; +// ── Ambient background ─────────────────────────────────────────────────────── +// A layer of slow-drifting, multi-hue gradient blobs plus a faint dot grid, +// scoped to this page's own stacking context so it never touches the shared +// AppShell chrome (nav/footer) that other routes' visual-regression +// screenshots depend on. + +function GradientOrb({ + color, + size, + top, + left, + right, + bottom, + driftX = 24, + driftY = 18, + duration = 18, + delay = 0, +}: { + color: string; + size: string; + top?: string; + left?: string; + right?: string; + bottom?: string; + driftX?: number; + driftY?: number; + duration?: number; + delay?: number; +}) { + return ( + + ); +} + +function AmbientBackground() { + return ( + + + + + + + ); +} + +// ── Icons ──────────────────────────────────────────────────────────────────── +// Small inline line icons — no new icon-package dependency for four glyphs. + +function IconVault(props: { color: string }) { + return ( + + + + + + + ); +} + +function IconLayers(props: { color: string }) { + return ( + + + + + + ); +} + +function IconUsers(props: { color: string }) { + return ( + + + + + + + ); +} + +function IconPulse(props: { color: string }) { + return ( + + + + ); +} + function StatCard({ label, value, accent = "app.accent", + glow = "glow", + icon, delay = 0, isLoading = false, + span, + featured = false, }: { label: string; value: string | number; accent?: string; + glow?: string; + icon: (props: { color: string }) => React.ReactElement; delay?: number; isLoading?: boolean; + span?: { base: number; lg: number }; + featured?: boolean; }) { + const Icon = icon; return ( - - - - {label} - - - - {isLoading ? "—" : value} - - - + + + + {featured && ( + + )} + + + {label} + + + + + + + + {isLoading ? "—" : value} + + + + ); } @@ -137,117 +341,173 @@ export default function Home() { value || value === 0 ? value.toLocaleString() : fallback; return ( - - - + + + + + + + Live on {stellarNetwork} + + + + SmartDrop Dashboard + + + Live Soroban RPC data with contract-driven TVL, pool counts, and user + metrics. + + + RPC: {sorobanRpcUrl.replace(/^https?:\/\//, "")} + {publicKey ? ` · Wallet ${publicKey.slice(0, 6)}…` : ""} + + + + + + + + + + + - - Live on {stellarNetwork} + + Your credits + + + Credits are calculated from your on-chain positions across all pools. - - - SmartDrop Dashboard - - - Live Soroban RPC data with contract-driven TVL, pool counts, and user - metrics. - - - RPC: {sorobanRpcUrl.replace(/^https?:\/\//, "")} - {publicKey ? ` · Wallet ${publicKey.slice(0, 6)}…` : ""} - - - - - - - - - - - - Your credits - - - Credits are calculated from your on-chain positions across all pools. - - - {isConnected ? ( - creditsLoading ? ( - + {isConnected ? ( + creditsLoading ? ( + + ) : ( + + {totalCredits ?? "0"} Credits + + ) ) : ( - - {totalCredits ?? "0"} Credits - - ) - ) : ( - - Connect your Freighter wallet to fetch your user credits and positions. - - )} - - - + + Connect your Freighter wallet to fetch your user credits and positions. + + )} + + + + ); }