Menus stay on the screen, and the content pickers keep their list while they search (#1029, #1030) #1032

Merged
claude-bot merged 5 commits from fix/1029-menu-stays-on-screen into main 2026-10-02 04:42:58 +00:00
Collaborator

Closes #1029. Closes #1030.

Menus stay on the screen (#1029)

A menu hangs from one edge of the button that opens it. That is right only while the button sits near that edge of the page. On a phone, a wiki article's "See it as…" wraps to the left and its menu ran 30px off the screen.

Menu now measures its open panel before paint and moves it sideways by whatever it is off by (--menu-nudge, applied as translate in Menu.css). The limit is the nearest box around it that clips its contents, and the window in any case. It keeps a 16px gutter from that limit, but never more than its own button keeps. The panel is also never wider than the screen.

Measured in a browser, 390×844 (touch) and 1440×900, every menu the seed reaches:

Menu Before After
Wiki article "See it as…", 390 −30…242 16…288
Post "Moderate this post", 390 −94…178 16…288
Character sheet "Export…", 390 −153…119 16…288
Table, first card's menu, 1440 0…272, cut by the shelf board at 24 40…312, whole
Bell, account, wiki More, session Manage, Add to your calendar, thread More, File in a scene, table Add a card on screen unchanged

The table's "Shelf menu" was measured at 724…996 in the second pass (16px off its button); the last commit puts it back at 740…1012. That commit is covered by a unit test built from the measured rects, not by a third browser pass.

No horizontal page scroll with any menu open (document and .book__scroll scrollWidth = clientWidth at both widths).

Not measured: "Add to a sheet" (the seed has no page that offers it) and the account menu at 390 (there is none; the phone has the Contents drawer).

The content pickers keep their list (#1030)

Level up's feat picker and Start a character's "Choose from the loaded content" read their list straight from useAsync's result, which is undefined while a request is in flight. On every search the list emptied, "Nothing matches" was shown and announced, and every row was unmounted and mounted again. A key pressed on a row in that moment was lost, which is what failed J7 on the keyboard in #1027's run (1790).

Both now keep the last answer until the next arrives, as AddFromContent already does.

Checks

  • Full vitest: 3719 passed, 1 skipped. ESLint: 0 errors.
  • e2e/j7-a-character.spec.js on the keyboard project, three repeats in a local e2e stack: 18 passed, no retries.
  • Screenshots looked at: "See it as…" at 390, Moderate at 390, Export at 390, the table card menu at 1440.
  • Backend suite not run: no backend file is touched.

🤖 Generated with Claude Code

Closes #1029. Closes #1030. ## Menus stay on the screen (#1029) A menu hangs from one edge of the button that opens it. That is right only while the button sits near that edge of the page. On a phone, a wiki article's "See it as…" wraps to the left and its menu ran 30px off the screen. `Menu` now measures its open panel before paint and moves it sideways by whatever it is off by (`--menu-nudge`, applied as `translate` in `Menu.css`). The limit is the nearest box around it that clips its contents, and the window in any case. It keeps a 16px gutter from that limit, but never more than its own button keeps. The panel is also never wider than the screen. Measured in a browser, 390×844 (touch) and 1440×900, every menu the seed reaches: | Menu | Before | After | |---|---|---| | Wiki article "See it as…", 390 | −30…242 | 16…288 | | Post "Moderate this post", 390 | −94…178 | 16…288 | | Character sheet "Export…", 390 | −153…119 | 16…288 | | Table, first card's menu, 1440 | 0…272, cut by the shelf board at 24 | 40…312, whole | | Bell, account, wiki More, session Manage, Add to your calendar, thread More, File in a scene, table Add a card | on screen | unchanged | The table's "Shelf menu" was measured at 724…996 in the second pass (16px off its button); the last commit puts it back at 740…1012. That commit is covered by a unit test built from the measured rects, not by a third browser pass. No horizontal page scroll with any menu open (document and `.book__scroll` scrollWidth = clientWidth at both widths). Not measured: "Add to a sheet" (the seed has no page that offers it) and the account menu at 390 (there is none; the phone has the Contents drawer). ## The content pickers keep their list (#1030) Level up's feat picker and Start a character's "Choose from the loaded content" read their list straight from `useAsync`'s `result`, which is `undefined` while a request is in flight. On every search the list emptied, "Nothing matches" was shown and announced, and every row was unmounted and mounted again. A key pressed on a row in that moment was lost, which is what failed J7 on the keyboard in #1027's run (1790). Both now keep the last answer until the next arrives, as `AddFromContent` already does. ## Checks - Full vitest: 3719 passed, 1 skipped. ESLint: 0 errors. - `e2e/j7-a-character.spec.js` on the keyboard project, three repeats in a local e2e stack: 18 passed, no retries. - Screenshots looked at: "See it as…" at 390, Moderate at 390, Export at 390, the table card menu at 1440. - Backend suite not run: no backend file is touched. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
A menu hangs from one edge of its trigger. A wiki article's "See it as…"
wraps to the left on a phone, and its panel ran 30px off the screen. Menu now
measures the open panel before paint and moves it back inside the page's
gutters (the page's scroller where there is one, the window otherwise), and is
never wider than the screen.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Level up's feat picker and Start a character's ChooseContent read their list
straight from useAsync's result, which is undefined while a request is in
flight: the list emptied on every search, "Nothing matches" was announced
until the answer arrived, and every row was unmounted and remounted, losing a
focused row's key press. It is what failed J7 on the keyboard in #1027's run.
Both now keep the last answer, as AddFromContent does.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The table's shelf board clips its contents, and a card's menu hung from the
first card was cut at the board's left edge. The limit is now the nearest
ancestor that does not show its overflow, and the window in any case.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A menu is not pushed further in than its own trigger sits (#1029)
All checks were successful
CI / Backend lint (ruff) (pull_request) Successful in 44s
CI / Bot/backend version sync (pull_request) Successful in 1m6s
CI / Does this change touch the recording path? (pull_request) Successful in 38s
CI / Synthetic session harness (no GPU, no LLM) (pull_request) Has been skipped
CI / Feedback site tests (pull_request) Successful in 1m8s
CI / Docker image build (pull_request) Successful in 1m8s
CI / Bot tests and audit (pull_request) Successful in 2m34s
CI / Summarisation accuracy eval harness (stub provider) (pull_request) Successful in 2m37s
CI / Frontend (shard 2/2) (pull_request) Successful in 9m52s
CI / Frontend (shard 1/2) (pull_request) Successful in 10m9s
CI / End-to-end journeys (keyboard) (pull_request) Successful in 10m49s
CI / End-to-end journeys (desktop) (pull_request) Successful in 12m35s
CI / End-to-end journeys (phone) (pull_request) Successful in 18m41s
CI / Backend migration, tests, and audit (pull_request) Successful in 25m45s
1512a6ccd9
The gutter kept from the limit is capped at what the trigger itself keeps:
the table's Shelf menu button sits at the board's edge, and its panel was
being moved 16px away from it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Sign in to join this conversation.
No description provided.