UI bugfix round: copy payload, activity time, spanning project line, modal scroll #24
Loading…
Reference in a new issue
No description provided.
Delete branch "oss-oo/observatory-bugfix-round-gfix20260924"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Four narrow-window UI defects reported from the cockpit, fixed and verified per-bug with a CDP-driven fixture harness (headless Chrome, trusted input events, granted clipboard) at 1280/900/400 px.
1. Copy title button copied wrong content (or nothing)
Root cause: the title payload was embedded with
JSON.stringify(...)into a double-quotedonclickattribute. The HTML parser ends the attribute at the first JSON double-quote, so the rendered attribute was literallyonclick="copyText("— the handler never compiled (el.onclick === null) and every click was a no-op. The sessionId copy button escaped differently and happened to work, which produced the inconsistent "sometimes nothing, sometimes something else" behavior.Fix: payloads ride in
data-copy/data-copy-msgattributes (HTML-escaped, decoded by the DOM); one delegated document-level click listener reads the clicked row's dataset — quoting/entities in titles can never break it, and the listener survives the 3 s table re-renders.copyTextgains anexecCommandfallback for unfocused/non-secure contexts and reports failures via toast.Verified: clicking 📋 on five probe rows (quoted title, 152-char title, two similar-prefix titles, running row) puts EXACTLY that row's displayed title on the clipboard; sessionId copy still exact.
2. "Last activity" truncated to "HH:…"
Root cause: the cell rendered the full locale datetime (
9/24/2026, 6:01:23 PM) into a percentage-width column (14% → 43 px at 400 px) with nowrap+ellipsis — clipped to18:….Fix: compact
fmtActivity—now/8m/2h 05mrelative when fresh,Wed 16:10within the week,Aug 10 18:10beyond; the full timestamp moves to the cell tooltip. Column widths now ride on header cells in pixels (the name column takes the leftover) so the time column keeps its width at any window size. The models column slims down: chips abbreviate to the bare model name (GLM-5.3,claude-opus-4-5) with the full id on hover, tighter chip padding, per-chip ellipsis discipline.Verified: no clipped activity cell at 1280/900/400; every entry shows minutes at minimum (relative or HH:MM).
3. Project/worktree line squeezed multi-line
Root cause: the path line lived in a
divinside the first (name) column — at 400 px that column is ~100 px and a 48-char path wrapped to 7 lines.Fix: each session now renders as a two-row group in its own
tbody: the main row plus a second row whose singletd colspan="7"spans the full table width — one clean line down to ~400 px (ellipsis + full path in the tooltip for extreme paths). Group-level hover/cursor, run tint and hidden dimming apply to both rows; every row control keeps working (sort, pager, unhide, show, copy, title link, row click). Below 560 px the models column and the show-button label drop out so the remaining columns stay readable.Verified: spanning cell
colspan=7, single line, width ≈ table width at all three sizes; sort/pager/unhide regression-tested.4. Modal/drawer scroll focus
Root cause: neither dialog took focus on open and the page scroll stayed live — wheel events over non-scrollable dialog parts (header, footer, backdrop) or at the scroll boundary scrolled the dashboard behind.
Fix: dialogs get
tabindex="-1"andfocus({preventScroll:true})on open; scroll bodies getoverscroll-behavior: contain; the page scroll locks (overflow:hidden+ scrollbar-width compensation) while either dialog is open and unlocks when the last one closes.Verified: after opening,
activeElementis inside the dialog; CDP wheel events over the header and at the scroll bottom leavewindow.scrollYat 0 while the dialog body scrolls; lock releases on close (✕/ESC/backdrop).Notes
.models { display:flex }also hit theth.modelsheader cell; a flex box is not a table-cell, so Blink dropped it as the fixed-layout first-row width definer and injected a phantom auto column. The flex layout is now scoped totd.models.docs/screenshot.pngregenerated from the fixture with the new row layout.py_compile+--help,make check-social-preview, Super-Linter slim v8.7.0 (workflow env, exit 0) — plus the 26-check functional harness (evidence in the PR conversation).Four narrow-window defects fixed in dashboard.html: - Copy title: the payload was JSON.stringify'd into a double-quoted onclick attribute, which the HTML parser truncated at the first quote (onclick="copyText(") — the handler never compiled and clicks copied nothing. Payloads now ride in data-copy attributes handled by one delegated listener that survives the 3 s re-renders; copyText gains an execCommand fallback for unfocused/non-secure contexts. - Last activity: full locale datetimes ellipsized to "HH:…" on narrow windows. Now compact and never truncated: relative (now / 8m / 2h 05m) for fresh entries, weekday+HH:MM within the week, date+HH:MM beyond; full timestamp on hover. Column widths moved from percentages to header-cell pixels so the time column keeps its width at any window size; model chips abbreviate to the bare model name (full id on hover) to reclaim width. - Project/worktree line: was squeezed into the name column and wrapped to many lines. Each session now renders as a two-row group whose second row spans the full table width via colspan, one clean line down to ~400 px (ellipsis + tooltip for extreme paths). Below 560 px the models column drops out and the show button becomes an icon so the remaining columns stay readable. - Modal/drawer scroll: focus stayed outside the dialog, so wheel events over non-scrollable dialog parts scrolled the page behind. Dialogs now take focus on open (tabindex="-1" + focus()), their scroll bodies contain overscroll, and the page scroll locks while a dialog is open. README documents the scroll isolation; screenshot regenerated from the fixture with the new row layout.