From 75b73cd3f59877b562a8b7a9603a20b511683643 Mon Sep 17 00:00:00 2001 From: Henrik Kurelid Date: Mon, 20 Apr 2026 22:20:49 +0200 Subject: [PATCH 1/8] fix: make quest popup body scrollable to prevent overflow - Modal card capped at max-h-[90vh] with flex-col layout - Body text scrolls independently; title and Continue button always visible - Bottom fade gradient hints at more content below - Padding reduced to p-4 on mobile, p-6 on desktop - 2 new e2e tests: Continue button within viewport, card height <= viewport Formatting constraints verified --- web/e2e/game.spec.ts | 59 +++++++++++++++++++++++++++++++ web/src/components/QuestModal.vue | 34 ++++++++++++------ 2 files changed, 82 insertions(+), 11 deletions(-) diff --git a/web/e2e/game.spec.ts b/web/e2e/game.spec.ts index dce4a90..d563cd7 100644 --- a/web/e2e/game.spec.ts +++ b/web/e2e/game.spec.ts @@ -197,6 +197,65 @@ test.describe('QuestModal – Escape key dismissal', () => { }) }) +/* ------------------------------------------------------------------ */ +/* QuestModal overflow fix – Continue button always reachable */ +/* ------------------------------------------------------------------ */ + +test.describe('QuestModal – overflow fix', () => { + test.beforeEach(async ({ page }) => { + await page.goto(APP_URL) + await expect(page.locator('.loading-spinner')).toBeVisible({ + timeout: 10_000, + }) + await injectMockGameState(page) + }) + + async function openLongModal(page: Page) { + const longBody = Array.from( + { length: 12 }, + (_, i) => + `

Paragraph ${i + 1}: The ancient prophecy speaks of a hero who shall rise from humble beginnings to face a darkness that has long plagued these lands. Only the chosen one may restore balance.

`, + ).join('') + await page.evaluate((body: string) => { + /* eslint-disable @typescript-eslint/no-explicit-any */ + const app = (document.querySelector('#app') as any).__vue_app__ + const pinia = app.config.globalProperties.$pinia + const store = pinia.state.value.game + store.showModal = true + store.modalTitle = 'A Very Long Quest' + store.modalBody = body + /* eslint-enable @typescript-eslint/no-explicit-any */ + }, longBody) + await expect(page.getByText('A Very Long Quest', { exact: true })).toBeVisible() + } + + test('Continue button is visible in viewport when quest body is very long', async ({ + page, + }) => { + await openLongModal(page) + const button = page.getByRole('button', { name: 'Continue' }) + await expect(button).toBeVisible() + const box = await button.boundingBox() + const viewportSize = page.viewportSize() + expect(box).not.toBeNull() + expect(viewportSize).not.toBeNull() + expect(box!.y + box!.height).toBeLessThanOrEqual(viewportSize!.height) + }) + + test('modal card does not exceed viewport height when body is very long', async ({ + page, + }) => { + await openLongModal(page) + const card = page.locator('[data-testid="quest-modal-card"]') + await expect(card).toBeVisible() + const box = await card.boundingBox() + const viewportSize = page.viewportSize() + expect(box).not.toBeNull() + expect(viewportSize).not.toBeNull() + expect(box!.height).toBeLessThanOrEqual(viewportSize!.height) + }) +}) + /* ------------------------------------------------------------------ */ /* LoadDialog Escape key tests */ /* ------------------------------------------------------------------ */ diff --git a/web/src/components/QuestModal.vue b/web/src/components/QuestModal.vue index 9ed2a1c..f178589 100644 --- a/web/src/components/QuestModal.vue +++ b/web/src/components/QuestModal.vue @@ -33,18 +33,30 @@ onUnmounted(() => { @click.self="$emit('dismiss')" >
-
{{ title }}
- -
- -
+
+ {{ title }} +
+
+ +
+
+
+
+ +
From d4a4455893a629605cb08c10abba3516d5af076b Mon Sep 17 00:00:00 2001 From: Henrik Kurelid Date: Mon, 20 Apr 2026 22:25:42 +0200 Subject: [PATCH 2/8] fix: remove overflow-hidden wrapper blocking touch scroll in quest popup The parent overflow-hidden was preventing touch scroll events from reaching the inner overflow-y-auto div on iOS/mobile. Also adds touch-pan-y to explicitly enable vertical touch scroll on the body. --- web/src/components/QuestModal.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/src/components/QuestModal.vue b/web/src/components/QuestModal.vue index f178589..58b0d80 100644 --- a/web/src/components/QuestModal.vue +++ b/web/src/components/QuestModal.vue @@ -39,10 +39,10 @@ onUnmounted(() => {
{{ title }}
-
+
Date: Mon, 20 Apr 2026 22:29:53 +0200 Subject: [PATCH 3/8] fix: flatten scroll container to fix overflow on Android On Android Chrome, overflow-y-auto on a nested div inside a flex-1 min-h-0 wrapper is unreliable and causes text to overflow the modal. Flatten to a single flex child with overflow-y-auto, min-h-0, and overscroll-contain directly on the content div. --- web/src/components/QuestModal.vue | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/web/src/components/QuestModal.vue b/web/src/components/QuestModal.vue index 58b0d80..381d7e3 100644 --- a/web/src/components/QuestModal.vue +++ b/web/src/components/QuestModal.vue @@ -39,16 +39,11 @@ onUnmounted(() => {
{{ title }}
-
- -
-
-
+ +