Skip to content

fix: code-review batch — sysmon sampler liveness, stale fetch race, a11y names, interaction polish - #17

Merged
Xuepoo merged 10 commits into
mainfrom
carryctx/web-0019-uiux
Aug 23, 2026
Merged

Xuepoo merged 10 commits into
mainfrom
carryctx/web-0019-uiux

Conversation

@Xuepoo

@Xuepoo Xuepoo commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

Implements accepted findings from the WEB-0017 review. Rebased onto main after #16 (the deps commit is intentionally absent here).

Fix Commit
sysmon sampler dies permanently after minimize (P1) e4b0f2a*
sysmon window rows rebuilt every 1s → reconcile by id (see branch)
calculator Ctrl+C clears display
browser stale proxy response overwrites newer page
paint hint clipped at min width; dead branch removed
click-catcher drag latch on pointercancel/leave
unused IconDef.emoji dropped
textual accessible names for glyph buttons (✕ etc.)
clock digital readout clipping at min size
smoke floor aligned to declared 240x220 e90311c

Deferred with notes: notes unsaved-edit confirm (needs dialog pattern, PX-0040), settings active-preset indicator (PX-0040).
(*rebase rewrote SHAs; see branch tip e90311c)

Validation

  • bun run check clean · bun test 38/38 (260 expects) · build verified pre-rebase (361.00 kB / gzip 108.79 kB)
  • Headed-browser spot checks deferred to post-merge verification

CarryCtx: WEB-0019 (findings WEB-0017 PX-0026..0036)

Xuepoo added 10 commits August 23, 2026 23:25
The self-chained 16ms tick returned early when the window was invisible
WITHOUT rescheduling, so one minimized tick killed the sampling chain
permanently — frame-time p50/max froze forever even after restore.

Reschedule before any early return, skip only the push while hidden,
and advance the timestamp every tick so the first sample after restore
measures one interval instead of the whole minimized duration. Also
corrects the comment: the chain is a timer approximation of frame
cadence, not real rAF.
refreshWindows() destroyed and recreated every window-row entity each
1s tick — GC churn, pressed/hover state loss, and a rebuilt a11y
subtree under screen readers. Reconcile against wm.list() keyed by
windowId instead: closed windows drop their rows, survivors are reused
and only relabeled when focus/minimize state changes, and the empty
placeholder is created once.

Also gives the ✕ close button a textual accessible name ("Close
<title>") while keeping the glyph visual.
DesktopClickCatcher set dragging on pointerdown but only cleared it on
pointerup, so a gesture released over another mirror, cancelled by the
browser, or leaving the canvas left dragging/moved latched — later
buttonless pointermove kept drawing marquees. Mirror ThemedButton's
defensive handlers: abandon the drag on pointercancel and pointerleave,
collapsing any latched marquee via a final zero-size rect.
The emoji fallback has been populated for all 10 icons since the SVG
migration but never read anywhere. Remove the field, its factory
parameter, and the 10 literal arguments.
Ctrl+C with the calculator focused cleared the display and
Ctrl+Backspace backspaced: the global keydown handler read every key
as a keypad press. Early-return on ctrlKey/metaKey/altKey, matching
the terminal's guard.
render() awaited the proxy fetch with no generation guard, so Back or
re-navigation during an in-flight fetch let the old response overwrite
the newer page's title/body/status (address bar then disagreed with
the page). Capture the requested URL before the await and bail unless
it is still history[historyIndex] after both the fetch and the JSON
parse — including the network-error path.
The usage hint was anchored at absolute x=364 with clipChildren=true:
fully outside the client area at the declared 360px minimum and its
tail clipped even at the default 600px width. Derive its position from
the actual swatch row and hide it when the window cannot fit it
(IRenderer has no measureText, so the fit budget is ~5.5px per glyph).

Also removes the unreachable currentColor === '' branch that
highlighted the Clear button — the color starts as #000000 and only
changes via swatch clicks, so it is never empty.
ThemedButton now projects an optional a11y name in place of the visual
label (setA11yName + getA11yAttributes override; btn/themedButton take
an optional 4th argument). Decorative emoji stay visible on the canvas
while screen readers hear plain words:

- Files nav buttons: Root / /docs / /notes / Refresh / Seed Samples
- Files entry rows: '<name> (<size> B)' without the kind glyph
- Notes toolbar: Save / Reload / Clear
The dial used the full half-height for its radius, pushing the
toLocaleTimeString readout past the bottom edge at the declared
240x220 minimum. Reserve 24px under the dial when computing the
radius.
The minimum-geometry gate exercised clock at 260x220 while clock.ts
declares minWidth 240 — the test was looser than the contract it
guards.
@Xuepoo
Xuepoo merged commit 0bc7cbd into main Aug 23, 2026
4 checks passed
@Xuepoo
Xuepoo deleted the carryctx/web-0019-uiux branch August 23, 2026 15:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant