chore(pr): add force-UI evidence assets for #1142 logs UI redesign
Self-contained HTML report + 7 light-theme PNG captures with DOM-overlay
red callouts (#ef4444, 3px, 8px pad). Captured via Playwright MCP against
local 'bun run dev' instance with ?mock=logs deterministic 150-entry
fixture.
Surfaces:
1. Overview - default state, callouts on Live pill + ? button
2. Trace grouping - expanded vs collapsed states
3. Live-tail paused (Resume tail button)
4. Advanced filters expanded
5. Empty state - filtered-to-nothing + active filter chip
6. Keyboard shortcuts dialog
7. Mobile responsive (390x844)
Targeted-mode evidence; the 'before' UI is captured in the parent issue's
contributor screenshot. Asset directory will be renamed from PLACEHOLDER_PR
to actual PR number; HTML and asset URLs use {HEAD_SHA_PLACEHOLDER}
tokens that the maintainer pins after final commit.
Refs #1142, #1138
No files matched your search
@@ -0,0 +1,218 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>Logs UI Redesign - Evidence (#1142, parent #1138)</title>
|
||||
<style>
|
||||
:root {
|
||||
color-scheme: light;
|
||||
--bg: #ffffff;
|
||||
--fg: #18181b;
|
||||
--muted: #71717a;
|
||||
--border: #e4e4e7;
|
||||
--accent: #2563eb;
|
||||
--callout: #ef4444;
|
||||
}
|
||||
* { box-sizing: border-box; }
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
|
||||
background: var(--bg);
|
||||
color: var(--fg);
|
||||
line-height: 1.5;
|
||||
}
|
||||
header.page { max-width: 1180px; margin: 0 auto; padding: 48px 32px 24px; }
|
||||
header.page h1 { font-size: 28px; margin: 0 0 8px; letter-spacing: -0.01em; }
|
||||
header.page p { margin: 4px 0; color: var(--muted); font-size: 14px; }
|
||||
main { max-width: 1180px; margin: 0 auto; padding: 0 32px 64px; }
|
||||
section.surface {
|
||||
margin: 32px 0;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
background: #fafafa;
|
||||
}
|
||||
section.surface > header {
|
||||
display: flex; align-items: center; justify-content: space-between;
|
||||
padding: 16px 20px; border-bottom: 1px solid var(--border); background: #ffffff;
|
||||
}
|
||||
section.surface > header h2 { margin: 0; font-size: 16px; }
|
||||
section.surface > header .meta { font-size: 12px; color: var(--muted); }
|
||||
.body { padding: 20px; background: #ffffff; }
|
||||
figure { margin: 0; }
|
||||
figure img { width: 100%; height: auto; display: block; border-radius: 8px; border: 1px solid var(--border); }
|
||||
figure figcaption { font-size: 13px; color: var(--muted); margin-top: 10px; }
|
||||
.pair { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
|
||||
.mobile-row { display: grid; grid-template-columns: 1fr 380px; gap: 24px; align-items: start; }
|
||||
ul.checklist { margin: 16px 0; padding-left: 20px; font-size: 14px; }
|
||||
ul.checklist li { margin: 6px 0; }
|
||||
code { background: #f4f4f5; padding: 1px 6px; border-radius: 4px; font-size: 90%; }
|
||||
.badge {
|
||||
display: inline-block; padding: 2px 8px; border-radius: 999px;
|
||||
background: #f4f4f5; color: #52525b; font-size: 11px;
|
||||
font-weight: 600; text-transform: uppercase; letter-spacing: 0.04em;
|
||||
}
|
||||
.legend { background: #fffbeb; border: 1px solid #fde68a; padding: 12px 16px; border-radius: 8px; font-size: 13px; color: #713f12; margin: 12px 0 0; }
|
||||
hr { border: 0; border-top: 1px solid var(--border); margin: 32px 0; }
|
||||
.meta-list { list-style: none; padding: 0; margin: 0; font-size: 13px; color: var(--muted); }
|
||||
.meta-list li { margin: 4px 0; }
|
||||
@media (max-width: 900px) {
|
||||
.pair, .mobile-row { grid-template-columns: 1fr; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header class="page">
|
||||
<span class="badge">Force-UI evidence . light theme . targeted mode</span>
|
||||
<h1>Dashboard logs page redesign</h1>
|
||||
<p>Sub-issue <a href="https://github.com/kaitranntt/ccs/issues/1142">#1142</a> .
|
||||
parent <a href="https://github.com/kaitranntt/ccs/issues/1138">#1138</a> .
|
||||
sibling backend <a href="https://github.com/kaitranntt/ccs/issues/1141">#1141</a></p>
|
||||
<p>Branch <code>kai/feat/1138-logs-ui-redesign</code> .
|
||||
target <code>kai/feat/1138-logging-revamp</code> (integration) .
|
||||
captures via <code>?mock=logs</code> against local dashboard at 1440x900 (mobile at 390x844)</p>
|
||||
<p class="legend">
|
||||
Targeted mode chosen: original "before" UI is captured in
|
||||
<a href="https://github.com/kaitranntt/ccs/issues/1138#issuecomment-4351038690">issue #1138 comment</a>
|
||||
(contributor screenshot labeled "looks terrible"). This evidence shows the redesigned
|
||||
state with red callout boxes annotating new behaviors.
|
||||
</p>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
<section class="surface">
|
||||
<header>
|
||||
<h2>What changed</h2>
|
||||
<span class="meta">redesign-existing-projects . web-design-guidelines</span>
|
||||
</header>
|
||||
<div class="body">
|
||||
<ul class="checklist">
|
||||
<li>Removed ornamental glow / radial gradients / faux-HUD copy from <code>logs.tsx</code> and <code>components/logs/*</code>.</li>
|
||||
<li>Calm 3-pane shell on desktop, stacked + bottom-sheet on mobile.</li>
|
||||
<li>List virtualized via <code>react-virtuoso</code>; trace-grouped rows by <code>requestId</code>.</li>
|
||||
<li>Filters split into primary (search/level/source) + advanced (module/stage/requestId/time window).</li>
|
||||
<li>Live-tail pause/resume with rotation-safe id-set diff for new-entries pill.</li>
|
||||
<li>Detail panel: Overview / Context / Raw tabs; copy JSON, copy requestId, "Show trace" jump.</li>
|
||||
<li>Designed states: empty (selection / no data / no results / out-of-scope) and error w/ retry.</li>
|
||||
<li>Keyboard: <code>j</code>/<code>k</code> . <code>Enter</code> . <code>Esc</code> . <code>/</code> . <code>Space</code> . <code>?</code> + visible <code>?</code> button in header.</li>
|
||||
<li>Reduced-motion respected; AA contrast tokens; visible focus rings.</li>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="surface">
|
||||
<header>
|
||||
<h2>1. Overview - default state</h2>
|
||||
<span class="meta">1440x900 . light . callouts on Live pill (1) and ? button (2)</span>
|
||||
</header>
|
||||
<div class="body">
|
||||
<figure>
|
||||
<img src="screenshots/01-overview.png" alt="Logs page default state" />
|
||||
<figcaption>List + filters + detail panel populated. <strong>(1)</strong> connection status pill ("Live"). <strong>(2)</strong> new <code>?</code> button surfaces keyboard shortcuts dialog.</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="surface">
|
||||
<header>
|
||||
<h2>2. Trace grouping</h2>
|
||||
<span class="meta">collapse-by-requestId . expanded vs collapsed states</span>
|
||||
</header>
|
||||
<div class="body">
|
||||
<figure>
|
||||
<img src="screenshots/02-trace-grouping.png" alt="Trace grouping with expanded and collapsed states" />
|
||||
<figcaption><strong>(1)</strong> expanded trace shows 5 indented stage rows (intake / auth / route / handler / provider) under the parent row, all sharing <code>req_0001</code>. <strong>(2)</strong> collapsed trace badge ("trace . 6 stages") with chevron - one click toggles.</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="surface">
|
||||
<header>
|
||||
<h2>3. Live-tail paused</h2>
|
||||
<span class="meta">pause/resume affordance</span>
|
||||
</header>
|
||||
<div class="body">
|
||||
<figure>
|
||||
<img src="screenshots/03-live-tail-paused.png" alt="Live tail paused state" />
|
||||
<figcaption><strong>(1)</strong> sticky header swaps to "Resume tail" with play icon when paused (was "Pause tail" with pause icon). <strong>(2)</strong> connection pill stays "Live" - polling continues to count new entries; UI just stops auto-scrolling.</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="surface">
|
||||
<header>
|
||||
<h2>4. Advanced filters</h2>
|
||||
<span class="meta">primary + advanced split</span>
|
||||
</header>
|
||||
<div class="body">
|
||||
<figure>
|
||||
<img src="screenshots/04-advanced-filters.png" alt="Advanced filters expanded" />
|
||||
<figcaption>Advanced filters expand inline below primary filters: <code>module</code> . <code>stage</code> . <code>requestId</code> . <code>time window</code>. Disclosure chevron flips on toggle. All inputs debounced 250ms; in-flight queries cancelled on filter change.</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="surface">
|
||||
<header>
|
||||
<h2>5. Empty state - filtered to nothing</h2>
|
||||
<span class="meta">designed empty + active filter chip</span>
|
||||
</header>
|
||||
<div class="body">
|
||||
<figure>
|
||||
<img src="screenshots/05-empty-state.png" alt="Empty state with active filter chip" />
|
||||
<figcaption>Filter <code>requestId: req_99999</code> matches nothing. Center pane shows centered icon + "No entries match your filters" + actionable copy. Active filter chip <code>requestId: req_99999</code> with x to clear; "Clear all" link below. Right pane shows distinct "No entry selected" empty variant.</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="surface">
|
||||
<header>
|
||||
<h2>6. Keyboard shortcuts dialog</h2>
|
||||
<span class="meta">discoverable via ? button or ? keypress</span>
|
||||
</header>
|
||||
<div class="body">
|
||||
<figure>
|
||||
<img src="screenshots/06-shortcuts-dialog.png" alt="Keyboard shortcuts dialog" />
|
||||
<figcaption><strong>(1)</strong> new <code>?</code> button in header. <strong>(2)</strong> dialog lists all 7 keybindings: <code>j</code>/<code>arrow-down</code> next, <code>k</code>/<code>arrow-up</code> prev, <code>Enter</code> focus detail, <code>Esc</code> close mobile, <code>/</code> search, <code>Space</code> pause/resume, <code>?</code> help. Background shows the upstream-errors view with multiple error traces visible.</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="surface">
|
||||
<header>
|
||||
<h2>7. Mobile - 390x844</h2>
|
||||
<span class="meta">stacked layout, no detail-pane fight</span>
|
||||
</header>
|
||||
<div class="body">
|
||||
<div class="mobile-row">
|
||||
<div></div>
|
||||
<figure>
|
||||
<img src="screenshots/07-mobile.png" alt="Mobile layout 390x844" />
|
||||
<figcaption>Header collapses to icon row (Live pill, Refresh, ?, Settings). Filters stack vertically. Detail panel becomes bottom sheet on row tap (not shown here - empty state at small viewport just shows the list).</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<hr />
|
||||
|
||||
<section class="surface">
|
||||
<header>
|
||||
<h2>Capture metadata</h2>
|
||||
</header>
|
||||
<div class="body">
|
||||
<ul class="meta-list">
|
||||
<li>Theme: light (default per force-UI rule).</li>
|
||||
<li>Backend: mock fixture via <code>?mock=logs</code> URL flag (150-entry deterministic fixture incl. 5 traces of 3-6 stages each).</li>
|
||||
<li>User / dataset / fixture / theme / viewport held constant within each capture.</li>
|
||||
<li>Callouts: DOM overlay injected via Playwright <code>browser_evaluate</code>, red <code>#ef4444</code> 3px solid border, 8px expanded padding (no ImageMagick).</li>
|
||||
<li>Capture tool: Playwright MCP. Annotations baked into the PNG by injecting overlay divs before screenshot.</li>
|
||||
<li>HEAD SHA: <code>{HEAD_SHA_PLACEHOLDER}</code> - orchestrator pins after final commit.</li>
|
||||
<li>PR number: <code>PLACEHOLDER_PR</code> - orchestrator renames asset directory after PR creation.</li>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
|
After Width: | Height: | Size: 189 KiB |
|
After Width: | Height: | Size: 189 KiB |
|
After Width: | Height: | Size: 189 KiB |
|
After Width: | Height: | Size: 198 KiB |
|
After Width: | Height: | Size: 115 KiB |
|
After Width: | Height: | Size: 179 KiB |
|
After Width: | Height: | Size: 67 KiB |