Stage 7 polish: docs + mark Stage 7 done (Part H)
- new docs/UI_DESIGN.md (design system: shell, nav, tab-bar, tiles, board zoom/labels, HoldConfirm, banner rotator, result iconography) - ARCHITECTURE: app-shell + announcement channel (mock->server) + hint place-on-board / no_hint_available contract + board-style setting - FUNCTIONAL(+ru): hint-on-board, word-check constraints/throttle, board style - PLAN: Stage 7 -> done + polish refinement note; CLAUDE sources list
This commit is contained in:
+14
-1
@@ -38,6 +38,11 @@ Three executables plus per-platform side-services:
|
||||
is a hash router and the session token is held in memory + IndexedDB. A build-flagged
|
||||
in-memory mock transport (`pnpm start`) runs the whole slice with no backend.
|
||||
Embeddable in platform webviews; packageable to native (iOS/Android) via Capacitor.
|
||||
The client uses a mobile-app shell (a growing nav bar; content pinned to the bottom),
|
||||
a one-line **announcement banner** under the nav (a client-side mock rotation today —
|
||||
a server-driven channel later, §10), and a client **board-style** setting (bonus-label
|
||||
mode). The visual/interaction design system is documented in
|
||||
[`UI_DESIGN.md`](UI_DESIGN.md).
|
||||
- **`platform/<name>`** *(planned)* — per-platform side-services (Telegram bot
|
||||
first): deep-link invites and platform-native push notifications. They talk
|
||||
to `backend` over an internal API.
|
||||
@@ -209,7 +214,11 @@ Key points:
|
||||
(`hint_balance`, spent after the allowance; top-ups are a later feature). A hint
|
||||
reveals the top-1 ranked move (`GenerateMoves[0]`). The lobby/tournament caller
|
||||
picks the per-game defaults (e.g. one in casual random games, none in
|
||||
tournaments).
|
||||
tournaments). The client **lays the hinted tiles onto the board** as a pending
|
||||
placement and leaves the commit to the player. When the rack has no legal move the
|
||||
service spends **nothing** and returns `ErrNoHintAvailable` — surfaced as the distinct
|
||||
result code `no_hint_available` (separate from `hint_unavailable`) so the UI can say
|
||||
"no options" rather than "no hints left".
|
||||
- **Word-check tool**: unlimited dictionary lookups against the game's pinned
|
||||
dictionary; each result offers a **complaint** (complainant, game, variant,
|
||||
dict_version, word, the disputed result, an optional note) that lands in an
|
||||
@@ -363,6 +372,10 @@ match-found. Out-of-app platform push (your-turn, nudge) is wired in Stage 9;
|
||||
session-revocation events and cursor-based stream resume are deferred
|
||||
(single-instance MVP).
|
||||
|
||||
A separate **announcements channel** feeds the client's one-line banner (UI_DESIGN.md).
|
||||
It is a client-side **mock** rotation today; a server-driven source (operational notices,
|
||||
promotions) is future work and would deliver short markdown messages (text + links).
|
||||
|
||||
## 11. Observability
|
||||
|
||||
- Structured logging with `go.uber.org/zap` (JSON). OpenTelemetry tracer and
|
||||
|
||||
+4
-1
@@ -17,7 +17,10 @@ the top-1 hint, the unlimited word-check with complaint, per-game chat and nudge
|
||||
real-time in-app updates, switching interface language (en/ru) and theme, and a
|
||||
read-only profile. Managing friends and blocks, creating friend games (invitations),
|
||||
editing the profile, the statistics screen and the history/GCG viewer arrive in
|
||||
Stage 8.
|
||||
Stage 8. Settings also pick the board's bonus-label style (beginner / classic /
|
||||
none). A hint **lays the suggested tiles on the board** for the player to confirm and
|
||||
costs nothing when the rack has no legal move. The word-check accepts only the
|
||||
variant's alphabet, remembers answers within the session and rate-limits repeats.
|
||||
|
||||
### Identity & sessions *(Stage 1 / 6)*
|
||||
A player arrives from a platform (Telegram first), via email login, or as an
|
||||
|
||||
@@ -16,7 +16,11 @@ top-1 подсказку, безлимитную проверку слова с
|
||||
обновления в реальном времени, переключение языка интерфейса (en/ru) и темы и
|
||||
профиль только для чтения. Управление друзьями и блоками, создание дружеских игр
|
||||
(приглашения), редактирование профиля, экран статистики и просмотр истории/GCG
|
||||
появятся в Stage 8.
|
||||
появятся в Stage 8. В настройках также выбирается стиль подписей бонус-клеток
|
||||
(новичок / классика / без текста). Подсказка **выставляет предложенные фишки на
|
||||
доску** — игрок сам решает сделать ход, и подсказка не тратится, если ходов нет.
|
||||
Проверка слова принимает только алфавит варианта, запоминает ответы в рамках сессии
|
||||
и ограничивает частоту повторов.
|
||||
|
||||
### Личность и сессии *(Stage 1 / 6)*
|
||||
Игрок приходит с платформы (сначала Telegram), через email-вход или как
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
# Scrabble Game — UI design system
|
||||
|
||||
Visual and interaction conventions for the `ui` client. Behaviour lives in
|
||||
[`FUNCTIONAL.md`](FUNCTIONAL.md); cross-service architecture (including the global
|
||||
points this doc references) lives in [`ARCHITECTURE.md`](ARCHITECTURE.md). The client
|
||||
is **pure HTML5/CSS + Unicode** — no image/font/SVG assets; icons are CSS shapes or
|
||||
emoji glyphs. Tokens are CSS custom properties (`ui/src/app.css`), light/dark via
|
||||
`prefers-color-scheme` or an explicit Settings choice, and **Telegram-themeParams-ready**
|
||||
(the tokens can be overridden at runtime).
|
||||
|
||||
## Layout shell (`components/Screen.svelte`)
|
||||
|
||||
A mobile-app feel: the screen is a full-height flex column where the **nav bar grows**
|
||||
to absorb spare vertical space (its buttons stay top-aligned) and everything else —
|
||||
the announcement strip, the content, and the optional bottom tab bar — **pins to the
|
||||
bottom**, the strip directly above the content. Tall content scrolls within the content
|
||||
region. Every screen except Login uses `Screen`.
|
||||
|
||||
## Navigation
|
||||
|
||||
- **Back**: a thin, compact `<` drawn from two rotated CSS borders (`Header.svelte`
|
||||
`.chev`) — lighter than a glyph.
|
||||
- **Hamburger**: a CSS three-bar (`Menu.svelte`), deliberately larger; opens a dropdown
|
||||
of items (lobby: Profile/Settings/About; game: History/Chat/Check word/Drop game).
|
||||
- **Tab bar** (`TabBar.svelte`): square, borderless, evenly distributed buttons — a large
|
||||
emoji icon over a tiny truncated label. A press highlights a rounded **square** behind
|
||||
the icon (slightly larger than it) until release; spacing keeps adjacent labels from
|
||||
touching. No text selection on nav / tab-bar / buttons (`user-select: none`).
|
||||
|
||||
## Tiles & board
|
||||
|
||||
- **Tiles**: the letter sits in the **top-left** corner (offset a touch more than the
|
||||
value), the point value bottom-right; blanks show no value.
|
||||
- **Board zoom** (`Board.svelte`): a two-state zoom (full 15×15 ↔ ~9 cells) via
|
||||
`transform: scale()` on an inner layer inside a **fixed-size viewport** (the page never
|
||||
reflows; the viewport scrolls when zoomed), with a smooth transition. Cell/tile **text
|
||||
lives in a counter-scaled layer** (`scale(1/z)`) sized in `cqw`, so labels stay a
|
||||
constant size (relatively smaller at higher zoom). On touch, attempting to place a tile
|
||||
auto-zooms in centred on the target; double-tap and pinch toggle.
|
||||
- **Bonus-square labels** — a Settings choice (`boardlabels.ts`): `beginner` shows a
|
||||
split `3×` / `word` (localized слово/буква), `classic` a single `3W` / `3С`, `none`
|
||||
nothing. Default **beginner**.
|
||||
- **Grid lines**: the inter-cell gap shows a contrasting `--cell-line` (darker in light,
|
||||
lighter in dark) to avoid a wavy-line optical illusion.
|
||||
|
||||
## Controls
|
||||
|
||||
- **HoldConfirm** (`components/HoldConfirm.svelte`): the shared press-and-hold control. A
|
||||
short tap opens a small popover above the button; a ~0.7 s hold runs the primary action
|
||||
immediately. Reused by:
|
||||
- **MakeMove** (appears when ≥1 tile is pending; the rack collapses its used slots and
|
||||
shifts left to free room): a **🏁** button whose popover offers **Make move ✅** /
|
||||
**Reset ❌**.
|
||||
- **Game tab bar**: 🔄 Draw (disabled when the bag is empty), 🥺 Skip, 🛟 Hint (with a
|
||||
remaining-count badge) — each confirmed by an **Ok ✅** popover; 🔀 Shuffle has no
|
||||
label and no confirm. The under-board slot shows the **Scores: N** preview.
|
||||
|
||||
## Announcement banner (`components/AdBanner.svelte`, `lib/banner.ts`)
|
||||
|
||||
A one-line inset strip under the nav bar. Content is minimal markdown (text + links,
|
||||
escaped + linkified). A parameterised **rotator** drives messages: a fitting message
|
||||
holds `holdMs` (default 60 s) then cross-fades to the next; a message wider than the strip
|
||||
pauses (`edgePauseMs`), scrolls to its right edge at `scrollPxPerSec`, pauses, and repeats
|
||||
until the cycle exceeds `holdMs`. Today a **mock** provider rotates a long and a short
|
||||
message; the source becomes a server-driven channel later (see ARCHITECTURE).
|
||||
|
||||
## Result / status iconography (`lib/result.ts`)
|
||||
|
||||
Lobby rows show two lines (opponents, then result + score) with a large place-based emoji
|
||||
on the right: Victory 🏆 / Defeat 🥈 / Draw 🏅, and for 3–4-player games II 🥈 / III 🥉 /
|
||||
IV 🏅; active games show Your move 🟢 / Opponent's move ⏳; invitations use 💌.
|
||||
|
||||
## Caveat
|
||||
|
||||
Emoji are rendered by the platform's system emoji font, so their exact look varies across
|
||||
OSes — acceptable for the MVP, and consistent with the no-asset rule (no glyphs are
|
||||
downloaded).
|
||||
Reference in New Issue
Block a user