feat: dashboard readability pass — type hierarchy, P&L masthead, trigger-row cleanup
- Two-texture typography: labels move to the UI sans (11px, brighter muted #93a0bd), values stay tabular mono — label/value pairs parse instead of dissolving into uniform mono soup - TOTAL P&L is the one dominant instrument: 34px + green/red state wash and accent bar on the cell (CSS :has on the existing pos/neg classes, no JS) - Equity tile: available funds as a small sub-line (fixes the two-line wrap that broke the strip height) - Armed triggers: single-line ellipsized meta/levels (was a 3-line crumb wrap), 15px symbols, ARMED/WEAK state chips, subtle zebra, thinner bars, wider levels cell so entry/stop/now never clip - Verified with headless before/after renders against live data; zero JS logic changes, node --check clean Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
47a64688d8
commit
da17be8969
1 file changed
+35
-18
+35
-18
@@ -12,8 +12,9 @@
|
||||
--panel-hi: #1c2435;
|
||||
--border: #232c41;
|
||||
--border-soft: #18202f;
|
||||
--text: #e3e8f2;
|
||||
--muted: #7884a2;
|
||||
--text: #e6ebf5;
|
||||
--muted: #93a0bd;
|
||||
--sans: "Inter", "Segoe UI", system-ui, -apple-system, sans-serif;
|
||||
--accent: #5ba3ff;
|
||||
--accent-dim: #2a4a78;
|
||||
--green: #34d17e;
|
||||
@@ -143,8 +144,16 @@
|
||||
transition: background .2s ease;
|
||||
}
|
||||
.pnl-cell:hover { background: rgba(91,163,255,.04); }
|
||||
.pnl-cell .label { font: 600 10px var(--mono); text-transform: uppercase; letter-spacing: .7px; color: var(--muted); }
|
||||
.pnl-cell .value { font: 650 20px var(--mono); margin-top: 3px; letter-spacing: -.3px; font-variant-numeric: tabular-nums; }
|
||||
/* labels in the UI sans, values in mono — two textures so label/value pairs
|
||||
parse at a glance instead of dissolving into one mono soup */
|
||||
.pnl-cell .label { font: 600 11px var(--sans); text-transform: uppercase; letter-spacing: .5px; color: var(--muted); }
|
||||
.pnl-cell .value { font: 650 22px var(--mono); margin-top: 4px; letter-spacing: -.3px; font-variant-numeric: tabular-nums; }
|
||||
/* signature: TOTAL P&L is the one instrument that dominates, and its cell
|
||||
carries a state wash (green/red) readable from across the room */
|
||||
.pnl-cell:first-child .value { font-size: 34px; }
|
||||
.pnl-cell:first-child:has(.value.pos) { background: linear-gradient(180deg, rgba(52,209,126,.10), transparent 75%); box-shadow: inset 3px 0 0 var(--green); }
|
||||
.pnl-cell:first-child:has(.value.neg) { background: linear-gradient(180deg, rgba(255,90,96,.10), transparent 75%); box-shadow: inset 3px 0 0 var(--red); }
|
||||
.funds-avail { display: block; font: 500 11px var(--sans); color: var(--muted); margin-top: 2px; letter-spacing: .2px; }
|
||||
#pnl-total { font-size: 27px; font-weight: 760; }
|
||||
.pos { color: var(--green); text-shadow: 0 0 20px var(--glow-green); }
|
||||
.neg { color: var(--red); text-shadow: 0 0 20px var(--glow-red); }
|
||||
@@ -188,9 +197,9 @@
|
||||
details.panel[open] > summary > h2 { background: linear-gradient(180deg, var(--panel-hi), rgba(22,28,42,.5)); }
|
||||
#panels-toggle { margin-left: 4px; }
|
||||
.count { font: 600 11px var(--mono); background: var(--border); color: var(--text); border-radius: 10px; padding: 1px 8px; }
|
||||
.hint { margin-left: auto; font: 500 10px var(--mono); color: var(--muted); letter-spacing: .3px; text-transform: none; }
|
||||
.hint { margin-left: auto; font: 500 11px var(--sans); color: var(--muted); letter-spacing: .2px; text-transform: none; }
|
||||
table { width: 100%; border-collapse: collapse; }
|
||||
th { text-align: left; font: 600 11px var(--mono); text-transform: uppercase; letter-spacing: .6px; color: var(--muted); padding: 8px 14px; border-bottom: 1px solid var(--border); }
|
||||
th { text-align: left; font: 600 11px var(--sans); text-transform: uppercase; letter-spacing: .5px; color: var(--muted); padding: 8px 14px; border-bottom: 1px solid var(--border); }
|
||||
td { padding: 8px 14px; border-bottom: 1px solid #151a26; font-size: 13px; vertical-align: middle; }
|
||||
tr:last-child td { border-bottom: none; }
|
||||
.num { font-family: var(--mono); }
|
||||
@@ -268,22 +277,29 @@
|
||||
.rdot.warn { color: #f1c40f; text-shadow: 0 0 12px rgba(241,196,15,.45); }
|
||||
.rdot.critical { color: #ff5a60; text-shadow: 0 0 12px rgba(255,77,79,.5); }
|
||||
/* armed-trigger proximity radar */
|
||||
.trig-row { display: flex; align-items: center; gap: 11px; padding: 6px 6px;
|
||||
.trig-row { display: flex; align-items: center; gap: 12px; padding: 9px 8px;
|
||||
border-bottom: 1px solid var(--border); font: 600 12px var(--mono); }
|
||||
.trig-row:last-child { border-bottom: 0; }
|
||||
.trig-sym { width: 62px; font-weight: 700; }
|
||||
.trig-state { width: 52px; font-size: 9px; font-weight: 700; text-transform: uppercase;
|
||||
letter-spacing: .5px; }
|
||||
.trig-meta { width: 96px; color: var(--muted); font: 500 10px var(--mono); }
|
||||
.trig-levels { width: 150px; color: var(--muted); font: 500 10px var(--mono); }
|
||||
.trig-row:nth-child(even) { background: rgba(255,255,255,.016); }
|
||||
.trig-sym { width: 68px; font-weight: 700; font-size: 15px; letter-spacing: .2px; }
|
||||
.trig-state { width: 56px; font-size: 9px; font-weight: 700; text-transform: uppercase;
|
||||
letter-spacing: .5px; text-align: center; padding: 3px 0; border-radius: 4px;
|
||||
background: var(--panel-hi); }
|
||||
.trig-state[data-state="armed"], .trig-state.armed { background: rgba(91,163,255,.16); color: var(--accent); }
|
||||
/* single-line meta with ellipsis — the 3-line "gap 836% 3277.8x tod" crumb wrap
|
||||
was the worst readability offender in the panel */
|
||||
.trig-meta { width: 148px; color: var(--muted); font: 500 11px var(--mono);
|
||||
white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
||||
.trig-levels { width: 218px; color: var(--muted); font: 500 11px var(--mono);
|
||||
white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
||||
.trig-levels b { color: var(--text); font-weight: 700; }
|
||||
.trig-bar { flex: 1; height: 16px; position: relative; background: #0d1117;
|
||||
border: 1px solid var(--border); border-radius: 3px; overflow: hidden; min-width: 120px; }
|
||||
.trig-bar { flex: 1; height: 10px; position: relative; background: #0d1117;
|
||||
border: 1px solid var(--border-soft); border-radius: 5px; overflow: hidden; min-width: 120px; }
|
||||
.trig-fill { position: absolute; left: 0; top: 0; bottom: 0; transition: width .35s ease; }
|
||||
.trig-trigline { position: absolute; top: -1px; bottom: -1px; width: 2px; background: #e6edf3;
|
||||
box-shadow: 0 0 4px rgba(230,237,243,.6); }
|
||||
.trig-dist { width: 70px; text-align: right; font-weight: 700; }
|
||||
.trig-cat { width: 196px; color: var(--accent); font: 500 10px var(--mono); overflow: hidden;
|
||||
.trig-cat { width: 216px; color: var(--accent); font: 500 11px var(--sans); overflow: hidden;
|
||||
text-overflow: ellipsis; white-space: nowrap; }
|
||||
.trig-adv { font: 600 10px var(--mono); color: #c9d3e6; }
|
||||
.trig-cat-raw { color: var(--muted); font: 500 10px var(--mono); }
|
||||
@@ -498,7 +514,7 @@
|
||||
<div class="pnl-cell"><div class="label">Win Rate</div><div class="value num" id="pnl-winrate">—</div></div>
|
||||
<div class="pnl-cell"><div class="label">Avg R</div><div class="value num" id="pnl-avgr">—</div></div>
|
||||
<div class="pnl-cell"><div class="label">Open / Closed</div><div class="value num" id="pnl-counts">—</div></div>
|
||||
<div class="pnl-cell"><div class="label">Equity / Avail</div><div class="value num" id="pnl-funds">—</div></div>
|
||||
<div class="pnl-cell"><div class="label">Equity</div><div class="value num" id="pnl-funds">—</div></div>
|
||||
<div class="pnl-cell pnl-spark"><div class="label">Day Curve</div><div id="equity-spark" class="eqspark">—</div></div>
|
||||
</div>
|
||||
|
||||
@@ -1182,7 +1198,7 @@ function renderTriggers(tw, catMap) {
|
||||
const near = (t.state === 'armed' && dist != null && dist > -1.0) ? ' near' : '';
|
||||
return '<div class="trig-row st-' + esc(t.state) + near + '">'
|
||||
+ '<div class="trig-sym">' + (t.catalyst ? '📰 ' : '') + esc(t.symbol) + '</div>'
|
||||
+ '<div class="trig-state">' + esc(t.state) + '</div>'
|
||||
+ '<div class="trig-state ' + (String(t.state).toLowerCase() === "armed" ? "armed" : "") + '">' + esc(t.state) + '</div>'
|
||||
+ '<div class="trig-meta">' + (t.gap != null ? 'gap ' + t.gap.toFixed(0) + '% ' : '') + (t.rvol != null ? t.rvol.toFixed(1) + 'x' : '') + (t.rvol_tod != null ? ' \u00B7 tod ' + (t.rvol_tod >= 100 ? t.rvol_tod.toFixed(0) : t.rvol_tod.toFixed(1)) + 'x' : '') + '</div>'
|
||||
+ '<div class="trig-levels">entry <b>' + fmt(trig) + '</b> stop <b>' + fmt(stop) + '</b> now ' + fmt(price) + '</div>'
|
||||
+ '<div class="trig-bar" title="' + (price != null ? '$' + price : '?') + ' → trigger $' + (trig != null ? trig : '?') + ' (stop $' + (stop != null ? stop : '?') + ')">'
|
||||
@@ -1456,7 +1472,8 @@ function render(d) {
|
||||
if (acct0.account_id) {
|
||||
const eq = acct0.total_equity != null ? acct0.total_equity : acct0.net_liquidating_value;
|
||||
const avail = acct0.buying_power;
|
||||
$("pnl-funds").textContent = money(eq) + " / " + (avail != null ? money(avail) : "—");
|
||||
$("pnl-funds").innerHTML = money(eq)
|
||||
+ '<span class="funds-avail">avail ' + (avail != null ? money(avail) : "—") + '</span>';
|
||||
} else {
|
||||
$("pnl-funds").textContent = "—";
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user