UI: fix last-move highlight, localize move history, clamp zoom overscroll #42

Merged
developer merged 2 commits from feature/ui-recent-highlight-fixes into development 2026-06-11 17:32:34 +00:00
Owner

Four independent fixes in the game screen (ui/), reported by the owner.

1 & 3 — Recent-move highlight (event-driven)

The highlight used the last play (skipping passes) and was a $derived tied to placement.pending, so it lit the opponent's old word after our own pass and re-fired when a just-placed tile was recalled.

  • Q1 (agreed): the highlight now tracks the last move overall — a play highlights its tiles; a trailing pass/exchange highlights nothing (our own just-played word stays lit during the opponent's turn).
  • Q2 (agreed): it is event-driven (refreshRecent) — refreshed only on a real game event (open/refresh, opponent move, our own committed move) and dismissed the moment composing starts, so recalling a draft never re-lights it.

2 — Localized move-history labels

Non-play history rows printed the raw English action (exchange, pass). Added move.{pass,exchange,resign,timeout} to both catalogs and routed the label through t(); under a Russian UI the history now reads «Обмен» / «Пас».

4 — Zoomed-board overscroll

The zoomed board is a native overflow:auto scroller; added overscroll-behavior: none so it clamps at the edge instead of rubber-banding into empty space.

Tests

  • lastMoveCells unit coverage (trailing pass/exchange → empty).
  • i18n RU label assertions; the catalog parity test covers the new keys.
  • e2e overscroll-contract check on the zoomed viewport (chromium + webkit).

Verified locally: pnpm check (0/0), test:unit (148), build, test:e2e (86, both engines), plus a manual mock-mode pass via Playwright MCP covering all six scenarios (highlight on open, place→recall no re-fire, exchange→no stale highlight + live opponent re-flash, RU «Обмен» in history).

Four independent fixes in the game screen (`ui/`), reported by the owner. ### 1 & 3 — Recent-move highlight (event-driven) The highlight used the last *play* (skipping passes) and was a `$derived` tied to `placement.pending`, so it lit the opponent's old word after our own pass and re-fired when a just-placed tile was recalled. - **Q1 (agreed):** the highlight now tracks the **last move overall** — a play highlights its tiles; a trailing pass/exchange highlights nothing (our own just-played word stays lit during the opponent's turn). - **Q2 (agreed):** it is **event-driven** (`refreshRecent`) — refreshed only on a real game event (open/refresh, opponent move, our own committed move) and **dismissed the moment composing starts**, so recalling a draft never re-lights it. ### 2 — Localized move-history labels Non-play history rows printed the raw English action (`exchange`, `pass`). Added `move.{pass,exchange,resign,timeout}` to both catalogs and routed the label through `t()`; under a Russian UI the history now reads «Обмен» / «Пас». ### 4 — Zoomed-board overscroll The zoomed board is a native `overflow:auto` scroller; added `overscroll-behavior: none` so it clamps at the edge instead of rubber-banding into empty space. ### Tests - `lastMoveCells` unit coverage (trailing pass/exchange → empty). - i18n RU label assertions; the catalog parity test covers the new keys. - e2e overscroll-contract check on the zoomed viewport (chromium + webkit). Verified locally: `pnpm check` (0/0), `test:unit` (148), `build`, `test:e2e` (86, both engines), plus a manual mock-mode pass via Playwright MCP covering all six scenarios (highlight on open, place→recall no re-fire, exchange→no stale highlight + live opponent re-flash, RU «Обмен» in history).
developer added 1 commit 2026-06-11 16:50:48 +00:00
UI: fix last-move highlight, localize move history, clamp zoom overscroll
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Has been skipped
CI / integration (pull_request) Has been skipped
CI / ui (pull_request) Successful in 41s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 57s
ac29dca865
- Highlight tracks the last move overall (not the last word): a trailing
  pass/exchange now highlights nothing, so the board no longer lights up the
  opponent's old word after our own empty move.
- Make the highlight event-driven: refreshed only on a real game event
  (open/refresh, opponent move, our own committed move) and dismissed the moment
  composing starts, so recalling a just-placed tile never re-triggers it.
- Localize non-play move-history labels via new move.* catalog keys
  (pass/exchange/resign/timeout); the label printed the raw English action.
- Clamp the zoomed board's pan at its edge (overscroll-behavior: none), removing
  the native rubber-band past the content.

Tests: lastMoveCells unit coverage (trailing pass/exchange -> empty), i18n RU
label assertions, an e2e overscroll-contract check on the zoomed viewport.
developer added 1 commit 2026-06-11 17:24:02 +00:00
UI: render non-play history moves as a dim lowercase tag
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Has been skipped
CI / integration (pull_request) Has been skipped
CI / ui (pull_request) Successful in 40s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 58s
b14cc38919
Per owner feedback: pass/exchange/resign/timeout rows in the move history now read
as a dim, parenthesised, lowercase tag — e.g. «(обмен)» — so they stand apart from a
scored word. The move.* catalog values are lowercased (resign RU → «сдаюсь»); the
parentheses and the muted colour (var(--text-muted)) are applied in the view via a
.ha.sys modifier.
owner approved these changes 2026-06-11 17:32:02 +00:00
developer merged commit 4c65923544 into development 2026-06-11 17:32:34 +00:00
developer deleted branch feature/ui-recent-highlight-fixes 2026-06-11 17:32:34 +00:00
Sign in to join this conversation.
No Reviewers
No Label
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: developer/scrabble-game#42