From a0da0712c73b16f127a4fad44bb223d46084a15d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=94=D0=B5=D0=BD=D0=B8=D1=81=20=D0=97=D0=B5=D1=84=D0=B8?= =?UTF-8?q?=D1=80=D0=BE=D0=B2?= Date: Sat, 11 Jul 2026 23:41:04 +0400 Subject: [PATCH] feat: cyberpunk HUD charts + drop "test" from faucet copy - SlippageCurve: segmented depth-charge meter with a volt redline at the 2% slippage limit, replacing the flat bar. - DepthHistory: area trace with survey grid, peak marker and a pulsing live 'now' node. - HealthRadial: ticked radial dial with reticle crosshairs instead of the plain arc. - Faucet/action copy: "Get test hUSD" -> "Get hUSD", "Get test {SYM}" -> "Get {SYM}", "test hUSD minted" -> "hUSD minted". Co-Authored-By: Claude Opus 4.8 --- apps/web/src/components/DepositPanel.tsx | 4 +- apps/web/src/components/DepthHistory.tsx | 77 +++++++++++-------- apps/web/src/components/HealthRadial.tsx | 93 ++++++++++++++--------- apps/web/src/components/SlippageCurve.tsx | 74 +++++++++++++++--- apps/web/src/screens/AppBoard.tsx | 4 +- 5 files changed, 167 insertions(+), 85 deletions(-) diff --git a/apps/web/src/components/DepositPanel.tsx b/apps/web/src/components/DepositPanel.tsx index d7ad74d..7854c8f 100644 --- a/apps/web/src/components/DepositPanel.tsx +++ b/apps/web/src/components/DepositPanel.tsx @@ -196,9 +196,9 @@ export function DepositPanel({ ? `Enter ${symbol} amount` : "Enter amount" : needsUsdFaucet - ? "Get test hUSD" + ? "Get hUSD" : needsStockFaucet - ? `Get test ${symbol}` + ? `Get ${symbol}` : needsUsdApprove ? "Approve hUSD" : needsStockApprove diff --git a/apps/web/src/components/DepthHistory.tsx b/apps/web/src/components/DepthHistory.tsx index e77c0cc..d90b279 100644 --- a/apps/web/src/components/DepthHistory.tsx +++ b/apps/web/src/components/DepthHistory.tsx @@ -1,11 +1,14 @@ /** - * 30-day depth sparkline. Historical points are estimated: a deterministic, + * 30-day depth trace. Historical points are estimated: a deterministic, * per-market random walk that converges to the current live depth figure, so - * the line is stable across renders and always ends at truth. + * the line is stable across renders and always ends at truth. Rendered as a + * cyberpunk area trace with grid, glow and hi/now field markers. */ -const W = 220; -const H = 48; +const W = 240; +const H = 58; const DAYS = 30; +const TOP = 7; +const BOT = H - 8; function seeded(i: number, salt: number) { const x = Math.sin(i * 91.7 + salt * 47.3) * 24634.5453; @@ -34,40 +37,50 @@ export function DepthHistory({ const max = Math.max(...values); const min = Math.min(...values); const span = max - min || 1; - const pts = values - .map((v, i) => { - const x = (i / (DAYS - 1)) * W; - const y = H - 6 - ((v - min) / span) * (H - 12); - return `${x.toFixed(1)},${y.toFixed(1)}`; - }) - .join(" "); + const xAt = (i: number) => (i / (DAYS - 1)) * W; + const yAt = (v: number) => BOT - ((v - min) / span) * (BOT - TOP); + + const pts = values.map((v, i) => `${xAt(i).toFixed(1)},${yAt(v).toFixed(1)}`).join(" "); + const idxMax = values.indexOf(max); + const gid = `dh-${salt}`; return ( - - - - + + + + + + + + {/* survey grid */} + {[0.25, 0.5, 0.75].map((g) => ( + + ))} + {[0.25, 0.5, 0.75].map((g) => ( + + ))} + + + + + {/* peak marker */} + + + {/* baseline */} + + + {/* live 'now' node */} + + + + + ); } diff --git a/apps/web/src/components/HealthRadial.tsx b/apps/web/src/components/HealthRadial.tsx index 01af83f..594d48d 100644 --- a/apps/web/src/components/HealthRadial.tsx +++ b/apps/web/src/components/HealthRadial.tsx @@ -1,51 +1,70 @@ import { healthLabel } from "@/lib/math"; -/** SVG radial gauge for the Market Health Score. */ +const TICKS = 34; // segments around the 270° dial +const START = 135; // degrees, y-down; gap sits at the bottom +const SWEEP = 270; +const CX = 40; +const CY = 40; + +function pt(r: number, deg: number): [number, number] { + const a = (deg * Math.PI) / 180; + return [CX + r * Math.cos(a), CY + r * Math.sin(a)]; +} + +/** Ticked radial dial for the Market Health Score. */ export function HealthRadial({ score }: { score: number }) { const { label, tone } = healthLabel(score); const color = tone === "mint" ? "#c8ff00" : tone === "violet" ? "#8a5cff" : "#ff3b00"; - const r = 34; - const c = 2 * Math.PI * r; - const filled = (score / 100) * c * 0.75; // 270 degree arc + const lit = Math.round((Math.max(0, Math.min(score, 100)) / 100) * TICKS); return (
- - - - - + {/* outer reticle ring */} + + + {/* dial ticks */} + + {Array.from({ length: TICKS }, (_, i) => { + const deg = START + (i / (TICKS - 1)) * SWEEP; + const on = i < lit; + const [x1, y1] = pt(24, deg); + const [x2, y2] = pt(on ? 33 : 30, deg); + return ( + + {on && ( + + )} + + ); + })} + + {/* crosshair ticks at 12 / 3 / 9 o'clock */} + {[270, 0, 180].map((deg) => { + const [x1, y1] = pt(15, deg); + const [x2, y2] = pt(18, deg); + return ; + })} + 0 ? Math.min((0.02 / max), 1) * CELLS * STEP : CELLS * STEP; + return ( -
- {SIZES.map((size) => { +
+ {SIZES.map((size, row) => { const s = slippageFor(size, liquidityUsd); - const width = max > 0 ? (s / max) * 100 : 0; + const frac = max > 0 ? s / max : 0; const hot = s > 0.02; + const on = Math.max(1, Math.round(frac * CELLS)); + const color = hot ? "#ff3b00" : "#c8ff00"; return ( -
- {fmtUsd(size)} - - - - - +
+ + {fmtUsd(size)} + + + {Array.from({ length: CELLS }, (_, i) => { + const lit = i < on; + return ( + + {lit && ( + + )} + + ); + })} + {limitX < CELLS * STEP && ( + + )} - + {(s * 100).toFixed(2)}%
diff --git a/apps/web/src/screens/AppBoard.tsx b/apps/web/src/screens/AppBoard.tsx index f89bc65..f64ad62 100644 --- a/apps/web/src/screens/AppBoard.tsx +++ b/apps/web/src/screens/AppBoard.tsx @@ -129,7 +129,7 @@ export default function AppBoard() { if (!isConnected) return openConnectModal?.(); if (amount === 0n) return say("enter an amount to deposit"); if (needsFaucet) { - lastAction.current = "test hUSD minted to wallet"; + lastAction.current = "hUSD minted to wallet"; writeContract({ address: deployment.usd, abi: mockERC20Abi, @@ -189,7 +189,7 @@ export default function AppBoard() { : amount === 0n ? "Enter amount" : needsFaucet - ? "Get test hUSD" + ? "Get hUSD" : needsApprove ? "Approve hUSD" : "Deposit hUSD";