diff --git a/.agents/evidence/pr/mobile-first-ui/README.md b/.agents/evidence/pr/mobile-first-ui/README.md new file mode 100644 index 00000000..ec019570 --- /dev/null +++ b/.agents/evidence/pr/mobile-first-ui/README.md @@ -0,0 +1,62 @@ +Mobile-first UI evidence captured from a real Claude Code trace. + +Source trace data: + +- Local trace database: `.traces/mobile-first-ui/traces.sqlite3` +- Session id: `600fd026-dbab-4d44-b19f-8df27536398d` +- Session model: `claude-sonnet-4-6` +- Session prompt: `Reply exactly: mobile-layout-real-trace-ok` +- API records: 2 + +Trace capture: + +```bash +CLOUDTAP_DB=.traces/mobile-first-ui/traces.sqlite3 \ + timeout 45s uv run python -m claude_tap \ + --tap-no-live \ + --tap-no-open \ + --tap-no-update-check \ + --tap-output-dir .traces/mobile-first-ui/out \ + -- -p --tools '' --no-session-persistence --max-budget-usd 0.03 \ + 'Reply exactly: mobile-layout-real-trace-ok' +``` + +Local dashboard server: + +```bash +CLOUDTAP_DB=.traces/mobile-first-ui/traces.sqlite3 \ + uv run claude-tap dashboard \ + --tap-output-dir .traces/mobile-first-ui/out \ + --tap-live-port 33117 \ + --tap-no-open +``` + +Screenshots: + +- `dashboard-mobile-list-320.png`: dashboard session cards at 320px. +- `dashboard-mobile-actions-320.png`: dashboard mobile card action row at 320px. +- `dashboard-mobile-list-375.png`: dashboard session cards at 375px. +- `dashboard-tablet-list-768.png`: tablet-width dashboard session cards at 768px. +- `dashboard-desktop-table-1440.png`: desktop dashboard table at 1440px. +- `viewer-mobile-list-320.png`: standalone viewer list state at 320px. +- `viewer-mobile-list-375.png`: standalone viewer list state at 375px. +- `viewer-mobile-detail-320.png`: standalone viewer detail state at 320px. +- `viewer-mobile-detail-375.png`: standalone viewer detail state at 375px. +- `viewer-desktop-detail-1440.png`: standalone viewer detail state at 1440px. + +Capture assertions: + +- `/api/sessions` returned exactly the generated session. +- Every captured viewport reported page-level `overflowX <= 2`. +- Dashboard mobile refresh control renders as an icon with `aria-label="Refresh"`, not a literal `R`. +- Viewer mobile detail action buttons stay inside the action bar, including `Diff with Prev`. +- Viewer mobile detail action bar stays below the sticky detail inspector tabs after scrolling. +- Empty embedded traces keep the sidebar hidden at mobile width. +- Viewer detail evidence keeps long `System Prompt` and `Messages` sections collapsed to avoid exposing local paths or private prompt context in public PR screenshots. + +Manual screenshot review: + +- No mobile screenshot shows clipped primary actions. +- No mobile detail screenshot shows action buttons hidden under the detail inspector tabs. +- No screenshot shows synthetic or mock trace data. +- No screenshot exposes secrets, tokens, local email addresses, or expanded long prompt context. diff --git a/.agents/evidence/pr/mobile-first-ui/dashboard-desktop-table-1440.png b/.agents/evidence/pr/mobile-first-ui/dashboard-desktop-table-1440.png new file mode 100644 index 00000000..b9917b5b Binary files /dev/null and b/.agents/evidence/pr/mobile-first-ui/dashboard-desktop-table-1440.png differ diff --git a/.agents/evidence/pr/mobile-first-ui/dashboard-mobile-actions-320.png b/.agents/evidence/pr/mobile-first-ui/dashboard-mobile-actions-320.png new file mode 100644 index 00000000..487d8eab Binary files /dev/null and b/.agents/evidence/pr/mobile-first-ui/dashboard-mobile-actions-320.png differ diff --git a/.agents/evidence/pr/mobile-first-ui/dashboard-mobile-list-320.png b/.agents/evidence/pr/mobile-first-ui/dashboard-mobile-list-320.png new file mode 100644 index 00000000..d54a10fe Binary files /dev/null and b/.agents/evidence/pr/mobile-first-ui/dashboard-mobile-list-320.png differ diff --git a/.agents/evidence/pr/mobile-first-ui/dashboard-mobile-list-375.png b/.agents/evidence/pr/mobile-first-ui/dashboard-mobile-list-375.png new file mode 100644 index 00000000..76429d74 Binary files /dev/null and b/.agents/evidence/pr/mobile-first-ui/dashboard-mobile-list-375.png differ diff --git a/.agents/evidence/pr/mobile-first-ui/dashboard-tablet-list-768.png b/.agents/evidence/pr/mobile-first-ui/dashboard-tablet-list-768.png new file mode 100644 index 00000000..842ec6df Binary files /dev/null and b/.agents/evidence/pr/mobile-first-ui/dashboard-tablet-list-768.png differ diff --git a/.agents/evidence/pr/mobile-first-ui/viewer-desktop-detail-1440.png b/.agents/evidence/pr/mobile-first-ui/viewer-desktop-detail-1440.png new file mode 100644 index 00000000..81de48db Binary files /dev/null and b/.agents/evidence/pr/mobile-first-ui/viewer-desktop-detail-1440.png differ diff --git a/.agents/evidence/pr/mobile-first-ui/viewer-mobile-detail-320.png b/.agents/evidence/pr/mobile-first-ui/viewer-mobile-detail-320.png new file mode 100644 index 00000000..6b1bcda7 Binary files /dev/null and b/.agents/evidence/pr/mobile-first-ui/viewer-mobile-detail-320.png differ diff --git a/.agents/evidence/pr/mobile-first-ui/viewer-mobile-detail-375.png b/.agents/evidence/pr/mobile-first-ui/viewer-mobile-detail-375.png new file mode 100644 index 00000000..0ca501e5 Binary files /dev/null and b/.agents/evidence/pr/mobile-first-ui/viewer-mobile-detail-375.png differ diff --git a/.agents/evidence/pr/mobile-first-ui/viewer-mobile-list-320.png b/.agents/evidence/pr/mobile-first-ui/viewer-mobile-list-320.png new file mode 100644 index 00000000..49f956e6 Binary files /dev/null and b/.agents/evidence/pr/mobile-first-ui/viewer-mobile-list-320.png differ diff --git a/.agents/evidence/pr/mobile-first-ui/viewer-mobile-list-375.png b/.agents/evidence/pr/mobile-first-ui/viewer-mobile-list-375.png new file mode 100644 index 00000000..6af6f369 Binary files /dev/null and b/.agents/evidence/pr/mobile-first-ui/viewer-mobile-list-375.png differ diff --git a/claude_tap/dashboard.html b/claude_tap/dashboard.html index c021d376..6e4c352c 100644 --- a/claude_tap/dashboard.html +++ b/claude_tap/dashboard.html @@ -74,11 +74,16 @@ } *,*::before,*::after { margin: 0; padding: 0; box-sizing: border-box; } +html { + width: 100%; + overflow-x: clip; +} body { font-family: var(--sans); background: var(--bg); color: var(--text); height: 100vh; + width: 100%; display: flex; flex-direction: column; overflow: hidden; @@ -849,22 +854,374 @@ } @media (max-width: 900px) { - body { overflow: auto; height: auto; min-height: 100vh; } - .header { flex-wrap: wrap; padding: 10px 12px; } - .stats { order: 4; width: 100%; flex-wrap: wrap; margin-left: 0; } - .trace-path-bar { display: none; } - .main { overflow: visible; padding: 12px; } - .dashboard-title-row { flex-wrap: wrap; } - .dashboard-clock { width: 100%; margin-left: 0; } - .control-panel { grid-template-columns: 1fr; } - .overview-card { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 18px; } - .table-scroll { max-height: none; } - .detail-page-head { align-items: flex-start; } - .viewer-frame-wrap { height: 78vh; min-height: 520px; } + body { + height: auto; + min-height: 100dvh; + overflow-y: auto; + overflow-x: clip; + } + .header { + display: grid; + grid-template-columns: minmax(0, 1fr) auto auto; + gap: 8px; + align-items: center; + padding: 8px 10px; + } + .header .logo { + grid-column: 1; + grid-row: 1; + min-width: 0; + } + .header .logo span { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + .header .divider { + display: none; + } + .theme-toggle, + .lang-select { + grid-row: 1; + min-height: 36px; + } + .theme-toggle { + grid-column: 2; + justify-self: end; + justify-content: center; + width: 38px; + min-width: 38px; + padding-inline: 0; + } + .lang-select { + grid-column: 3; + justify-self: end; + min-width: 92px; + max-width: 112px; + } + .path-filter { + grid-column: 1 / -1; + grid-row: 2; + min-width: 0; + max-width: 100%; + overflow-x: auto; + flex-wrap: nowrap; + padding-bottom: 2px; + -webkit-overflow-scrolling: touch; + scrollbar-width: none; + } + .path-filter::-webkit-scrollbar { + display: none; + } + .filter-chip { + flex: 0 0 auto; + min-height: 30px; + } + .stats { + grid-column: 1 / -1; + grid-row: 3; + width: 100%; + margin-left: 0; + gap: 6px; + overflow-x: auto; + flex-wrap: nowrap; + -webkit-overflow-scrolling: touch; + scrollbar-width: none; + } + .stats::-webkit-scrollbar { + display: none; + } + .stats .stat-group, + .live-status { + flex: 0 0 auto; + min-height: 28px; + padding: 4px 8px; + border: 1px solid var(--border); + border-radius: 999px; + background: var(--bg); + } + .trace-path-bar { + display: none; + } + .main { + overflow: visible; + padding: 10px; + } + body.detail-route .main { + padding-top: 10px; + } + .dashboard-title-row { + display: grid; + grid-template-columns: minmax(0, 1fr); + gap: 4px; + margin-bottom: 10px; + } + .dashboard-title { + font-size: 13px; + } + .dashboard-clock { + width: 100%; + margin-left: 0; + font-size: 11px; + letter-spacing: .08em; + } + .control-panel { + grid-template-columns: repeat(2, minmax(0, 1fr)) auto; + gap: 8px; + } + .control-field { + display: grid; + grid-template-columns: minmax(0, 1fr); + gap: 4px; + align-items: start; + } + .control-label { + font-size: 11px; + } + .session-search { + grid-column: 1 / 3; + } + .history-select, + .session-search input { + min-height: 38px; + } + .history-refresh { + grid-column: 3; + min-width: 42px; + min-height: 38px; + padding: 0 10px; + } + .overview-card { + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 8px; + min-height: 0; + padding: 12px; + margin-bottom: 10px; + border-radius: 8px; + } + .metric { + min-width: 0; + } + .metric-label { + font-size: 10px; + letter-spacing: .04em; + } + .metric-value { + margin-top: 6px; + font-size: 18px; + } + .table-panel { + overflow: visible; + border: 0; + background: transparent; + box-shadow: none; + } + .table-scroll { + max-height: none; + overflow: visible; + } + .session-table { + display: block; + min-width: 0; + } + .session-table thead { + display: none; + } + .session-table tbody { + display: grid; + gap: 10px; + } + .session-table tr.session-row { + display: grid; + grid-template-columns: minmax(0, 1fr) auto; + gap: 9px 12px; + min-width: 0; + padding: 12px; + border: 1px solid #cfd8e7; + border-radius: 8px; + background: var(--bg-card); + box-shadow: var(--shadow-sm); + } + [data-theme="dark"] .session-table tr.session-row { + border-color: var(--border); + } + .session-table tr.session-row.active { + box-shadow: inset 3px 0 0 var(--blue), var(--shadow-sm); + } + .session-row.active td:first-child { + box-shadow: none; + } + .session-table td { + min-width: 0; + padding: 0; + border-bottom: 0; + } + .session-table td[data-label]::before { + content: attr(data-label); + display: block; + margin-bottom: 4px; + color: var(--text-tertiary); + font-family: var(--mono); + font-size: 10px; + font-weight: 700; + letter-spacing: .05em; + text-transform: uppercase; + } + .session-start-cell { + grid-column: 1 / 2; + grid-row: 1; + } + .session-status-cell { + grid-column: 2 / 3; + grid-row: 1; + justify-self: end; + } + .session-status-cell::before { + display: none !important; + } + .session-first-cell { + grid-column: 1 / -1; + } + .session-actions-cell { + grid-column: 1 / -1; + } + .first-message { + display: -webkit-box; + max-width: none; + overflow: hidden; + white-space: normal; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + } + .model-pill, + .agent-pill, + .token-pill, + .status-pill { + max-width: 100%; + min-height: 28px; + } + .model-pill { + justify-content: flex-start; + } + .row-actions { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 8px; + width: 100%; + } + .row-action { + min-height: 42px; + width: 100%; + } + .loading-cell, + .table-empty { + display: block; + padding: 22px 12px; + border: 1px solid var(--border); + border-radius: 8px; + background: var(--bg-card); + } + .detail-page-head { + position: sticky; + top: 0; + z-index: 5; + align-items: flex-start; + gap: 8px; + margin: -10px -10px 10px; + padding: 8px 10px; + border-bottom: 1px solid var(--border); + background: color-mix(in srgb, var(--bg) 92%, transparent); + backdrop-filter: blur(8px); + -webkit-backdrop-filter: blur(8px); + } + .back-btn { + min-height: 38px; + flex: 0 0 auto; + } + .detail-subtitle { + white-space: normal; + overflow-wrap: anywhere; + } + .viewer-frame-wrap { + height: calc(100dvh - 112px); + min-height: 460px; + border-radius: 8px; + } + .detail-inspector-bar { + gap: 6px; + padding: 6px; + } + .detail-tabs { + width: 100%; + flex-wrap: nowrap; + overflow-x: auto; + scrollbar-width: none; + } + .detail-tabs::-webkit-scrollbar { + display: none; + } + .detail-tab { + flex: 0 0 auto; + min-height: 36px; + } + .action-bar { + width: 100%; + margin-left: 0; + justify-content: flex-start; + } + .act-btn { + min-height: 36px; + } .action-bar .export-menu-list { left: 0; right: auto; } + .modal-backdrop { + align-items: flex-end; + padding: 10px; + } + .confirm-dialog { + width: 100%; + max-height: calc(100dvh - 20px); + overflow: auto; + padding: 16px; + } + .confirm-actions { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + } + .confirm-btn { + min-height: 42px; + } +} + +@media (max-width: 420px) { + .header { + grid-template-columns: minmax(0, 1fr) 38px 78px; + } + .theme-toggle { + min-width: 38px; + padding-inline: 0; + } + .lang-select { + min-width: 78px; + padding-inline: 6px; + } + .overview-card { + grid-template-columns: repeat(2, minmax(0, 1fr)); + padding: 10px; + } + .metric-value { + font-size: 16px; + } + .session-table tr.session-row { + grid-template-columns: minmax(0, 1fr); + } + .session-status-cell { + grid-column: 1 / -1; + grid-row: auto; + justify-self: start; + } } @@ -919,7 +1276,7 @@