ui/phase-10: in-game shell with view-replacement skeleton

Wraps every in-game route under `/games/:id/*` in a responsive shell
with a header (race / turn placeholders, view-menu dropdown or mobile
hamburger, account menu), a three-tab sidebar (Calculator, Inspector,
Order), an active-view slot, and a mobile-only bottom-tabs row
`[Map, Calc, Order, More]`. Every view in the IA section
(`map`, `table/:entity`, `report`, `battle/:battleId?`, `mail`,
`designer/{ship-class,science}/:id?`) ships as a thin SvelteKit route
that mounts a `lib/active-view/<name>.svelte` stub rendering a
localised `coming soon` body. The lobby's `gotoGame` path now actually
lands on a rendered shell instead of a 404.

The "view router" mentioned in the plan is implemented as the file
system plus two-line route wrappers — no separate dispatch component.
Sidebar tab state lives as a `$state` rune inside `sidebar.svelte`,
which sits in the layout that SvelteKit keeps mounted across child
route swaps, so tab choice survives every active-view navigation for
free. A `?sidebar=calc|inspector|order` URL param seeds the initial
tab on first mount; the mobile bottom-tabs use a layout-owned
`mobileTool` rune with a URL-gated `effectiveTool` derivation so the
Calc / Order tool overlay only applies on `/map` and naturally drops
when the user navigates elsewhere.

Tablet ships with a click-toggle drawer for the sidebar rather than
the IA section's swipe-from-right gesture; the structural breakpoint
satisfies Phase 10's acceptance criterion and Phase 35 polish lands
the swipe. The mobile More drawer mirrors the header view-menu
content; the IA's narrower More list (Mail, Battle, Tables, History,
Settings, Logout) is also a Phase 35 polish target once History
exists.

Topic doc `ui/docs/navigation.md` captures the active-view model, the
sidebar state-preservation rule, the `?sidebar=` and `mobileTool`
conventions, and the transient map-overlay back-stack concept (with
the implementation deferred to Phase 34 alongside its first user).
i18n catalogues for `en` and `ru` add the full `game.shell.*`,
`game.view.*`, `game.sidebar.*`, `game.bottom_tabs.*` namespaces.

Tests: Vitest covers the header view-menu (every IA destination
including the Tables sub-list), the account-menu Logout / Language
wiring, the sidebar default tab / switching / `?sidebar=` seed /
close button, and every active-view stub. Playwright e2e boots an
authenticated session via `__galaxyDebug.setDeviceSessionId` (no
gateway calls — the shell makes none in Phase 10), exercises every
view through both the desktop dropdown and the mobile More drawer,
verifies sidebar tab survival across navigation, and uses
`setViewportSize` to validate the breakpoint switches at 768 px and
1024 px.

Phase 10 status stays `pending` in `ui/PLAN.md` until the local-ci
run lands green; flipping to `done` follows in the next commit per
the per-stage CI gate in `CLAUDE.md`.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Ilia Denisov
2026-05-08 20:15:49 +02:00
parent 0f8f8698bd
commit fc371c7fe1
36 changed files with 2337 additions and 29 deletions
+41
View File
@@ -82,6 +82,47 @@ const en = {
"lobby.error.conflict": "request conflicts with current state",
"lobby.error.internal_error": "internal server error",
"lobby.error.unknown": "{message}",
"game.shell.race_placeholder": "race ?",
"game.shell.turn_label": "turn",
"game.shell.turn_unknown": "?",
"game.shell.connection.online": "online",
"game.shell.connection.reconnecting": "reconnecting…",
"game.shell.connection.offline": "offline",
"game.shell.menu.toggle_sidebar": "open sidebar",
"game.shell.menu.close_sidebar": "close sidebar",
"game.shell.menu.open_views": "open views menu",
"game.shell.menu.close_views": "close views menu",
"game.shell.menu.account": "account",
"game.shell.menu.settings": "settings",
"game.shell.menu.sessions": "sessions",
"game.shell.menu.theme": "theme",
"game.shell.menu.language": "language",
"game.shell.menu.logout": "logout",
"game.shell.coming_soon": "coming soon",
"game.view.map": "map",
"game.view.table": "table",
"game.view.table.planets": "planets",
"game.view.table.ship_classes": "ship classes",
"game.view.table.ship_groups": "ship groups",
"game.view.table.fleets": "fleets",
"game.view.table.sciences": "sciences",
"game.view.table.races": "races",
"game.view.report": "turn report",
"game.view.battle": "battle log",
"game.view.mail": "diplomatic mail",
"game.view.designer.ship_class": "ship-class designer",
"game.view.designer.science": "science designer",
"game.sidebar.tab.calculator": "calculator",
"game.sidebar.tab.inspector": "inspector",
"game.sidebar.tab.order": "order",
"game.sidebar.empty.calculator": "coming soon",
"game.sidebar.empty.inspector": "select an object on the map",
"game.sidebar.empty.order": "coming soon",
"game.bottom_tabs.map": "map",
"game.bottom_tabs.calc": "calc",
"game.bottom_tabs.order": "order",
"game.bottom_tabs.more": "more",
} as const;
export default en;