From e76d3ca5dbd048522059c68ea142d79dbc5d2a6b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 2 Jul 2026 18:02:01 +0000 Subject: [PATCH 1/4] Initial plan From 6d638f0b8077342a737e7969f96330a680fcd412 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 2 Jul 2026 18:15:25 +0000 Subject: [PATCH 2/4] Fix package modal scroll locking --- .../src/script/components/publish-pane.ts | 5 +- .../Frontend/tests/packaging.spec.ts | 59 +++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) diff --git a/apps/pwabuilder/Frontend/src/script/components/publish-pane.ts b/apps/pwabuilder/Frontend/src/script/components/publish-pane.ts index 0bec50340..2e37db647 100644 --- a/apps/pwabuilder/Frontend/src/script/components/publish-pane.ts +++ b/apps/pwabuilder/Frontend/src/script/components/publish-pane.ts @@ -24,6 +24,7 @@ import { AndroidPackageOptions } from "../utils/android-validation"; import { WindowsPackageOptions } from '../utils/win-validation'; import { Router } from '@vaadin/router'; import { AppStore, packagingCompleted, packagingFailed, packagingStarted } from '../pages/app-report.api'; +import { turnOffScroll, turnOnScroll } from '../utils/dom-utils'; import '@awesome.me/webawesome/dist/components/button/button.js'; import '@awesome.me/webawesome/dist/components/callout/callout.js'; import '@awesome.me/webawesome/dist/components/dialog/dialog.js'; @@ -469,7 +470,7 @@ export class PublishPane extends LitElement { this.feedbackMessages = []; dialog!.open = false; recordPWABuilderProcessStep("publish_pane_closed", AnalyticsBehavior.ProcessCheckpoint); - document.body.style.height = "unset"; + turnOnScroll(); this.cardsOrForm = true; } } @@ -644,6 +645,8 @@ export class PublishPane extends LitElement { turnOffScroll()} @wa-hide=${(e: any) => this.hideDialog(e)} @wa-request-close=${(e: any) => this.handleRequestClose(e)} > diff --git a/apps/pwabuilder/Frontend/tests/packaging.spec.ts b/apps/pwabuilder/Frontend/tests/packaging.spec.ts index 03fc1b943..07b5bae82 100644 --- a/apps/pwabuilder/Frontend/tests/packaging.spec.ts +++ b/apps/pwabuilder/Frontend/tests/packaging.spec.ts @@ -137,3 +137,62 @@ test('Ensure Windows Download Package button has visible focus indicator', async expect(outlineWidth).toBe('2px'); }); + +test('Package for Stores dialog locks scrolling and closes on backdrop click', async ({ page }) => { + const demoButton = page.locator('id=demo-action'); + + await demoButton.click(); + await page.waitForLoadState('networkidle'); + await expect(page.url()).toContain('/reportcard'); + await page.waitForLoadState('networkidle'); + + await page.evaluate(() => window.scrollTo(0, 500)); + const initialScrollPosition = await page.evaluate(() => window.scrollY); + + await page.evaluate(() => { + const appReport = document.querySelector('app-index')?.shadowRoot?.querySelector('app-report') as { + openPublishModal?: () => void; + } | null; + + appReport?.openPublishModal?.(); + }); + + await expect.poll(async () => { + return page.evaluate(() => { + const appReport = document.querySelector('app-index')?.shadowRoot?.querySelector('app-report'); + const dialog = appReport?.shadowRoot + ?.querySelector('publish-pane') + ?.shadowRoot + ?.querySelector('.dialog') as { open?: boolean } | null; + + return dialog?.open ?? false; + }); + }).toBe(true); + + await expect.poll(async () => { + return page.evaluate(() => document.documentElement.style.overflowY); + }).toBe('hidden'); + + await page.mouse.wheel(0, 500); + await expect.poll(async () => { + return page.evaluate(() => window.scrollY); + }).toBe(initialScrollPosition); + + await page.mouse.click(20, 20); + + await expect.poll(async () => { + return page.evaluate(() => { + const appReport = document.querySelector('app-index')?.shadowRoot?.querySelector('app-report'); + const dialog = appReport?.shadowRoot + ?.querySelector('publish-pane') + ?.shadowRoot + ?.querySelector('.dialog') as { open?: boolean } | null; + + return dialog?.open ?? false; + }); + }).toBe(false); + + await expect.poll(async () => { + return page.evaluate(() => document.documentElement.style.overflowY); + }).toBe('initial'); +}); From 05e1d3a644c54af9e0ea1928422045477eded158 Mon Sep 17 00:00:00 2001 From: Judah Himango Date: Wed, 8 Jul 2026 15:11:26 -0700 Subject: [PATCH 3/4] Simplify dialog scroll lock via WA class, make all dialogs light-dismiss Replace the per-dialog JavaScript scroll hacks with a single CSS rule that rides WebAwesome's own wa-scroll-lock lifecycle. WA locks scrolling by adding .wa-scroll-lock to but only styles ; PWABuilder scrolls on , so its built-in lock was a no-op. Adding html.wa-scroll-lock { overflow: hidden } makes WA's lock work for every dialog with no JS. - Remove turnOffScroll/turnOnScroll + dom-utils.ts (added by this PR) - Remove the older document.body.style.height hacks in sw-selector, test-publish-pane and manifest-editor-frame (they had the same #5061 bug) - Enable light-dismiss on all wa-dialogs and drop the preventClosing pattern - Update packaging.spec.ts to assert the wa-scroll-lock class Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- apps/pwabuilder/Frontend/public/global.css | 11 +++++++++++ .../script/components/manifest-editor-frame.ts | 4 +--- .../script/components/publish-pane.styles.ts | 4 ---- .../src/script/components/publish-pane.ts | 17 ++--------------- .../src/script/components/share-card.ts | 9 +-------- .../src/script/components/sw-selector.ts | 3 +-- .../src/script/components/test-publish-pane.ts | 3 +-- .../Frontend/src/script/pages/app-report.ts | 6 +++--- .../src/script/pages/powerplatform-publish.ts | 2 +- .../Frontend/src/script/utils/dom-utils.ts | 7 ------- .../pwabuilder/Frontend/tests/packaging.spec.ts | 8 ++++---- 11 files changed, 25 insertions(+), 49 deletions(-) delete mode 100644 apps/pwabuilder/Frontend/src/script/utils/dom-utils.ts diff --git a/apps/pwabuilder/Frontend/public/global.css b/apps/pwabuilder/Frontend/public/global.css index b67a7edf2..11a413111 100644 --- a/apps/pwabuilder/Frontend/public/global.css +++ b/apps/pwabuilder/Frontend/public/global.css @@ -138,6 +138,17 @@ body { overflow-x: hidden; /* Prevent horizontal scrolling at high zoom */ } +/* + * WebAwesome locks page scrolling by adding the `wa-scroll-lock` class to + * while a dialog is open, but its bundled rule only targets + * (`.wa-scroll-lock body { overflow: hidden }`). PWABuilder scrolls on , + * so that rule is a no-op here. Mirror it on so WA's built-in scroll + * lock works for every dialog without any per-dialog JavaScript. + */ +html.wa-scroll-lock { + overflow: hidden !important; +} + /* Ensure all text wraps properly */ * { word-wrap: break-word; diff --git a/apps/pwabuilder/Frontend/src/script/components/manifest-editor-frame.ts b/apps/pwabuilder/Frontend/src/script/components/manifest-editor-frame.ts index 484fbb9d8..34a03e599 100644 --- a/apps/pwabuilder/Frontend/src/script/components/manifest-editor-frame.ts +++ b/apps/pwabuilder/Frontend/src/script/components/manifest-editor-frame.ts @@ -66,12 +66,10 @@ export class ManifestEditorFrame extends LitElement { if (e.target === dialog) { dialog!.open = false; recordPWABuilderProcessStep("manifest_editor_closed", AnalyticsBehavior.ProcessCheckpoint); - document.body.style.height = "unset"; } } async openDialog() { - document.body.style.height = "100vh" const dialog = this.shadowRoot!.querySelector(".dialog"); dialog?.removeEventListener('wa-request-close', () => { }); @@ -120,7 +118,7 @@ export class ManifestEditorFrame extends LitElement { render() { return html` - this.openDialog()} @wa-hide=${(e: any) => this.hideDialog(e)}> + this.openDialog()} @wa-hide=${(e: any) => this.hideDialog(e)}>
diff --git a/apps/pwabuilder/Frontend/src/script/components/publish-pane.styles.ts b/apps/pwabuilder/Frontend/src/script/components/publish-pane.styles.ts index 624ae0c94..80faace5b 100644 --- a/apps/pwabuilder/Frontend/src/script/components/publish-pane.styles.ts +++ b/apps/pwabuilder/Frontend/src/script/components/publish-pane.styles.ts @@ -319,10 +319,6 @@ export const publishPaneStyles = css` flex-direction: column; } - .noX::part(close-button) { - display: none; - } - .dialog::part(body){ padding: 0; width: 100%; diff --git a/apps/pwabuilder/Frontend/src/script/components/publish-pane.ts b/apps/pwabuilder/Frontend/src/script/components/publish-pane.ts index 2e37db647..ff40e54e6 100644 --- a/apps/pwabuilder/Frontend/src/script/components/publish-pane.ts +++ b/apps/pwabuilder/Frontend/src/script/components/publish-pane.ts @@ -16,7 +16,6 @@ import './android-form'; import './ios-form'; import { AppPackageFormBase } from './app-package-form-base'; import { PackageOptions } from '../utils/interfaces'; -import { classMap } from 'lit/directives/class-map.js'; import { getDataFromDB, setDataInDB } from '../utils/indexedDB'; import { GooglePlayPackageError } from "../models/google-play-package-error"; import { enqueueGooglePlayPackageJob } from "../services/publish/android-publish"; @@ -24,7 +23,6 @@ import { AndroidPackageOptions } from "../utils/android-validation"; import { WindowsPackageOptions } from '../utils/win-validation'; import { Router } from '@vaadin/router'; import { AppStore, packagingCompleted, packagingFailed, packagingStarted } from '../pages/app-report.api'; -import { turnOffScroll, turnOnScroll } from '../utils/dom-utils'; import '@awesome.me/webawesome/dist/components/button/button.js'; import '@awesome.me/webawesome/dist/components/callout/callout.js'; import '@awesome.me/webawesome/dist/components/dialog/dialog.js'; @@ -52,8 +50,6 @@ export class PublishPane extends LitElement { @state() downloadFileName: string | null = null; @state() feedbackMessages: TemplateResult[] = []; - @property({ type: Boolean }) preventClosing = false; - @state() storeMap: any = { "Windows": { @@ -470,17 +466,10 @@ export class PublishPane extends LitElement { this.feedbackMessages = []; dialog!.open = false; recordPWABuilderProcessStep("publish_pane_closed", AnalyticsBehavior.ProcessCheckpoint); - turnOnScroll(); this.cardsOrForm = true; } } - handleRequestClose(e: Event) { - if (this.preventClosing) { - e.preventDefault(); - } - } - // goes from form back to cards when you click the back arrow backToCards() { this.cardsOrForm = !this.cardsOrForm; @@ -644,11 +633,9 @@ export class PublishPane extends LitElement { return html` turnOffScroll()} + class="dialog" + light-dismiss @wa-hide=${(e: any) => this.hideDialog(e)} - @wa-request-close=${(e: any) => this.handleRequestClose(e)} >
diff --git a/apps/pwabuilder/Frontend/src/script/components/share-card.ts b/apps/pwabuilder/Frontend/src/script/components/share-card.ts index 3ee05975d..8298a3ca3 100644 --- a/apps/pwabuilder/Frontend/src/script/components/share-card.ts +++ b/apps/pwabuilder/Frontend/src/script/components/share-card.ts @@ -9,7 +9,6 @@ import '@awesome.me/webawesome/dist/components/dialog/dialog.js'; @customElement('share-card') export class ShareCard extends LitElement { - @property() preventClosing = false; @property() manifestData = ""; @property() swData = ""; @property() enhancementsData = ""; @@ -106,15 +105,9 @@ export class ShareCard extends LitElement { dialog!.open = false; } - handleRequestClose(e: Event){ - if (this.preventClosing) { - e.preventDefault(); - } - } - render() { return html` - this.setup()} @wa-hide=${() => this.hideDialog()}> + this.setup()} @wa-hide=${() => this.hideDialog()}>
diff --git a/apps/pwabuilder/Frontend/src/script/components/sw-selector.ts b/apps/pwabuilder/Frontend/src/script/components/sw-selector.ts index acd13e702..a9f996e25 100644 --- a/apps/pwabuilder/Frontend/src/script/components/sw-selector.ts +++ b/apps/pwabuilder/Frontend/src/script/components/sw-selector.ts @@ -28,7 +28,6 @@ export class SWSelector extends LitElement { if(e.target === dialog){ dialog!.open = false; recordPWABuilderProcessStep("sw_selector_closed", AnalyticsBehavior.ProcessCheckpoint); - document.body.style.height = "unset"; } } @@ -63,7 +62,7 @@ export class SWSelector extends LitElement { render() { return html` - document.body.style.height = "100vh"} @wa-hide=${(e: any) => this.hideDialog(e)}> + this.hideDialog(e)}>

