Commit Graph
7 Commits
Author SHA1 Message Date
Tam Nhu Tran 40cc62a67f fix(ui): reserve stage column on every row for consistent alignment
PR-Agent flagged that trace child rows rendered an extra stage-hint
cell while the header grid template only had 7 columns. Result: every
expanded child shifted module/message/latency/request rightward, and
the stage chip overlapped its neighbour in the trace timeline.

Add a dedicated 72px "Stage" column to the header grid template and
to every row variant. Standalone leaves and trace heads render an
empty span at the same width; trace children with stage hints render
the chip in that slot. Column edges now match across all row types.

Refs #1138, #1151
2026-04-30 16:09:50 -04:00
Tam Nhu Tran 6f1396cf1e fix(ui): import MouseEvent type explicitly in logs-row
PR-Agent flagged that `React.MouseEvent` referenced an unimported
`React` namespace; in stricter TypeScript builds this would fail
typecheck. Import the type alias from `react` directly.

Refs #1138, #1151
2026-04-30 15:44:36 -04:00
Tam Nhu Tran 39ec84a8a9 fix(ui): only show "Copied" feedback when clipboard write succeeds
PR-Agent re-review flagged that `copyText()` swallowed clipboard
errors but the row's `setJustCopied(true)` always fired regardless,
so users in insecure contexts (or with denied clipboard permission)
saw a fake success indicator while nothing was actually copied.

Make `copyText()` return a boolean and gate the "Copied" UI state
on it. When the clipboard write fails, the button stays in its idle
state and the user can retry rather than being misled.

Refs #1138, #1151
2026-04-30 15:37:50 -04:00
Tam Nhu Tran b7cfbd14e2 fix(ui): make logs row keyboard-accessible without nested interactive markup
PR-Agent flagged that the row's copy-requestId widget was a
`<span role="button" tabIndex={-1}>` nested inside a row `<button>`.
Two issues:
1. Nested interactive elements inside a `<button>` is invalid HTML.
2. `tabIndex={-1}` made the copy widget unreachable via keyboard, so
   the new affordance was effectively mouse-only.

Convert the row's outer element from `<button>` to `<div role="row"
tabIndex={0}>` with `onKeyDown` for Enter/Space → select. Now the row
itself is keyboard-focusable and the copy widget can be a real
`<button>` with focus-visible styling — keyboard users can Tab to it
and Enter to copy the requestId.

Refs #1138, #1151
2026-04-30 15:26:29 -04:00
Tam Nhu Tran 0dfb7b8583 fix(ui): reserve leading chevron column so trace and leaf rows align
Trace rows pushed the TIME column ~30px right because the expand chevron
was an inline flex child while leaf rows had nothing in that position.
Result: every column drifted right whenever a trace row was visible.

Reserve a 16px slot at the start of every row (header + leaf + trace).
Leaf rows render an empty span; trace rows render the chevron centered
inside the slot. All columns now share the same x-coordinates regardless
of row type.

Refs #1138
2026-04-30 14:56:32 -04:00
Tam Nhu Tran d5b14bec1c fix(ui): align logs row and detail panel via shared accessors
Both surfaces now consume `getDisplayModule / getDisplayStage /
getDisplayRequestId / getDisplayLatency` from `utils.ts`, replacing the
previous divergence where the list row fell back to `source` while the
detail panel showed em-dash placeholders for the same entry.

Also widens the request-id column in the row table from 88px to 112px
and adds a hover-revealed clipboard icon for one-click copy of the full
requestId. List header bumped to 12px sans-serif uppercase + 9h height
for legibility.

Refs #1138, #1141, #1142
2026-04-30 13:37:02 -04:00
Tam Nhu Tran ae3240d4c8 feat(ui): redesign dashboard logs page with virtualized 3-pane shell
Replace the ornamental logs page (radial-gradient overlays, faux-HUD
captions, scale-on-click animations, two competing tab shells, zero
virtualization) with a calm, accessible, performant surface.

- Calm 48px header + tabs + 3-pane shell (filters | list | detail)
- List virtualized via react-virtuoso; trace-grouped rows by requestId
  with expandable per-stage timeline and per-stage latencyMs
- Filters split into primary (search / level / source) + advanced
  (module / stage / requestId / time-window) with 250ms debounce and
  in-flight react-query cancellation on filter change
- Live-tail pause / resume with rotation-safe id-set diff for the
  new-entries pill; visibility-aware polling
- Detail panel: Overview / Context / Raw tabs; Copy JSON, Copy requestId,
  Show-trace jump; redaction-aware rendering
- Designed empty / loading / error states (4 empty variants, retry on error)
- Keyboard nav (j / k / Enter / Esc / / / Space / ?) with visible focus
  rings; reduced-motion respected; AA-tuned level palette
- New header button for keyboard-shortcuts discoverability (alongside ?
  keypress) -- pairs with the shortcuts dialog
- Optional fields added to LogsEntry to consume the #1141 contract; UI
  ships against fixture (?mock=logs URL flag) so backend isn't a hard
  prerequisite. Dev-only assertLogsEntryShape warns once on drift
- Deleted dead logs-overview-cards.tsx (was unmounted)

Closes #1142
Refs #1138, #1141
2026-04-30 13:03:47 -04:00