feat(ui): move in-game status to the board — highlight, score badge, full-width rack
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) Failing after 13s
CI / conformance (pull_request) Successful in 9s
CI / gate (pull_request) Failing after 0s
CI / deploy (pull_request) Has been skipped
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) Failing after 13s
CI / conformance (pull_request) Successful in 9s
CI / gate (pull_request) Failing after 0s
CI / deploy (pull_request) Has been skipped
Remove the under-board status strip and relocate its signals: - bag count -> a badge on the exchange/pass control + the foot of the move table - whose-turn / win-lose -> a thin strip above the score plaques - the tentative-move caption -> the board itself: staged tiles tint green (legal) or pink (illegal), the board tiles a formed word runs through go a shade darker, and an orange score badge sits on the main word (digit sized like a tile value, clamped on-board) The word geometry (covered cells + badge anchor) is a new pure client-side helper (ui/src/lib/formed.ts), independent of the move evaluator, so it works on the local or network preview path alike; the badge's number still comes from the preview score. Rack: a seven-column grid filling the tray width in both layouts — square, full-width tiles — with the confirm control in the fixed 7th slot. Settings: a touch-only "Zoom the board" toggle (default on, device-local) gates the tile-placement auto-zoom; taking a hint while zoomed in now zooms out so the highlighted hint word is never left off-screen. Docs (FUNCTIONAL +_ru, UI_DESIGN, ARCHITECTURE) and e2e/unit tests updated.
This commit is contained in:
+31
-20
@@ -179,16 +179,16 @@ e2e and the screenshots.
|
||||
back near the edges. It **recentres only on a zoom-in** — placing a 2nd+ tile or
|
||||
hovering a dragged tile never jumps the board. On touch the first tile placement auto-zooms
|
||||
in centred on the target, and **holding a dragged tile over a cell ~1 s** auto-zooms there
|
||||
the first time. A **swipe down on the zoom-out board** opens the history, but only when the
|
||||
the first time — both gated by the **Zoom the board** setting (on by default; the toggle is
|
||||
shown only on a touch device). A **swipe down on the zoom-out board** opens the history, but only when the
|
||||
board is scrolled to its top so it never fights the stage's own vertical scroll (the conflict
|
||||
that once retired this gesture) — and it is suppressed on the zoomed board, where the
|
||||
one-finger drag pans (and on desktop / the landscape iframe, where a mouse cannot drag-scroll the
|
||||
viewport natively, a **drag-to-pan** handler moves the zoomed board instead — active only while
|
||||
zoomed, off pending tiles, past a small threshold, swallowing the trailing click). History also
|
||||
opens on a **tap of the score bar** and closes on a tap or
|
||||
an **upward swipe** of the then-inert board (below). A **hint** auto-zooms centred on the
|
||||
hint's placement, not
|
||||
the top-left.
|
||||
an **upward swipe** of the then-inert board (below). Taking a **hint** while zoomed in **zooms
|
||||
out** to the whole board, so the hint's word — highlighted (below) — is never left off-screen.
|
||||
- **Placing & recall** (`Game.svelte`): a rack tile is placed by tap-then-tap or by
|
||||
dragging it onto a cell; while a dragged tile is carried over the board, the aimed-at empty
|
||||
cell is **highlighted as a drop target** (an accent ring). A pending tile is taken back by a
|
||||
@@ -224,7 +224,7 @@ e2e and the screenshots.
|
||||
are pinned to the card's edges.
|
||||
Unread chat is also badged on the score bar itself, so it shows with the history closed.
|
||||
- **Vertical fit & keyboard**: when the game does not fit the viewport, only the
|
||||
board area scrolls vertically (`Screen` `column` mode; the score bar, status, rack and tab
|
||||
board area scrolls vertically (`Screen` `column` mode; the turn strip, score bar, rack and tab
|
||||
bar stay fixed), while zoom keeps its own scroll. The check-word dialog opens in
|
||||
`Modal` keyboard-overlay mode — the small sheet is top-anchored and the soft keyboard
|
||||
overlays the empty area below, so the layout doesn't resize/jank; other modals stay
|
||||
@@ -235,23 +235,31 @@ e2e and the screenshots.
|
||||
(`min(100cqw, 100cqh)`, height-driven in `Board.svelte`'s `.scaler.land`) inside a
|
||||
`container-type: size` pane, shrinking by width when the column is narrow — the board has the
|
||||
**lowest priority**, so the left panel is never squeezed. The **left panel** stacks, top to
|
||||
bottom: the score plaques, the **always-open** history (docked and scrolling with its header
|
||||
sticky — no slide-down drawer, no score-bar toggle), the status line (bag · turn · score
|
||||
preview), the rack (+ the ✅ make control) and, pinned at the bottom, the controls tab bar. Board
|
||||
bottom: the **turn/result strip**, the score plaques, the **always-open** history (docked and
|
||||
scrolling with its header sticky and the **bag count** pinned at its foot — no slide-down drawer,
|
||||
no score-bar toggle), the rack (with the ✅ confirm control in its fixed 7th slot) and, pinned at
|
||||
the bottom, the controls tab bar. Board
|
||||
**zoom works as in portrait** (double-tap / pinch / placement auto-zoom), but the viewport is the
|
||||
full pane: zoom-out shows the height-fitted square centred, and zoom-in magnifies the board past
|
||||
the pane and pans within it, occupying the full width up to the left panel (the focus-centred
|
||||
scroll is set directly, without the portrait width-progress tween). Only the history open/close
|
||||
swipes are dropped (it is always open) and the nav bar does not grow (`growNav` off). The
|
||||
portrait layout is byte-for-byte unchanged; both layouts render from the same snippets, so the
|
||||
behaviour and markup stay single-sourced. The rack tiles size to the (fixed-width) panel rather
|
||||
than the viewport width so seven tiles never overflow the column.
|
||||
- **Highlights**: pending tiles use a slightly darker tile background (no outline). The
|
||||
behaviour and markup stay single-sourced. The rack is a **seven-column grid** filling the tray
|
||||
width in both layouts, so the tiles are square and as large as the row allows (the confirm ✅ takes
|
||||
the fixed 7th slot while a play is staged).
|
||||
- **Highlights**: while composing a play the staged tiles are **tinted by legality** — a light
|
||||
green once they form a word (a shade darker on the committed board tiles the word runs through),
|
||||
a calm pink when they form none — and an **orange score badge** sits on a corner of the main
|
||||
word's tile, its digit sized like a tile's point value (so it scales with the zoom) and clamped
|
||||
to stay on the board. Off-turn or with no preview the staged tiles keep the plain pending fill.
|
||||
The colours are theme tokens in `app.css` (`--tile-pending-legal` / `-illegal`, `--tile-formed`,
|
||||
`--score-badge`); the geometry — which cells a word covers and where the badge anchors — is a
|
||||
pure client-side helper (`lib/formed.ts`), independent of the move evaluator. The
|
||||
last completed word keeps the normal tile background; instead its letters — not the point
|
||||
values — are drawn in the recent-move colour, in both themes. It is static while it is the
|
||||
opponent's turn (our word), and a 1 s flash (the letter pulses between its normal colour
|
||||
and the recent-move colour) when it is our turn (their word). While placing, only the
|
||||
pending tiles are highlighted.
|
||||
and the recent-move colour) when it is our turn (their word).
|
||||
- **Bonus-square labels** — a Settings choice (`boardlabels.ts`): `beginner` shows a
|
||||
split `3×` / `word` (localized слово/буква), `classic` a single `3W` / `3С`, `none`
|
||||
nothing. Default **beginner**.
|
||||
@@ -267,18 +275,21 @@ e2e and the screenshots.
|
||||
otherwise it reverts. Used by the **Hint** tab (the icon morphs to ✅, no label — replacing
|
||||
the old press-and-hold popover) and the in-game **add-friend 🤝** and **block ✖️** card
|
||||
controls. The **Drop game** action keeps its `Modal` confirmation (a destructive, less-frequent action).
|
||||
- **MakeMove / Reset**: when ≥1 tile is pending the rack collapses its used slots
|
||||
and shifts left, a **borderless ✅ icon button** (styled like a tab, not a filled accent
|
||||
button) beside the rack commits the move — no popover, and disabled while the pending word
|
||||
is known illegal; the 🔀 Shuffle tab is replaced by a **↩️ Reset** tab.
|
||||
- **Game tab bar**: 🔄 Exchange/Pass (opens a dialog — pick tiles to **Exchange N**, or pick
|
||||
- **Confirm / Reset**: while ≥1 tile is pending a **borderless ✅ icon button** (styled like a
|
||||
tab, not a filled accent button) takes the rack's **fixed 7th slot** and commits the move — no
|
||||
popover, and disabled while the pending word is known illegal; the 🔀 Shuffle tab is replaced by
|
||||
a **↩️ Reset** tab.
|
||||
- **Game tab bar**: 🔄 Exchange/Pass (a **bag-count badge** on its icon while the bag is non-empty;
|
||||
opens a dialog — pick tiles to **Exchange N**, or pick
|
||||
none to **Pass without exchanging**; pass is always available on your turn, exchange only
|
||||
while the bag still holds a full rack, below which the tiles disable and only the pass
|
||||
remains), 🛟 Hint (with a remaining-count badge, disabled at zero); 🔀 Shuffle (no label,
|
||||
no confirm), which
|
||||
**animates** — tiles hop along a low parabola to their new slots (duration scaled by the
|
||||
distance, the longest ≤ 0.3 s; off under reduce-motion) with a short haptic shake. The
|
||||
under-board slot shows the **Scores: N** preview. The screen **title** is the variant's
|
||||
distance, the longest ≤ 0.3 s; off under reduce-motion) with a short haptic shake. Whose turn it
|
||||
is — or the viewer's result once the game ends — shows in a **thin strip above the score
|
||||
plaques**; the tentative move's score rides the board badge (above), not an under-board caption.
|
||||
The screen **title** is the variant's
|
||||
display name (Scrabble / Скрэббл / Erudite / Эрудит), not a constant "Scrabble".
|
||||
|
||||
## Advertising banner (`components/AdBanner.svelte` in `components/Header.svelte`, `lib/banner.ts` + `lib/bannerEngine.ts`)
|
||||
|
||||
Reference in New Issue
Block a user