Download a Service Worker

Download one of our pre-built Service Workers package that utilize Workbox to make building your offline experience easy.

diff --git a/apps/pwabuilder/Frontend/src/script/components/test-publish-pane.ts b/apps/pwabuilder/Frontend/src/script/components/test-publish-pane.ts index 390d96960..5f138daf1 100644 --- a/apps/pwabuilder/Frontend/src/script/components/test-publish-pane.ts +++ b/apps/pwabuilder/Frontend/src/script/components/test-publish-pane.ts @@ -235,13 +235,12 @@ export class TestPublishPane extends LitElement { this.generating = false; dialog!.open = false; recordPWABuilderProcessStep("test_publish_pane_closed", AnalyticsBehavior.ProcessCheckpoint); - document.body.style.height = "unset"; } } render() { return html` - document.body.style.height = "100vh"} @wa-hide=${(e: any) => this.hideDialog(e)}> + this.hideDialog(e)}>
diff --git a/apps/pwabuilder/Frontend/src/script/pages/app-report.ts b/apps/pwabuilder/Frontend/src/script/pages/app-report.ts index e48be4b84..79f40218e 100644 --- a/apps/pwabuilder/Frontend/src/script/pages/app-report.ts +++ b/apps/pwabuilder/Frontend/src/script/pages/app-report.ts @@ -1132,7 +1132,7 @@ export class AppReport extends LitElement {
- { this.showRetestConfirmationModal = false; this.readDenied = false; }} without-header> + { this.showRetestConfirmationModal = false; this.readDenied = false; }} without-header> ${this.renderReadDialog()} @@ -1396,7 +1396,7 @@ export class AppReport extends LitElement { } return html` - +

Logs @@ -1422,7 +1422,7 @@ export class AppReport extends LitElement { const errorInfo = `${this.analysis.url} failed due to an internal error.\r\n\r\n> ${this.analysis.error}\r\n\r\nId: ${this.analysis.id}\r\n\r\nLogs:\r\n> ${this.analysis.logs.join("\r\n")}`; const bugLink = `https://github.com/pwa-builder/pwabuilder/issues/new?title=Analysis%20Failed&labels=bug%20:bug:&body=${encodeURIComponent(errorInfo.substring(0, 4000))}`; return html` - +

😵 Oh no, PWABuilder was unable to analyze your web app due to an error.

diff --git a/apps/pwabuilder/Frontend/src/script/pages/powerplatform-publish.ts b/apps/pwabuilder/Frontend/src/script/pages/powerplatform-publish.ts index f0cb06734..194a96305 100644 --- a/apps/pwabuilder/Frontend/src/script/pages/powerplatform-publish.ts +++ b/apps/pwabuilder/Frontend/src/script/pages/powerplatform-publish.ts @@ -53,7 +53,7 @@ export class AppReport extends LitElement {

- + `; } } diff --git a/apps/pwabuilder/Frontend/src/script/utils/dom-utils.ts b/apps/pwabuilder/Frontend/src/script/utils/dom-utils.ts deleted file mode 100644 index 189ab7b42..000000000 --- a/apps/pwabuilder/Frontend/src/script/utils/dom-utils.ts +++ /dev/null @@ -1,7 +0,0 @@ -export function turnOffScroll() { - document.documentElement.style.overflowY = 'hidden'; -} - -export function turnOnScroll() { - document.documentElement.style.overflowY = 'initial'; -} diff --git a/apps/pwabuilder/Frontend/tests/packaging.spec.ts b/apps/pwabuilder/Frontend/tests/packaging.spec.ts index 07b5bae82..3036dcfb0 100644 --- a/apps/pwabuilder/Frontend/tests/packaging.spec.ts +++ b/apps/pwabuilder/Frontend/tests/packaging.spec.ts @@ -170,8 +170,8 @@ test('Package for Stores dialog locks scrolling and closes on backdrop click', a }).toBe(true); await expect.poll(async () => { - return page.evaluate(() => document.documentElement.style.overflowY); - }).toBe('hidden'); + return page.evaluate(() => document.documentElement.classList.contains('wa-scroll-lock')); + }).toBe(true); await page.mouse.wheel(0, 500); await expect.poll(async () => { @@ -193,6 +193,6 @@ test('Package for Stores dialog locks scrolling and closes on backdrop click', a }).toBe(false); await expect.poll(async () => { - return page.evaluate(() => document.documentElement.style.overflowY); - }).toBe('initial'); + return page.evaluate(() => document.documentElement.classList.contains('wa-scroll-lock')); + }).toBe(false); }); From 9da6635da29867a56144f07b151281d976fb0d90 Mon Sep 17 00:00:00 2001 From: Judah Gabriel Himango Date: Wed, 8 Jul 2026 16:33:42 -0700 Subject: [PATCH 4/4] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- apps/pwabuilder/Frontend/tests/packaging.spec.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/pwabuilder/Frontend/tests/packaging.spec.ts b/apps/pwabuilder/Frontend/tests/packaging.spec.ts index 40ce7c3ff..7a279828d 100644 --- a/apps/pwabuilder/Frontend/tests/packaging.spec.ts +++ b/apps/pwabuilder/Frontend/tests/packaging.spec.ts @@ -175,9 +175,9 @@ test('Package for Stores dialog locks scrolling and closes on backdrop click', a await page.mouse.wheel(0, 500); await expect.poll(async () => { - return page.evaluate(() => window.scrollY); - }).toBe(initialScrollPosition); - + const currentScrollY = await page.evaluate(() => window.scrollY); + return Math.abs(currentScrollY - initialScrollPosition); + }).toBeLessThan(2); await page.mouse.click(20, 20); await expect.poll(async () => {