diff --git a/ui/PLAN-finalize.md b/ui/PLAN-finalize.md index c40f2bc..251d640 100644 --- a/ui/PLAN-finalize.md +++ b/ui/PLAN-finalize.md @@ -19,7 +19,15 @@ being marked done. --- -## F1 — Visual design system +## F1 — Visual design system — done + +Merged to `development` via PR #26 (2026-05-22): a shared design-token +system (`ui/frontend/src/lib/theme/`), light/dark theming with a picker +and pre-paint guard, and the whole UI migrated onto the tokens. +Documented literal exceptions: the battle-scene data-viz palette, overlay +scrims, and directional/deliberate drop shadows. The default theme is +dark; flipping it to `system` is an available follow-up. Tokens and +conventions live in `ui/docs/design-system.md`. Goal: replace the ad-hoc per-component styling (inline hex colors like `#0a0e1a`, one-off spacing) with a shared design language so every view @@ -36,7 +44,17 @@ Acceptance: no literal theme colors left in component ` diff --git a/ui/frontend/src/lib/active-view/map-toggles.svelte b/ui/frontend/src/lib/active-view/map-toggles.svelte index 9e01036..2b61bda 100644 --- a/ui/frontend/src/lib/active-view/map-toggles.svelte +++ b/ui/frontend/src/lib/active-view/map-toggles.svelte @@ -14,6 +14,7 @@ bottom-tabs bar. -
- {#each tabs as tab (tab.id)} +
+ {#each tabs as tab, i (tab.id)} diff --git a/ui/frontend/src/lib/theme/base.css b/ui/frontend/src/lib/theme/base.css index fe31674..44e5fb4 100644 --- a/ui/frontend/src/lib/theme/base.css +++ b/ui/frontend/src/lib/theme/base.css @@ -27,3 +27,41 @@ body { ::selection { background: var(--color-accent-subtle); } + +/* + * Visually-hidden content that stays available to assistive tech. Use + * for labels/announcements a sighted user gets from layout or icons. + */ +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border: 0; +} + +/* + * Skip link: visually hidden until focused, then slides into the + * top-left so a keyboard user can jump straight to the main content. + * Each layout renders one as its first focusable element, targeting a + * `tabindex="-1"` main region. + */ +.skip-link { + position: absolute; + left: var(--space-2); + top: -4rem; + z-index: 100; + padding: var(--space-2) var(--space-3); + background: var(--color-surface-overlay); + color: var(--color-text); + border: 1px solid var(--color-border); + border-radius: var(--radius-sm); + transition: top 120ms ease; +} +.skip-link:focus-visible { + top: var(--space-2); +} diff --git a/ui/frontend/src/routes/games/[id]/+layout.svelte b/ui/frontend/src/routes/games/[id]/+layout.svelte index 591ab86..c2ad782 100644 --- a/ui/frontend/src/routes/games/[id]/+layout.svelte +++ b/ui/frontend/src/routes/games/[id]/+layout.svelte @@ -46,6 +46,7 @@ fresh. import { onDestroy, onMount, setContext, untrack } from "svelte"; import { goto } from "$app/navigation"; import { page } from "$app/state"; + import { i18n } from "$lib/i18n/index.svelte"; import Header from "$lib/header/header.svelte"; import HistoryBanner from "$lib/header/history-banner.svelte"; import Sidebar from "$lib/sidebar/sidebar.svelte"; @@ -528,6 +529,9 @@ fresh.
+
-
+
{#if effectiveTool === "calc"} {:else if effectiveTool === "order"} diff --git a/ui/frontend/src/routes/lobby/+page.svelte b/ui/frontend/src/routes/lobby/+page.svelte index 35f198f..77cd66d 100644 --- a/ui/frontend/src/routes/lobby/+page.svelte +++ b/ui/frontend/src/routes/lobby/+page.svelte @@ -265,7 +265,8 @@ }); -
+ +

{i18n.t("lobby.title")}

@@ -297,7 +298,7 @@

{i18n.t("lobby.section.my_games")}

{#if listsLoading} -

{i18n.t("lobby.list_loading")}

+

{i18n.t("lobby.list_loading")}

{:else if myGames.length === 0}

{i18n.t("lobby.my_games.empty")}

{:else} @@ -323,7 +324,7 @@

{i18n.t("lobby.section.invitations")}

{#if listsLoading} -

{i18n.t("lobby.list_loading")}

+

{i18n.t("lobby.list_loading")}

{:else if invitations.length === 0}

{i18n.t("lobby.invitations.empty")}

{:else} @@ -357,7 +358,7 @@

{i18n.t("lobby.section.applications")}

{#if listsLoading} -

{i18n.t("lobby.list_loading")}

+

{i18n.t("lobby.list_loading")}

{:else if applications.length === 0}

{i18n.t("lobby.applications.empty")}

{:else} @@ -416,7 +417,7 @@

{i18n.t("lobby.section.public_games")}

{#if listsLoading} -

{i18n.t("lobby.list_loading")}

+

{i18n.t("lobby.list_loading")}

{:else if publicGames.length === 0}

{i18n.t("lobby.public_games.empty")}

{:else} diff --git a/ui/frontend/src/routes/lobby/create/+page.svelte b/ui/frontend/src/routes/lobby/create/+page.svelte index 9b169d1..0aa13d0 100644 --- a/ui/frontend/src/routes/lobby/create/+page.svelte +++ b/ui/frontend/src/routes/lobby/create/+page.svelte @@ -125,7 +125,8 @@ }); -
+ +

{i18n.t("lobby.create.title")}

{#if configError !== null}

{configError}

diff --git a/ui/frontend/src/routes/login/+page.svelte b/ui/frontend/src/routes/login/+page.svelte index 482c5b5..23bacd3 100644 --- a/ui/frontend/src/routes/login/+page.svelte +++ b/ui/frontend/src/routes/login/+page.svelte @@ -133,7 +133,8 @@ } -
+ +

{i18n.t("login.title")}

@@ -166,7 +167,7 @@ stroke-width="1.5" /> -