docs(ui): finalize MVP plan structure and de-archaeologize topic docs
MVP web client (Phases 1-30) is complete; reorganize planning + living docs around that. - PLAN.md kept as the staged MVP record (1-30) with a status block + pointers; removed the 31-36 stages, regression scenarios, and deferred-TODO section (moved out); fixed a stale cross-machine plan path. - ui/PLAN-finalize.md (new): active web-finalization plan in 8 stages (visual system, a11y, i18n, error UX, PWA, build hygiene, docs, owner manual-QA loop); absorbs former Phases 33 and 35. - ui/ROADMAP.md (new): post-MVP (Wails, Capacitor, realistic projection, acceptance + regression scenarios) and triaged deferred follow-ups. - ui/docs/README.md (new): grouped topic-doc index. - De-archaeologized all 20 ui/docs topic docs + ui/README.md + ui/core/README.md: stripped Phase-N build history, rewritten as current-state; deferred work now points at ROADMAP.md / PLAN-finalize.md. Docs-only; no code change. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
+56
-65
@@ -18,50 +18,45 @@ two-line wrapper that mounts the matching content component from
|
||||
the plan is the file system plus those wrappers — there is no
|
||||
separate dispatch component.
|
||||
|
||||
| URL | Active view component | Phase that fills it |
|
||||
| ------------------------------------- | ---------------------------------------------- | ----------------------- |
|
||||
| URL | Active view component | Phase that fills it |
|
||||
| ------------------------------------------ | ---------------------------------------------- | ----------------------- |
|
||||
| `/games/:id/map` | `lib/active-view/map.svelte` | Phase 11 |
|
||||
| `/games/:id/table/:entity` | `lib/active-view/table.svelte` | Phase 11 / 17 / 19 / 22 |
|
||||
| `/games/:id/report` | `lib/active-view/report.svelte` (see [report-view.md](report-view.md)) | Phase 23 |
|
||||
| `/games/:id/battle/:battleId?` | `lib/active-view/battle.svelte` | Phase 27 |
|
||||
| `/games/:id/mail` | `lib/active-view/mail.svelte` | Phase 28 |
|
||||
| `/games/:id/designer/science/:scienceId?` | `lib/active-view/designer-science.svelte` | Phase 21 |
|
||||
| URL | Active view component |
|
||||
| ------------------------------------------ | ---------------------------------------------------------------------- |
|
||||
| `/games/:id/map` | `lib/active-view/map.svelte` |
|
||||
| `/games/:id/table/:entity` | `lib/active-view/table.svelte` |
|
||||
| `/games/:id/report` | `lib/active-view/report.svelte` (see [report-view.md](report-view.md)) |
|
||||
| `/games/:id/battle/:battleId?` | `lib/active-view/battle.svelte` |
|
||||
| `/games/:id/mail` | `lib/active-view/mail.svelte` |
|
||||
| `/games/:id/designer/science/:scienceId?` | `lib/active-view/designer-science.svelte` |
|
||||
|
||||
`/games/:id` (no trailing view) redirects to `/games/:id/map`. The
|
||||
optional `:scienceId?` segment on the science designer route matches
|
||||
SvelteKit's `[[scienceId]]` syntax — `/designer/science` opens the
|
||||
empty new-science form, `/designer/science/{name}` opens the named
|
||||
science. Phase 17/18 originally added a parallel ship-class designer
|
||||
route; Phase 30 removed it and folded ship-class design into the
|
||||
sidebar ship-class calculator (`lib/sidebar/calculator-tab.svelte`,
|
||||
see [calculator-ux.md](calculator-ux.md)), reached from the
|
||||
ship-classes table and the view/bottom menus.
|
||||
science. Ship-class design is folded into the sidebar ship-class
|
||||
calculator (`lib/sidebar/calculator-tab.svelte`, see
|
||||
[calculator-ux.md](calculator-ux.md)), reached from the ship-classes
|
||||
table and the view/bottom menus.
|
||||
|
||||
The `entity` slug on the table route is kebab-case (`planets`,
|
||||
`ship-classes`, `ship-groups`, `fleets`, `sciences`, `races`).
|
||||
`table.svelte` is the active-view router: it dispatches by slug to
|
||||
the per-entity component (`ship-classes` → `table-ship-classes.svelte`
|
||||
in Phase 17; the others fall back to the Phase 10 stub copy until
|
||||
their respective phases land).
|
||||
the per-entity component (`ship-classes` → `table-ship-classes.svelte`;
|
||||
other entities dispatch to their respective components).
|
||||
|
||||
## Sidebar tools and state preservation
|
||||
|
||||
The desktop sidebar hosts three tools:
|
||||
|
||||
| Tool | Component | Phase that fills it |
|
||||
| ---------- | -------------------------------------- | -------------------- |
|
||||
| Calculator | `lib/sidebar/calculator-tab.svelte` | Phase 30 |
|
||||
| Inspector | `lib/sidebar/inspector-tab.svelte` | Phase 13 / 19 |
|
||||
| Order | `lib/sidebar/order-tab.svelte` | Phase 12 / 14 |
|
||||
| Tool | Component |
|
||||
| ---------- | ----------------------------------- |
|
||||
| Calculator | `lib/sidebar/calculator-tab.svelte` |
|
||||
| Inspector | `lib/sidebar/inspector-tab.svelte` |
|
||||
| Order | `lib/sidebar/order-tab.svelte` |
|
||||
|
||||
The selected-tab state is a `$state` rune in
|
||||
`routes/games/[id]/+layout.svelte`, bound into
|
||||
`lib/sidebar/sidebar.svelte` via `$bindable()`. The layout owns the
|
||||
rune so external events — Phase 13's planet click, future similar
|
||||
flows — can drive the active tab from outside the sidebar without
|
||||
plumbing callbacks. The component is mounted by the layout, and
|
||||
rune so external events — such as a planet click — can drive the
|
||||
active tab from outside the sidebar without plumbing callbacks. The component is mounted by the layout, and
|
||||
SvelteKit keeps that layout instance alive while the user navigates
|
||||
between child routes (`/games/:id/map` → `/games/:id/report` → …),
|
||||
so the rune survives every active-view switch automatically with no
|
||||
@@ -70,23 +65,21 @@ described below still live inside the sidebar — they mutate the
|
||||
bindable in place; the layout sees the change through the binding.
|
||||
|
||||
A `?sidebar=calc|calculator|inspector|order` URL param is read once
|
||||
on mount and seeds the initial tab. Later phases that want to land
|
||||
the user on a particular tool (for example, Phase 14's first
|
||||
end-to-end command flow) can set it on navigation.
|
||||
on mount and seeds the initial tab. Navigation flows that want to
|
||||
land the user on a particular tool can set this param on navigation.
|
||||
|
||||
The Order entry is hidden when the layout's `historyMode` flag is
|
||||
true. Phase 12 plumbs the flag end-to-end as a prop —
|
||||
`+layout.svelte` forwards a derived value to `Sidebar`, which
|
||||
true. `+layout.svelte` forwards a derived value to `Sidebar`, which
|
||||
forwards `hideOrder` to its `TabBar`; the same flag goes to
|
||||
`BottomTabs` so the mobile `Order` button is also suppressed. A
|
||||
`?sidebar=order` URL seed that arrives while the flag is true falls
|
||||
back to `inspector`, and an `$effect` on the sidebar resets
|
||||
`activeTab` away from `order` if the flag flips on mid-session.
|
||||
|
||||
Phase 26 wires the flag to the live history signal owned by
|
||||
`GameStateStore`. The derivation lives directly in `+layout.svelte`
|
||||
The `historyMode` flag is derived from the live history signal owned
|
||||
by `GameStateStore`. The derivation lives directly in `+layout.svelte`
|
||||
(`const historyMode = $derived(gameState.historyMode)`) — no
|
||||
separate `lib/history-mode.ts` module ships, because the layout is
|
||||
separate `lib/history-mode.ts` module exists, because the layout is
|
||||
the single consumer and the project's compactness rule rejects a
|
||||
one-line indirection. The order draft survives the toggle because
|
||||
`OrderDraftStore` lives one level above the sidebar in the layout
|
||||
@@ -100,8 +93,7 @@ for the draft-store side of the flow and
|
||||
|
||||
## Header turn navigator and history banner
|
||||
|
||||
The header replaces the Phase 11 inline `turn N` text with a
|
||||
`← Turn N →` triplet (`lib/header/turn-navigator.svelte`). The
|
||||
The header shows a `← Turn N →` triplet (`lib/header/turn-navigator.svelte`). The
|
||||
arrows step `viewedTurn` by ±1 (disabled at boundaries `0` and
|
||||
`currentTurn`); clicking the middle button opens an absolute
|
||||
popover (desktop) or a fixed full-width drawer (mobile, ≤ 767.98
|
||||
@@ -129,9 +121,8 @@ Three discrete CSS modes matched to the IA section diagrams:
|
||||
toggle in the header right corner. Tapping the toggle slides the
|
||||
sidebar in as a fixed overlay above the active view; a close
|
||||
button on the sidebar dismisses it. The full swipe-from-right
|
||||
gesture in the IA section is deferred to Phase 35 polish — the
|
||||
click toggle satisfies the "layout switches at 768 px" acceptance
|
||||
criterion on Phase 10.
|
||||
gesture is deferred to the finalization plan
|
||||
([../PLAN-finalize.md](../PLAN-finalize.md)).
|
||||
- **< 768 px (mobile)** — the sidebar is hidden entirely and the
|
||||
bottom-tabs row appears at the bottom of the viewport. The
|
||||
view-menu trigger swaps to a hamburger icon (☰) that opens the
|
||||
@@ -139,7 +130,7 @@ Three discrete CSS modes matched to the IA section diagrams:
|
||||
|
||||
On mobile the bottom tab row does not include `Inspector`. The
|
||||
inspector content is reached by tapping a map object instead, which
|
||||
raises a bottom-sheet — see [Planet selection](#planet-selection-phase-13).
|
||||
raises a bottom-sheet — see [Planet selection](#planet-selection).
|
||||
|
||||
## Mobile bottom-tabs and tool overlay
|
||||
|
||||
@@ -157,27 +148,27 @@ The next time the user taps a Calc or Order bottom-tab, the
|
||||
navigation re-routes them to `/map` and re-applies the overlay.
|
||||
|
||||
The `More` button opens a drawer that mirrors the header view-menu
|
||||
content. The IA section's narrower "More" list (Mail, Battle log,
|
||||
Tables, History, Settings, Logout) is the polish target for Phase 35
|
||||
— Phase 10 keeps a single source of truth for destinations.
|
||||
content. A narrower "More" list (Mail, Battle log, Tables, History,
|
||||
Settings, Logout) is deferred to the finalization plan
|
||||
([../PLAN-finalize.md](../PLAN-finalize.md)); the current drawer keeps
|
||||
a single source of truth for destinations.
|
||||
|
||||
## Transient map overlays
|
||||
|
||||
Some views can push a transient overlay onto `/map` with a back
|
||||
affordance. (Phase 30's calculator reach circles are a simpler,
|
||||
always-on map extra rather than a back-stacked overlay; the transient
|
||||
back-stack mechanism itself is still a Phase 34 concept.) A transient
|
||||
overlay clears when the user navigates to any other view via the header
|
||||
or the bottom-tabs.
|
||||
affordance. (The calculator reach circles are a simpler, always-on
|
||||
map extra rather than a back-stacked overlay; the transient
|
||||
back-stack mechanism is planned — see
|
||||
[../ROADMAP.md](../ROADMAP.md).) A transient overlay clears when the
|
||||
user navigates to any other view via the header or the bottom-tabs.
|
||||
|
||||
Phase 10 documents this concept but does not implement the
|
||||
back-stack mechanism. Phase 34 lands the back-stack alongside its
|
||||
first user (multi-turn projection, range circles in the ship-class
|
||||
designer).
|
||||
The back-stack mechanism is not yet implemented; it is planned
|
||||
alongside its first user (multi-turn projection, range circles in the
|
||||
ship-class designer) in [../ROADMAP.md](../ROADMAP.md).
|
||||
|
||||
## Planet selection (Phase 13)
|
||||
## Planet selection
|
||||
|
||||
The map view turns into the entry point for the inspector by
|
||||
The map view is the entry point for the inspector by
|
||||
translating a renderer click into a planet selection. The flow:
|
||||
|
||||
1. The renderer (`src/map/render.ts`) exposes `onClick(cb)` next to
|
||||
@@ -190,9 +181,9 @@ translating a renderer click into a planet selection. The flow:
|
||||
`GameStateStore.report`, and calls `SelectionStore.selectPlanet(number)`.
|
||||
3. `SelectionStore` (`lib/selection.svelte.ts`) is a runes store
|
||||
instantiated by the layout and exposed via Svelte context under
|
||||
`SELECTION_CONTEXT_KEY`. It carries a discriminated union — Phase
|
||||
13 only models `{ kind: "planet"; id: number }`; Phase 19 widens
|
||||
it for ship groups. Selection is in-memory only: it survives the
|
||||
`SELECTION_CONTEXT_KEY`. It carries a discriminated union —
|
||||
`{ kind: "planet"; id: number }` for planets and widened for
|
||||
ship groups. Selection is in-memory only: it survives the
|
||||
layout's lifetime (active-view switches inside `/games/:id/*`)
|
||||
but does not persist across reloads — that contrast with the
|
||||
order draft is intentional.
|
||||
@@ -211,11 +202,11 @@ translating a renderer click into a planet selection. The flow:
|
||||
|
||||
The mobile bottom-sheet is mounted alongside `<BottomTabs />` in the
|
||||
layout. Its visibility is conditional on `effectiveTool === "map"` so
|
||||
it does not stack on top of the calc / order overlays. Phase 13 ships
|
||||
the minimal dismissal surface: a close button (`✕`) that calls
|
||||
`SelectionStore.clear()`. Tap-outside and swipe-down dismissal from
|
||||
the IA section are deferred to Phase 35 polish. A click that lands on
|
||||
empty space is a no-op — selection is mutated only by an explicit
|
||||
it does not stack on top of the calc / order overlays. The dismissal
|
||||
surface is a close button (`✕`) that calls `SelectionStore.clear()`.
|
||||
Tap-outside and swipe-down dismissal are deferred to the finalization
|
||||
plan ([../PLAN-finalize.md](../PLAN-finalize.md)). A click that lands
|
||||
on empty space is a no-op — selection is mutated only by an explicit
|
||||
planet click or by the close button.
|
||||
|
||||
The planet inspector itself is a presentational component: it takes
|
||||
@@ -227,9 +218,9 @@ field the FBS schema carries (`industryStockpile` for `capital`,
|
||||
Fields the FBS table does not project for a given kind read as `null`
|
||||
and the inspector simply omits the row.
|
||||
|
||||
The selected-planet visual on the map (a ring or halo) is **not**
|
||||
shipped in Phase 13. It rolls into Phase 35 polish together with the
|
||||
sheet's swipe-to-dismiss gesture.
|
||||
The selected-planet visual on the map (a ring or halo) is deferred
|
||||
to the finalization plan ([../PLAN-finalize.md](../PLAN-finalize.md))
|
||||
together with the sheet's swipe-to-dismiss gesture.
|
||||
|
||||
## Auth gate
|
||||
|
||||
|
||||
Reference in New Issue
Block a user