Skip to content

Rating question layout and focus, Space on buttons, one unasked prompt at a time - #1936

Merged
BarganConstantin merged 5 commits into
developmentfrom
fix/rating-banner
Oct 4, 2026
Merged

BarganConstantin merged 5 commits into
developmentfrom
fix/rating-banner

Conversation

@BarganConstantin

Copy link
Copy Markdown
Owner

What changes

  • The rating question takes the whole row under the topbar. It used to keep the right rail's width free as padding, from a viewport media query that knew nothing of the detail or accounts panel. With a session selected at 1024px the row was 40px wide and 492px tall, one word to a line, and the board started at y=544. With the accounts panel open as well, the page scrolled sideways and the machine panel covered every number. Now the row spans the window. The left panel and the detail panel start a row lower. The rail is moved down by the row's own height, which the row writes as --rating-h. On a phone the row is two lines: the question with "Not now", then the scale. With a coarse pointer the numbers share that line, between 24px and 32px each. The low-score thanks takes the same shape.
  • Keyboard focus stays on the page when the question goes. A number pressed from the keyboard hands focus to the thanks: its offer for a low score, otherwise its ×. "Not now" and the × hand focus to the canvas. The thanks does not go by itself while focus is in it, or while a dialog is open. So the feedback dialog opened from the offer can still give focus back to the offer: the offer no longer closes the thanks first. The thanks is said through a live region that is always mounted.
  • Space presses the buttons outside the board again. React Flow's pan key defaults to Space. It listens on the whole document and cancels the keydown unless focus is in a text field, so Space pressed none of the topbar toggles, the ⋯ menu, the rating numbers or a dialog's Cancel. The board now takes no pan key. Dragging and scrolling already pan it, and Space on the canvas still pauses.
  • The question waits for the dialogs a panel opens. Its check only covered App's own dialogs, so it turned up behind the CPU and load history, Busiest processes, the network map, a sign-in or a pairing request. It now asks the dialog stack, the same test the canvas's keys use.
  • The pairing request and the re-sign-in prompt come one at a time. Each decided its turn by counting the dialog stack. A dialog joins that stack only after the render that draws it, so when a dialog both were waiting on closed, both came up together, with the re-sign-in prompt on top. They are now decided in one render (UnaskedPrompts), pairing request first.

Verification

  • npm run typecheck: clean.
  • Full suite (--maxWorkers=3 --minWorkers=1): 885 files and 11,573 tests passed, before the rebase. After rebasing onto development, the 33 touched and nearby files (639 tests) pass.
  • Each new test failed before its fix, for the reason it describes:
    • rating-banner-room.test.ts failed on the padding-right: calc(288px + 18px) rule, the missing full-width placement and the missing --rating-h.
    • rating-banner-focus.test.ts: focus was on body after a keyboard pick, after "Not now" and after the ×. The thanks was gone while focus was in it, the offer called closeRating and there was no live region. Its mouse case passes both before and after, as a guard.
    • space-presses-buttons.test.ts: React Flow was given no panActivationKeyCode, so it used its default, Space.
    • rating-waits-for-dialogs.test.ts: the question showed with a stack dialog open.
    • unasked-prompts-one-at-a-time.test.ts: both prompts were drawn at once, [pairing request, re-sign-in].
  • Repointed: lan-pair-request-waits.test.ts now targets usePairRequestDialog, and the promptShows pin in reauth-prompt-1893.test.ts now reads the pairing count.
  • Browser checks on an isolated deck (Playwright, Chromium) in light and dark:
    • Every panel combination: accounts, usage, machine and detail each on and off, at 1440, 1280, 1024, 768, 390 and 360, in both themes. That is 192 layouts, each measuring canvas top, scrollWidth and elementFromPoint on all 12 banner buttons.

      before after
      layouts that scroll sideways 12 (up to 504px past the edge) 0
      layouts with a covered button 62 (680 covered buttons) 0
      row taller than two lines 134 layouts (up to 492px) 0 (41px on one line, 71px on two)
      canvas top 93 to 544 93 (one line) or 123 (two lines)

      For example, 1024 with accounts, usage, machine and detail open went from canvas top 544, scrollWidth 1272/1024 and 12/12 buttons covered by aside.sysdetail to canvas top 93, 1024/1024 and 0/12. The rail follows the row through question, thanks and dismissal. At 390 the usage panel top moves 131 → 131 → 60.

    • Focus:

      • Enter on 3 → focus on "Tell us what would make it better", and the live region says the thanks.
      • The thanks outlives its timer while focused and while the feedback dialog is open.
      • Escape out of feedback → focus back on the offer.
      • × → main#canvas. "Not now" → main#canvas.
      • Enter on 9 → focus on ×. Tab away → the thanks goes by itself.
      • Mouse click → the thanks goes by itself.
    • Space: Space presses a rating number (the keydown is no longer cancelled), the usage toggle, Send feedback, the dialog's close and the ⋯ at 390. Space on the canvas still toggles pause.

    • Gate: with the CPU history chart open at the first look, there is no banner. At the next look after it closes, the banner shows with no buttons covered.

    • Prompts: with /api/lan and /api/claude-accounts faked, closing Feedback shows only "A deck wants to pair". One Escape, then the re-sign-in prompt.

It kept the right rail's width free as padding from a viewport media query that knew nothing of the detail or accounts panel, so with a session selected at 1024px the row was 40px wide and 492px tall, and with the accounts panel open too the page scrolled sideways and the machine panel covered every number. The row now spans the window, the side panels and the rail start under it by the height it reports, and on a phone it is two lines.
A number pressed from the keyboard now hands focus to the thanks, Not now and the × hand it to the canvas, and the thanks no longer goes by itself while focus is in it or while the feedback dialog it offered is open, so that dialog can give focus back. The thanks is said through a live region that is always mounted, rather than by the row turning into one with its words.
React Flow listens for its pan key, Space by default, on the whole document and cancels the keydown wherever focus is unless it is a text field, so Space pressed none of the topbar toggles, the ⋯ menu, the rating numbers or a dialog's Cancel. The board takes no pan key now; dragging and scrolling already pan it.
The question's look checked only App's own dialogs, so it turned up behind the CPU and load history, Busiest processes, the network map, a sign-in or a pairing request, under a scrim where none of it could be pressed. It now asks the dialog stack as the canvas's keys do, and the thanks waits on the same test.
… at a time

Both waited for an open dialog by counting the stack, which a dialog joins only after the render that draws it, so when that dialog closed they came up together, the re-sign-in prompt over the pairing request it should follow. The two are now decided in one render, the pairing request first, and one going up counts against the prompt behind it.
@BarganConstantin
BarganConstantin merged commit 0730f89 into development Oct 4, 2026
10 checks passed
@BarganConstantin BarganConstantin mentioned this pull request Oct 5, 2026
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