From 609ba6f0dd6ceb97ea46471d9d806af664203643 Mon Sep 17 00:00:00 2001 From: Justin Visser Date: Wed, 10 Jun 2026 18:09:51 +0200 Subject: [PATCH] web: mobile pass, slice 10 of M3 The MobileScoreStrip lands: sticky under the app bar, one pill per panel with the round-synced colored share, horizontally scrollable (the only horizontal scroller, verified at 320 px), tapping scrolls to the panel (instant under reduced motion, scroll-margin clears the sticky stack). Touch targets reach 44 px on mobile: player buttons, panel kebabs, and toolbar buttons; Export collapses to its icon so the toolbar stays one row down to 320 px. --- web/src/App.vue | 2 + web/src/components/MobileScoreStrip.vue | 117 ++++++++++++++++++++++++ web/src/components/PlayerBar.vue | 11 +++ web/src/components/ScenarioPanel.vue | 16 +++- web/src/components/ScenarioToolbar.vue | 20 +++- 5 files changed, 163 insertions(+), 3 deletions(-) create mode 100644 web/src/components/MobileScoreStrip.vue diff --git a/web/src/App.vue b/web/src/App.vue index 6b8feaf..c8b5ff6 100644 --- a/web/src/App.vue +++ b/web/src/App.vue @@ -7,6 +7,7 @@ import FocusModal from '@/components/FocusModal.vue' import FooterDisclaimer from '@/components/FooterDisclaimer.vue' import HeroHeadline from '@/components/HeroHeadline.vue' import LegendRow from '@/components/LegendRow.vue' +import MobileScoreStrip from '@/components/MobileScoreStrip.vue' import NodeTooltip from '@/components/NodeTooltip.vue' import PanelGrid from '@/components/PanelGrid.vue' import PlayerBar from '@/components/PlayerBar.vue' @@ -31,6 +32,7 @@ onMounted(async () => {
+ diff --git a/web/src/components/MobileScoreStrip.vue b/web/src/components/MobileScoreStrip.vue new file mode 100644 index 0000000..c893957 --- /dev/null +++ b/web/src/components/MobileScoreStrip.vue @@ -0,0 +1,117 @@ + + + + + diff --git a/web/src/components/PlayerBar.vue b/web/src/components/PlayerBar.vue index 03b0f87..0090ef7 100644 --- a/web/src/components/PlayerBar.vue +++ b/web/src/components/PlayerBar.vue @@ -335,5 +335,16 @@ input[type='range']::-moz-range-thumb { .player .iconbtn.step { display: none; } + + /* 44 px touch targets (spec section 8). */ + .iconbtn { + width: 44px; + height: 44px; + } + + .iconbtn.play { + width: 48px; + height: 48px; + } } diff --git a/web/src/components/ScenarioPanel.vue b/web/src/components/ScenarioPanel.vue index 3498b75..d1847f3 100644 --- a/web/src/components/ScenarioPanel.vue +++ b/web/src/components/ScenarioPanel.vue @@ -94,7 +94,7 @@ const dimmed = computed(() => store.state.runState === 'running' && result.value