feat(web-ui): improve Agents page legibility and scannability

Targeted UI/UX polish on the Agents page, keeping the existing dark
aesthetic and both Overview/Live view modes:

- Add a readable --text-mute token (dark + light) and apply it to the
  summary chips, lane meta, and idle/offline status, which previously
  used the near-invisible --text-dim.
- Event feed: demote the generic "Span Started/Completed" label to a
  quiet mono category tag and promote the tool name, with a left-edge
  accent by event kind (run/span/error/session). Scoped to
  #agents-content so other pages' feeds are unaffected.
- Active-op pills: add a per-kind left accent bar (tool/subagent/run).
- Lane sparkline: raise opacity and add a gradient so it actually reads.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
William Valentin
2026-06-27 10:35:33 -07:00
parent 478c7529a7
commit 69eb87ebc9
2 changed files with 52 additions and 9 deletions
+12 -3
View File
@@ -46,6 +46,14 @@ let _agentsRenderTimer = null;
// ── Private helpers ──────────────────────────────────────
function eventKindClass(eventType) {
if (eventType === 'run.start' || eventType === 'run.end') return 'evt-run';
if (eventType === 'span.start' || eventType === 'span.end') return 'evt-span';
if (eventType === 'error') return 'evt-error';
if (eventType === 'session.start' || eventType === 'session.end') return 'evt-session';
return 'evt-other';
}
function ensureAgentBucket(evt) {
const identity = getAgentIdentity(evt);
if (!identity.key) return null;
@@ -258,7 +266,8 @@ function renderAgentLanes() {
const opsHTML = ops.length > 0 ? `<div class="active-ops">${ops.map(op => {
const elapsed = Math.floor((Date.now() - op.startedAt) / 1000);
const stale = elapsed > 300;
const kindClass = op.kind === 'agent' || op.subType === 'subagent' ? ' subagent' : '';
const kindClass = op.kind === 'agent' || op.subType === 'subagent' ? ' subagent'
: op.kind === 'run' ? ' run' : '';
return `
<div class="active-op${stale ? ' stale' : ''}${kindClass}">
<span class="active-op-dot"></span>
@@ -276,7 +285,7 @@ function renderAgentLanes() {
const expandHTML = details ? '<button class="timeline-expand-hint" type="button">details</button>' : '';
return `
<div class="timeline-event">
<div class="timeline-event ${eventKindClass(eventType)}">
<div class="timeline-event-header">
${getEventIcon(eventType)}
<span class="timeline-event-type">${escapeHTML(getEventLabel(eventType))}</span>
@@ -675,7 +684,7 @@ function renderAgentsLive() {
</div>
<div class="live-run-events">
${group.events.map(evt => `
<div class="timeline-event live-event">
<div class="timeline-event live-event ${eventKindClass(getEnvelopeType(evt))}">
<div class="timeline-event-header">
${getEventIcon(getEnvelopeType(evt))}
<span class="timeline-event-type">${escapeHTML(getEventLabel(getEnvelopeType(evt)))}</span>
+40 -6
View File
@@ -12,6 +12,7 @@
--text: #b8c5d4;
--text-dim: #465a6e;
--text-mute: #6b7f94;
--text-bright: #e4edf5;
--accent: #22d3ee;
@@ -2147,6 +2148,7 @@ tr.expandable:hover .expand-icon::before {
--text: #3d4a5c;
--text-dim: #8b9ab0;
--text-mute: #5c6b80;
--text-bright: #1a2332;
--accent: #0891b2;
@@ -2270,7 +2272,8 @@ tr.expandable:hover .expand-icon::before {
padding: 0.6rem 1rem;
font-family: var(--font-mono);
font-size: 0.78rem;
color: var(--text-dim);
color: var(--text-mute);
letter-spacing: 0.02em;
display: flex;
align-items: center;
gap: 0.5rem;
@@ -2333,7 +2336,7 @@ tr.expandable:hover .expand-icon::before {
margin-top: 0.2rem;
font-family: var(--font-mono);
font-size: 0.68rem;
color: var(--text-dim);
color: var(--text-mute);
}
/* ── Agent Lane Sparklines ────────────────────────────────── */
@@ -2347,10 +2350,10 @@ tr.expandable:hover .expand-icon::before {
.agent-lane-sparkline-bar {
flex: 1;
background: var(--accent);
background: linear-gradient(to top, var(--accent), var(--accent-glow));
border-radius: 1px 1px 0 0;
opacity: 0.5;
min-height: 1px;
opacity: 0.8;
min-height: 2px;
}
.agent-lane-dot {
@@ -2374,7 +2377,7 @@ tr.expandable:hover .expand-icon::before {
.agent-lane-status {
font-size: 0.7rem;
font-weight: 600;
color: var(--text-dim);
color: var(--text-mute);
text-transform: uppercase;
letter-spacing: 0.06em;
}
@@ -2399,6 +2402,7 @@ tr.expandable:hover .expand-icon::before {
padding: 0.35rem 0.625rem;
background: var(--accent-dim);
border: 1px solid rgba(34, 211, 238, 0.15);
border-left: 2px solid var(--accent);
border-radius: var(--radius);
font-size: 0.75rem;
animation: fadeUp 0.2s ease both;
@@ -2406,11 +2410,17 @@ tr.expandable:hover .expand-icon::before {
[data-theme="light"] .active-op {
border-color: rgba(8, 145, 178, 0.2);
border-left-color: var(--accent);
}
.active-op.run {
border-left-color: var(--accent);
}
.active-op.subagent {
background: rgba(167, 139, 250, 0.12);
border-color: rgba(167, 139, 250, 0.22);
border-left-color: var(--purple);
}
.active-op.stale {
@@ -2482,6 +2492,7 @@ tr.expandable:hover .expand-icon::before {
border-radius: var(--radius);
margin-bottom: 0.25rem;
border: 1px solid var(--border-soft);
border-left: 2px solid var(--border);
background: transparent;
font-size: 0.82rem;
}
@@ -2494,6 +2505,29 @@ tr.expandable:hover .expand-icon::before {
font-size: 0.6rem;
}
/* ── Event-kind accents + hierarchy (scoped to Agents page) ── */
#agents-content .timeline-event.evt-run { border-left-color: var(--accent); }
#agents-content .timeline-event.evt-error { border-left-color: var(--error); }
#agents-content .timeline-event.evt-session { border-left-color: var(--success); }
#agents-content .timeline-event.evt-span { border-left-color: rgba(34, 211, 238, 0.4); }
/* Demote the generic type label to a quiet category tag; let the
tool name / preview body carry the line. */
#agents-content .timeline-event-type {
font-family: var(--font-mono);
font-size: 0.62rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.06em;
color: var(--text-mute);
}
#agents-content .timeline-event-body.tool-name,
#agents-content .timeline-event-body.subagent-name {
font-size: 0.82rem;
font-weight: 500;
}
.agent-lane-events .empty-state {
padding: 2rem 1rem;
font-size: 0.78rem;