ui: staffing co-pilot UX fixes — new-tab reference nav + discoverable collapsibles
Reconciles month-old working-tree UX work (served per-request, live on the demo since 2026-05-30) into git. Implements UX_FIX_PLAN.md's 5 user complaints: reference pages (Profiler/Architecture/Spec/Onboard/Alerts/Workspaces) open in new tabs; contract-card collapsible shows a persistent chevron + expand/collapse label in both states; proof.html gains a substrate-signals chapter. Not authored this session — captured as-is (working state verified: pages serve 200). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+91
-84
@@ -135,6 +135,26 @@ body{font-family:'Inter',-apple-system,system-ui,'Segoe UI',sans-serif;backgroun
|
||||
.ft{text-align:center;padding:24px;color:#3d444d;font-size:11px;border-top:1px solid #171d27;margin-top:32px}
|
||||
.ft a{color:#545d68;text-decoration:none;transition:color 0.15s}
|
||||
.ft a:hover{color:#e6edf3}
|
||||
/* ── UX pass 2026-05-30: clearer interactive affordances ── */
|
||||
[onclick]{cursor:pointer}
|
||||
[role="button"]{cursor:pointer}
|
||||
.iworker{cursor:pointer}
|
||||
.iworker:hover{background:#1c2333;transform:translateY(-1px);box-shadow:0 2px 8px rgba(0,0,0,.3),0 0 0 1px #30363d;transition:background .15s,transform .15s,box-shadow .15s}
|
||||
.iworker:active{transform:translateY(0);box-shadow:none}
|
||||
details>summary{cursor:pointer}
|
||||
details>summary:hover{color:#e6edf3;background:rgba(58,90,127,.15);border-radius:6px}
|
||||
a:focus-visible,button:focus-visible,summary:focus-visible,[onclick]:focus-visible{outline:2px solid #388bfd;outline-offset:2px;border-radius:4px}
|
||||
/* ③ example-search disclosure (2026-05-30) — collapsed by default, CSS-only hover/focus */
|
||||
.samples-disclosure{font-size:11px}
|
||||
.samples-summary{display:inline-flex;align-items:center;gap:6px;cursor:pointer;color:#8b949e;list-style:none;padding:4px 0;user-select:none}
|
||||
.samples-summary::-webkit-details-marker{display:none}
|
||||
.samples-summary::before{content:'▸';display:inline-block;font-size:10px;transition:transform .15s}
|
||||
.samples-disclosure[open] .samples-summary::before{transform:rotate(90deg)}
|
||||
.samples-summary:hover{color:#e6edf3}
|
||||
.samples-row{display:flex;flex-wrap:wrap;gap:6px;margin-top:8px}
|
||||
.search-chip{font-size:11px;padding:5px 10px;background:#161b22;border:1px solid #30363d;border-radius:14px;color:#8b949e;cursor:pointer;transition:border-color .15s,color .15s,background .15s}
|
||||
.search-chip:hover{border-color:#58a6ff;color:#e6edf3;background:#1c2333}
|
||||
.search-chip:focus-visible{outline:2px solid #388bfd;outline-offset:2px}
|
||||
|
||||
.ld{color:#3d444d;text-align:center;padding:40px;font-size:13px}
|
||||
/* Reused pulse keyframe — shared by status dots in the market-pulse
|
||||
@@ -336,6 +356,18 @@ body{font-family:'Inter',-apple-system,system-ui,'Segoe UI',sans-serif;backgroun
|
||||
line-height: 1;
|
||||
}
|
||||
.contract-card.expanded .card-toggle .chevron { transform: rotate(180deg) }
|
||||
/* Persistent top-of-card expand affordance (2026-05-30 UX) — always
|
||||
visible, button-styled so users immediately see the card expands. */
|
||||
.contract-card .card-top-toggle {
|
||||
display: inline-flex; align-items: center; gap: 6px;
|
||||
padding: 4px 10px; margin-bottom: 10px;
|
||||
font-size: 11px; font-weight: 600; color: #8b949e;
|
||||
background: #161b22; border: 1px solid #30363d; border-radius: 7px;
|
||||
cursor: pointer; user-select: none;
|
||||
transition: background .15s, border-color .15s, color .15s;
|
||||
}
|
||||
.contract-card .card-top-toggle:hover { background: #1c2333; border-color: #58a6ff; color: #e6edf3 }
|
||||
.contract-card .card-top-toggle .chevron { display:inline-block; font-size:12px; line-height:1 }
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.contract-card { transition: none }
|
||||
.contract-card:hover { transform: none }
|
||||
@@ -591,12 +623,12 @@ body{font-family:'Inter',-apple-system,system-ui,'Segoe UI',sans-serif;backgroun
|
||||
<nav>
|
||||
<a href="." class="active">Dashboard</a>
|
||||
<a href="console">Walkthrough</a>
|
||||
<a href="profiler">Profiler</a>
|
||||
<a href="proof">Architecture</a>
|
||||
<a href="spec">Spec</a>
|
||||
<a href="onboard">Onboard</a>
|
||||
<a href="alerts">Alerts</a>
|
||||
<a href="workspaces">Workspaces</a>
|
||||
<a href="profiler" target="_blank" rel="noopener">Profiler ↗</a>
|
||||
<a href="proof" target="_blank" rel="noopener">Architecture ↗</a>
|
||||
<a href="spec" target="_blank" rel="noopener">Spec ↗</a>
|
||||
<a href="onboard" target="_blank" rel="noopener">Onboard ↗</a>
|
||||
<a href="alerts" target="_blank" rel="noopener">Alerts ↗</a>
|
||||
<a href="workspaces" target="_blank" rel="noopener">Workspaces ↗</a>
|
||||
</nav>
|
||||
<div class="rt" id="status">Loading...</div>
|
||||
</div>
|
||||
@@ -711,10 +743,15 @@ body{font-family:'Inter',-apple-system,system-ui,'Segoe UI',sans-serif;backgroun
|
||||
|
||||
<div class="section" id="market-section">
|
||||
<div class="section-header">
|
||||
<span class="section-title">Market Intelligence</span>
|
||||
<span class="section-meta">Public permit data · Updated live</span>
|
||||
<span class="section-title">Market Intelligence — Chicago permit map</span>
|
||||
<span class="section-meta">Where the construction money is · live from data.cityofchicago.org</span>
|
||||
</div>
|
||||
<div id="market"></div>
|
||||
<p style="color:#8b949e;font-size:11px;margin:0 0 10px;line-height:1.5;max-width:680px">
|
||||
The geographic companion to ① Live Market: every active building permit plotted
|
||||
by location, sized by construction value. ① tells you <em>when</em> the shifts are;
|
||||
this tells you <em>where</em> the work is.
|
||||
</p>
|
||||
<div id="market"><div style="color:#8b949e;font-size:11px;padding:8px 0">Loading Chicago permit map…</div></div>
|
||||
</div>
|
||||
|
||||
<!-- ═══ ③ Worker Search — natural-language lookup over the 500K bench ═══ -->
|
||||
@@ -747,12 +784,18 @@ body{font-family:'Inter',-apple-system,system-ui,'Segoe UI',sans-serif;backgroun
|
||||
</div>
|
||||
|
||||
<!-- ═══ ④ System Activity — what the substrate has learned to do ═══ -->
|
||||
<div class="section" id="learning-section">
|
||||
<div class="section-header">
|
||||
<!-- 2026-05-30: demoted to a collapsed-by-default <details> (tier 3). It's
|
||||
capability/reference info, not the day's staffing work, so it no longer
|
||||
competes for attention on every load. Mirrors the ⓪ legacy-bridge pattern:
|
||||
ontoggle flips the ▸/▾ hint. loadLearning() still populates #learning. -->
|
||||
<details class="section" id="learning-section"
|
||||
ontoggle="var s=this.querySelector('.lr-toggle-hint');if(s)s.textContent=this.open?'▾ click to collapse':'▸ click to expand'">
|
||||
<summary style="list-style:none;cursor:pointer;display:flex;align-items:baseline;gap:14px;flex-wrap:wrap;outline:none">
|
||||
<span class="section-title" style="color:#e6edf3;font-size:13px">④ System Activity — what the substrate has learned to do</span>
|
||||
<span class="section-meta">Live capabilities · pulled from each subsystem on load</span>
|
||||
</div>
|
||||
<p style="color:#8b949e;font-size:11px;margin:0 0 12px;line-height:1.5;max-width:780px">
|
||||
<span class="lr-toggle-hint" style="margin-left:auto;font-size:10px;color:#545d68">▸ click to expand</span>
|
||||
</summary>
|
||||
<p style="color:#8b949e;font-size:11px;margin:10px 0 12px;line-height:1.5;max-width:780px">
|
||||
Each tile is a capability the system has acquired and the live metric proving
|
||||
it's running. Operational learning (fills, playbooks, hot-swaps) compounds
|
||||
inside each capability; what changes here is the <em>set of things the
|
||||
@@ -760,25 +803,14 @@ body{font-family:'Inter',-apple-system,system-ui,'Segoe UI',sans-serif;backgroun
|
||||
capability replicates by config, not code.
|
||||
</p>
|
||||
<div id="learning"></div>
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<!-- ═══ ⑤ Substrate signals — compact architecture-health strip (bottom) ═══ -->
|
||||
<div class="section" id="arch-signals-section">
|
||||
<div class="section-header">
|
||||
<span class="section-title" style="color:#e6edf3;font-size:13px">⑤ Substrate Signals — architecture health</span>
|
||||
<span class="section-meta">Live probes of the index, memory, and pathway layers</span>
|
||||
</div>
|
||||
<p style="color:#8b949e;font-size:11px;margin:0 0 10px;line-height:1.5;max-width:680px">
|
||||
These tiles measure the architecture itself, not the staffing workload.
|
||||
Instant-search latency, index shape, playbook-memory depth, pathway-matrix
|
||||
compounding — four probes that answer "is the substrate healthy right now?"
|
||||
</p>
|
||||
<div id="arch-signals" style="display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:10px">
|
||||
<div style="color:#8b949e;font-size:11px;grid-column:1/-1">Probing substrate…</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- ⑤ Substrate Signals (architecture-health probes) moved to the Architecture
|
||||
page (proof.html, Chapter 11) on 2026-05-30 — they measure the substrate,
|
||||
not the staffing workload, so they belong with the architecture story and
|
||||
keep this operator dashboard focused on the day's work. Link in the footer. -->
|
||||
|
||||
<div class="ft" id="footer">Staffing Co-Pilot · Hybrid SQL + Vector Search · loading scale… · <a href="console">Console</a> · <a href="proof">Architecture</a></div>
|
||||
<div class="ft" id="footer">Staffing Co-Pilot · Hybrid SQL + Vector Search · loading scale… · <a href="console">Console</a> · <a href="proof" target="_blank" rel="noopener">Architecture ↗</a></div>
|
||||
</div>
|
||||
|
||||
<!-- ═══ Mobile section-jump dock — visible < 768px only via CSS ═══ -->
|
||||
@@ -792,7 +824,7 @@ body{font-family:'Inter',-apple-system,system-ui,'Segoe UI',sans-serif;backgroun
|
||||
<a href="#live-contracts-section" title="Open contracts + candidates">②<span class="dock-label">Jobs</span></a>
|
||||
<a href="#worker-search-section" title="Search 500K workers">③<span class="dock-label">Search</span></a>
|
||||
<a href="#learning-section" title="What the substrate has learned">④<span class="dock-label">Learn</span></a>
|
||||
<a href="#arch-signals-section" title="Live architecture health">⑤<span class="dock-label">Stack</span></a>
|
||||
<a href="proof" title="Architecture & live substrate signals" target="_blank" rel="noopener">✦<span class="dock-label">Arch</span></a>
|
||||
</nav>
|
||||
<script>
|
||||
var P=location.pathname.indexOf('/lakehouse')>=0?'/lakehouse':'';
|
||||
@@ -826,7 +858,7 @@ function styleSkelStages(){
|
||||
}
|
||||
window.addEventListener('load',function(){
|
||||
styleSkelStages(); startSkelStages();
|
||||
loadSystemSummary();loadLegacyBridge();loadDay();loadStaffingForecast();loadLiveContracts();loadMarket();loadLearning();loadWorkerSearchSamples();loadArchSignals();loadStaffers();
|
||||
loadSystemSummary();loadLegacyBridge();loadDay();loadStaffingForecast();loadLiveContracts();loadMarket();loadLearning();loadWorkerSearchSamples();loadStaffers();
|
||||
});
|
||||
|
||||
// Per-staffer hot-swap dropdown — runs independently of the simulation
|
||||
@@ -989,6 +1021,15 @@ function loadWorkerSearchSamples(){
|
||||
{tag:'Specialist', q:'maintenance tech comfortable with Allen-Bradley PLCs'},
|
||||
{tag:'High-volume', q:'warehouse associates available next week near Indianapolis'}
|
||||
];
|
||||
// 2026-05-30: wrap the 6 example chips in a collapsed disclosure so they
|
||||
// don't consume vertical space on every load. The chip keeps its tag+query
|
||||
// two-span layout and scroll-into-view click; the disclosure just gates them.
|
||||
el.textContent='';
|
||||
var det=document.createElement('details');det.className='samples-disclosure';
|
||||
var sum=document.createElement('summary');sum.className='samples-summary';
|
||||
sum.textContent='Example searches';
|
||||
det.appendChild(sum);
|
||||
var row=document.createElement('div');row.className='samples-row';
|
||||
samples.forEach(function(s){
|
||||
var chip=document.createElement('button');
|
||||
chip.type='button';
|
||||
@@ -1002,8 +1043,10 @@ function loadWorkerSearchSamples(){
|
||||
var input=document.getElementById('sq');
|
||||
if(input){input.value=s.q;doSearch();input.scrollIntoView({behavior:'smooth',block:'center'});}
|
||||
};
|
||||
el.appendChild(chip);
|
||||
row.appendChild(chip);
|
||||
});
|
||||
det.appendChild(row);
|
||||
el.appendChild(det);
|
||||
}
|
||||
|
||||
function loadSystemSummary(){
|
||||
@@ -1023,7 +1066,7 @@ function loadSystemSummary(){
|
||||
foot.appendChild(document.createTextNode('Staffing Co-Pilot · Hybrid SQL + Vector Search · '+totalRows+' rows across '+ds+' datasets · '+chunks+' vector chunks · '));
|
||||
var a1=document.createElement('a');a1.href='console';a1.textContent='Console';foot.appendChild(a1);
|
||||
foot.appendChild(document.createTextNode(' · '));
|
||||
var a2=document.createElement('a');a2.href='proof';a2.textContent='Architecture';foot.appendChild(a2);
|
||||
var a2=document.createElement('a');a2.href='proof';a2.target='_blank';a2.rel='noopener';a2.textContent='Architecture ↗';foot.appendChild(a2);
|
||||
}
|
||||
// Also update the collapsible search box label if not yet populated
|
||||
var sum=document.querySelector('.sa summary');
|
||||
@@ -1033,56 +1076,9 @@ function loadSystemSummary(){
|
||||
}).catch(function(){/* non-fatal */});
|
||||
}
|
||||
|
||||
// ─── Substrate signals: render the 4 architecture-health tiles ───
|
||||
function loadArchSignals(){
|
||||
var el=document.getElementById('arch-signals');
|
||||
api('/intelligence/arch_signals',{}).then(function(s){
|
||||
el.textContent='';
|
||||
function tile(label, big, sub, accent){
|
||||
var t=document.createElement('div');
|
||||
t.style.cssText='background:#0d1117;border:1px solid #171d27;border-radius:10px;padding:14px 16px;border-left:3px solid '+(accent||'#58a6ff');
|
||||
var l=document.createElement('div');l.style.cssText='font-size:10px;text-transform:uppercase;letter-spacing:1px;color:#545d68;margin-bottom:6px';l.textContent=label;
|
||||
var b=document.createElement('div');b.style.cssText='font-size:20px;font-weight:600;color:#e6edf3;line-height:1.1';b.textContent=big;
|
||||
var u=document.createElement('div');u.style.cssText='font-size:10px;color:#8b949e;margin-top:6px;line-height:1.4';u.textContent=sub;
|
||||
t.appendChild(l);t.appendChild(b);t.appendChild(u);
|
||||
return t;
|
||||
}
|
||||
var idx=s.index||{};
|
||||
var pbm=s.playbook_memory||{};
|
||||
var pwm=s.pathway_memory||{};
|
||||
// Tile 1 — instant search (the "we cleverly indexed at ingest" claim)
|
||||
var latencyColor=s.instant_search_probe_ms<100?'#2ea043':s.instant_search_probe_ms<500?'#d29922':'#f85149';
|
||||
el.appendChild(tile(
|
||||
'Instant Search',
|
||||
(s.instant_search_probe_ms||'?')+'ms',
|
||||
'Live /vectors/hybrid probe · 500K-row index · '+(idx.chunk_count||0).toLocaleString()+' chunks',
|
||||
latencyColor
|
||||
));
|
||||
// Tile 2 — index shape (hot-swap claim)
|
||||
el.appendChild(tile(
|
||||
'Index',
|
||||
(idx.dimensions||768)+'d · '+(idx.model||'?'),
|
||||
(idx.source||'?')+' → '+(idx.name||'?')+' · '+(idx.backend||'parquet'),
|
||||
'#58a6ff'
|
||||
));
|
||||
// Tile 3 — self-regulating memory
|
||||
el.appendChild(tile(
|
||||
'Playbook Memory',
|
||||
(pbm.entries||0).toLocaleString()+' entries',
|
||||
pbm.entries>0?'Meta-index active · boosts candidates from past fills':'Empty · POST /vectors/playbook_memory/rebuild to populate',
|
||||
pbm.entries>0?'#2ea043':'#d29922'
|
||||
));
|
||||
// Tile 4 — ADR-021 pathway compounding
|
||||
el.appendChild(tile(
|
||||
'Pathway Matrix',
|
||||
(pwm.total_pathways||0)+' traces',
|
||||
pwm.retired+' retired · '+pwm.total_replays+' replays · ADR-021 compounding',
|
||||
'#58a6ff'
|
||||
));
|
||||
}).catch(function(e){
|
||||
el.textContent='substrate signals unavailable: '+e.message;
|
||||
});
|
||||
}
|
||||
// ⑤ loadArchSignals() was MOVED to proof.html (Architecture, Chapter 11)
|
||||
// on 2026-05-30 — the architecture-health probes live with the rest of the
|
||||
// architecture story now, so the dashboard stays focused on staffing work.
|
||||
|
||||
// ─── Live Market hero: 24/7 shift clock (left) + Chicago permit pulse (right) ──
|
||||
// Combines two previously-separate tiles into one coherent "what's happening in
|
||||
@@ -2534,6 +2530,15 @@ function loadLiveContracts(){
|
||||
right.appendChild(rate);
|
||||
}
|
||||
hdr.appendChild(left);hdr.appendChild(right);card.appendChild(hdr);
|
||||
// Persistent expand affordance at the TOP of the card (2026-05-30
|
||||
// UX). The whole card is already clickable; this makes the toggle
|
||||
// obvious and shows expand state in BOTH collapsed and expanded
|
||||
// form. Text + chevron are flipped by the card click handler below.
|
||||
var topToggle=document.createElement('div');topToggle.className='card-top-toggle';
|
||||
var topChev=document.createElement('span');topChev.className='chevron';topChev.textContent='▸';
|
||||
var topLabel=document.createElement('span');topLabel.textContent='Show details';
|
||||
topToggle.appendChild(topChev);topToggle.appendChild(topLabel);
|
||||
card.appendChild(topToggle);
|
||||
// Architecture pill row — instant-search latency + shift coverage
|
||||
// + pool-size proof that the index actually fired on this call.
|
||||
// This is the "our substrate is better" surface J asked for.
|
||||
@@ -2853,6 +2858,8 @@ function loadLiveContracts(){
|
||||
toggleLabel.textContent=nowExpanded
|
||||
? 'click to collapse'
|
||||
: 'click for full curve, economics, candidates, project index';
|
||||
topLabel.textContent=nowExpanded?'Hide details':'Show details';
|
||||
topChev.textContent=nowExpanded?'▾':'▸';
|
||||
// Auto-open the Project Index ONLY on user-driven expand. This
|
||||
// avoids firing 20+ OSHA scrapes on page load — each open
|
||||
// triggers /intelligence/permit_entities, which live-scrapes
|
||||
|
||||
Reference in New Issue
Block a user