From 1fdf47b81985b57c5d004bbd9b0b68310779ecaf Mon Sep 17 00:00:00 2001 From: Rajdeep Chandra Date: Tue, 5 Aug 2025 14:01:30 +0530 Subject: [PATCH 1/9] fix(overlay): added allowOutsideClick property to dialog show for page and modal overlay --- packages/overlay/src/Overlay.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/overlay/src/Overlay.ts b/packages/overlay/src/Overlay.ts index 8535f4db63..bd993883ab 100644 --- a/packages/overlay/src/Overlay.ts +++ b/packages/overlay/src/Overlay.ts @@ -552,6 +552,10 @@ export class Overlay extends ComputedOverlayBase { }, // disable escape key capture to close the overlay, the focus-trap library captures it otherwise escapeDeactivates: false, + // allow outside clicks to close the overlay + allowOutsideClick: (event: Event) => { + return !event.isTrusted; + }, }); if (this.type === 'modal' || this.type === 'page') { From 185906fed8cbca51588f570571264a1f79ed9f06 Mon Sep 17 00:00:00 2001 From: Rajdeep Chandra Date: Tue, 5 Aug 2025 14:02:04 +0530 Subject: [PATCH 2/9] chore: added a new story to demonstrate this behaviour --- packages/overlay/stories/overlay.stories.ts | 46 +++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/packages/overlay/stories/overlay.stories.ts b/packages/overlay/stories/overlay.stories.ts index 52031d0cef..f10905d4e2 100644 --- a/packages/overlay/stories/overlay.stories.ts +++ b/packages/overlay/stories/overlay.stories.ts @@ -1781,3 +1781,49 @@ export const WithInteractiveContent = (): TemplateResult => { `; }; + +export const RegisterClickOutside = (): TemplateResult => { + const handleClickOutside = (): void => { + const iframe = document.createElement('iframe'); + iframe.name = 'download-iframe'; + iframe.style.display = 'none'; + document.body.appendChild(iframe); + + const link = document.createElement('a'); + document.body.appendChild(link); + + const handleLinkClick = (event: Event): void => { + event.stopPropagation(); + document.body.removeChild(link); + document.body.removeChild(iframe); + console.log('Registered click outside the overlay'); + }; + + link.addEventListener('click', handleLinkClick, { once: true }); + link.click(); + }; + + return html` + + Open Overlay + + +
+ Example click outside functionality within an overlay +
+ + Click outside the overlay + +
+
+
+ `; +}; + +RegisterClickOutside.swc_vrt = { + skip: true, +}; From dc2e19ce40d2f602e94d3308d1eca55650bfb313 Mon Sep 17 00:00:00 2001 From: Rajdeep Chandra Date: Tue, 5 Aug 2025 14:03:25 +0530 Subject: [PATCH 3/9] chore: added test --- packages/overlay/test/overlay.test.ts | 87 +++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/packages/overlay/test/overlay.test.ts b/packages/overlay/test/overlay.test.ts index 11c13b2ece..b1ccac7500 100644 --- a/packages/overlay/test/overlay.test.ts +++ b/packages/overlay/test/overlay.test.ts @@ -1195,3 +1195,90 @@ describe('Overlay should correctly trap focus', () => { expect(document.activeElement).to.equal(input); }); }); + +it('allows programmatic clicks outside overlay to register after user interactions', async () => { + const el = await fixture(html` +
+ Open Overlay + + +
+ Overlay with interactive content +
+ + Interactive Button + + +
+
+
+ `); + + const trigger = el.querySelector('#interaction-trigger') as HTMLElement; + const overlay = el.querySelector('sp-overlay') as Overlay; + + await elementUpdated(overlay); + + // Create an element outside the overlay for testing clicks + const outsideElement = document.createElement('div'); + outsideElement.id = 'outside-element'; + outsideElement.style.cssText = + 'position: fixed; top: 10px; right: 10px; width: 100px; height: 100px; background: red; z-index: 1;'; + document.body.appendChild(outsideElement); + + // Open the overlay + const opened = oneEvent(overlay, 'sp-opened'); + trigger.click(); + await opened; + + // Interact with elements inside the overlay + const insideButton = overlay.querySelector( + '#interactive-button' + ) as HTMLElement; + const insideInput = overlay.querySelector( + '#interactive-input' + ) as HTMLInputElement; + + // Click inside button + insideButton.click(); + await nextFrame(); + + // Focus and type in input + insideInput.focus(); + await sendKeys({ + type: 'test text', + }); + await nextFrame(); + + // Verify overlay is still open after interactions + expect(overlay.open).to.be.true; + + // Test that clicking outside the overlay still registers and closes it + const closedEvent = oneEvent(overlay, 'sp-closed'); + + // Click outside the overlay + await sendMouse({ + steps: [ + { + type: 'click', + position: [window.innerWidth - 50, 50], // Click in top-right corner + }, + ], + }); + + await closedEvent; + + // Verify overlay is now closed + expect(overlay.open).to.be.false; + + // Clean up + document.body.removeChild(outsideElement); +}); From cdc864bca9aefb1f0ad64154ad2594e31642c65c Mon Sep 17 00:00:00 2001 From: Rajdeep Chandra Date: Tue, 5 Aug 2025 14:26:10 +0530 Subject: [PATCH 4/9] chore: updated readme --- packages/overlay/README.md | 68 ++++++++++++++++++++++++++++++++------ 1 file changed, 58 insertions(+), 10 deletions(-) diff --git a/packages/overlay/README.md b/packages/overlay/README.md index 78162fb6b7..0575f8d5ab 100644 --- a/packages/overlay/README.md +++ b/packages/overlay/README.md @@ -269,7 +269,7 @@ Some Overlays will always be passed focus (e.g. modal or page Overlays). When th The `trigger` option accepts an `HTMLElement` or a `VirtualTrigger` from which to position the Overlay. -- You can import the `VirtualTrigger` class from the overlay package to create a virtual trigger that can be used to position an Overlay. This is useful when you want to position an Overlay relative to a point on the screen that is not an element in the DOM, like the mouse cursor. +- You can import the `VirtualTrigger` class from the overlay package to create a virtual trigger that can be used to position an Overlay. This is useful when you want to position an Overlay relative to a point on the screen that is not an element in the DOM, like the mouse cursor. The `type` of an Overlay outlines a number of things about the interaction model within which it works: @@ -408,8 +408,8 @@ The `overlay` value in this case will hold a reference to the actual `` element have successfully dispatched their `transitionend` or `transitioncancel` event. Keep in mind the following: -- `transition*` events bubble; this means that while transition events on light DOM content of those direct children will be heard, those events will not be taken into account -- `transition*` events are not composed; this means that transition events on shadow DOM content of the direct children will not propagate to a level in the DOM where they can be heard +- `transition*` events bubble; this means that while transition events on light DOM content of those direct children will be heard, those events will not be taken into account +- `transition*` events are not composed; this means that transition events on shadow DOM content of the direct children will not propagate to a level in the DOM where they can be heard This means that in both cases, if the transition is meant to be a part of the opening or closing of the overlay in question you will need to redispatch the `transitionrun`, `transitionend`, and `transitioncancel` events from that transition from the closest direct child of the ``. @@ -772,9 +772,9 @@ When nesting multiple overlays, it is important to ensure that the nested overla The overlay manages focus based on its type: -- For `modal` and `page` types, focus is always trapped within the overlay -- For `auto` and `manual` types, focus behavior is controlled by the `receives-focus` attribute -- For `hint` type, focus remains on the trigger element +- For `modal` and `page` types, focus is always trapped within the overlay +- For `auto` and `manual` types, focus behavior is controlled by the `receives-focus` attribute +- For `hint` type, focus remains on the trigger element Example of proper focus management: @@ -811,6 +811,54 @@ Example of proper focus management: ``` +#### External click handling + +The overlay uses a focus trap for `modal` and `page` type overlays that includes special handling for external clicks. The `allowOutsideClick` configuration allows programmatic clicks (non-trusted events) to close the overlay while preventing user-initiated clicks from doing so. + +This means: + +- **Programmatic clicks** (e.g., `element.click()` in JavaScript) will close the overlay +- **User clicks** (trusted events from mouse/touch interaction) will not close the overlay +- This behavior is automatic for `modal` and `page` type overlays + +Example of programmatic click behavior: + +```javascript +// This will close the overlay +const outsideElement = document.createElement('button'); +outsideElement.click(); // Programmatic click - will close overlay + +// User clicking outside will NOT close the overlay +// (unless the overlay type is 'auto' or 'manual') +``` + +Example of external click registration: + +```javascript +// Programmatic click outside will close the overlay +function closeOverlayProgrammatically() { + const outsideElement = document.createElement('div'); + outsideElement.style.position = 'fixed'; + outsideElement.style.top = '0'; + outsideElement.style.left = '0'; + document.body.appendChild(outsideElement); + + outsideElement.click(); // Programmatic click - will close overlay + + document.body.removeChild(outsideElement); +} + +// User clicks outside will NOT close the overlay (default modal behavior) +// This is handled automatically by the overlay's focus trap +// Users clicking outside modal overlays will not close them +``` + +This design ensures that: + +- Users can't accidentally close important modal dialogs by clicking outside +- Developers can programmatically close overlays when needed +- The overlay maintains proper focus management and accessibility + #### Keyboard navigation @@ -840,10 +888,10 @@ Example of proper focus management: #### Screen reader considerations -- Use `aria-haspopup` on trigger elements to indicate the type of overlay -- Provide descriptive labels using `aria-label` or `aria-labelledby` -- Use proper heading structure within overlays -- Ensure error messages are announced using `aria-live` +- Use `aria-haspopup` on trigger elements to indicate the type of overlay +- Provide descriptive labels using `aria-label` or `aria-labelledby` +- Use proper heading structure within overlays +- Ensure error messages are announced using `aria-live` Example of a tooltip with proper screen reader support: From 82653adb5951d162736696820485e1384a3e6b4e Mon Sep 17 00:00:00 2001 From: Rajdeep Chandra Date: Tue, 5 Aug 2025 14:33:28 +0530 Subject: [PATCH 5/9] chore: added changeset --- .changeset/solid-points-talk.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/solid-points-talk.md diff --git a/.changeset/solid-points-talk.md b/.changeset/solid-points-talk.md new file mode 100644 index 0000000000..d24bcc9b39 --- /dev/null +++ b/.changeset/solid-points-talk.md @@ -0,0 +1,5 @@ +--- +'@spectrum-web-components/overlay': minor +--- + +**Fixed** : external click registration behavior in the `sp-overlay` component. Programmatic clicks on elements outside of modal overlays now properly register and close the overlay, while user-initiated clicks are prevented from doing so. From 424195d8e353a08c5c7212290d7b976521a76095 Mon Sep 17 00:00:00 2001 From: Rajdeep Chandra Date: Thu, 14 Aug 2025 18:28:27 +0530 Subject: [PATCH 6/9] chore: revert change to allow programmatic click hindering a11y contract --- packages/overlay/src/Overlay.ts | 4 - packages/overlay/stories/overlay.stories.ts | 46 ----------- packages/overlay/test/overlay.test.ts | 87 --------------------- 3 files changed, 137 deletions(-) diff --git a/packages/overlay/src/Overlay.ts b/packages/overlay/src/Overlay.ts index bd993883ab..8535f4db63 100644 --- a/packages/overlay/src/Overlay.ts +++ b/packages/overlay/src/Overlay.ts @@ -552,10 +552,6 @@ export class Overlay extends ComputedOverlayBase { }, // disable escape key capture to close the overlay, the focus-trap library captures it otherwise escapeDeactivates: false, - // allow outside clicks to close the overlay - allowOutsideClick: (event: Event) => { - return !event.isTrusted; - }, }); if (this.type === 'modal' || this.type === 'page') { diff --git a/packages/overlay/stories/overlay.stories.ts b/packages/overlay/stories/overlay.stories.ts index f10905d4e2..52031d0cef 100644 --- a/packages/overlay/stories/overlay.stories.ts +++ b/packages/overlay/stories/overlay.stories.ts @@ -1781,49 +1781,3 @@ export const WithInteractiveContent = (): TemplateResult => { `; }; - -export const RegisterClickOutside = (): TemplateResult => { - const handleClickOutside = (): void => { - const iframe = document.createElement('iframe'); - iframe.name = 'download-iframe'; - iframe.style.display = 'none'; - document.body.appendChild(iframe); - - const link = document.createElement('a'); - document.body.appendChild(link); - - const handleLinkClick = (event: Event): void => { - event.stopPropagation(); - document.body.removeChild(link); - document.body.removeChild(iframe); - console.log('Registered click outside the overlay'); - }; - - link.addEventListener('click', handleLinkClick, { once: true }); - link.click(); - }; - - return html` - - Open Overlay - - -
- Example click outside functionality within an overlay -
- - Click outside the overlay - -
-
-
- `; -}; - -RegisterClickOutside.swc_vrt = { - skip: true, -}; diff --git a/packages/overlay/test/overlay.test.ts b/packages/overlay/test/overlay.test.ts index b1ccac7500..11c13b2ece 100644 --- a/packages/overlay/test/overlay.test.ts +++ b/packages/overlay/test/overlay.test.ts @@ -1195,90 +1195,3 @@ describe('Overlay should correctly trap focus', () => { expect(document.activeElement).to.equal(input); }); }); - -it('allows programmatic clicks outside overlay to register after user interactions', async () => { - const el = await fixture(html` -
- Open Overlay - - -
- Overlay with interactive content -
- - Interactive Button - - -
-
-
- `); - - const trigger = el.querySelector('#interaction-trigger') as HTMLElement; - const overlay = el.querySelector('sp-overlay') as Overlay; - - await elementUpdated(overlay); - - // Create an element outside the overlay for testing clicks - const outsideElement = document.createElement('div'); - outsideElement.id = 'outside-element'; - outsideElement.style.cssText = - 'position: fixed; top: 10px; right: 10px; width: 100px; height: 100px; background: red; z-index: 1;'; - document.body.appendChild(outsideElement); - - // Open the overlay - const opened = oneEvent(overlay, 'sp-opened'); - trigger.click(); - await opened; - - // Interact with elements inside the overlay - const insideButton = overlay.querySelector( - '#interactive-button' - ) as HTMLElement; - const insideInput = overlay.querySelector( - '#interactive-input' - ) as HTMLInputElement; - - // Click inside button - insideButton.click(); - await nextFrame(); - - // Focus and type in input - insideInput.focus(); - await sendKeys({ - type: 'test text', - }); - await nextFrame(); - - // Verify overlay is still open after interactions - expect(overlay.open).to.be.true; - - // Test that clicking outside the overlay still registers and closes it - const closedEvent = oneEvent(overlay, 'sp-closed'); - - // Click outside the overlay - await sendMouse({ - steps: [ - { - type: 'click', - position: [window.innerWidth - 50, 50], // Click in top-right corner - }, - ], - }); - - await closedEvent; - - // Verify overlay is now closed - expect(overlay.open).to.be.false; - - // Clean up - document.body.removeChild(outsideElement); -}); From 8ad244a8396972fdcb24b6f52a77b03a9ec86f23 Mon Sep 17 00:00:00 2001 From: Rajdeep Chandra Date: Thu, 14 Aug 2025 18:29:24 +0530 Subject: [PATCH 7/9] docs: modal type should not allow external clicks docs update --- packages/overlay/README.md | 52 +++----------------------------------- 1 file changed, 4 insertions(+), 48 deletions(-) diff --git a/packages/overlay/README.md b/packages/overlay/README.md index 0575f8d5ab..06116e54fd 100644 --- a/packages/overlay/README.md +++ b/packages/overlay/README.md @@ -279,6 +279,8 @@ The `type` of an Overlay outlines a number of things about the interaction model `'modal'` Overlays create a modal context that traps focus within the content and prevents interaction with the rest of the page. The overlay manages focus trapping and accessibility features like `aria-modal="true"` to ensure proper screen reader behavior. +**Accessibility behavior:** Modal overlays implement strict focus trapping and prevent outside interactions for accessibility compliance. These overlays create a modal context that precludes usage of other content on the page, ensuring all interactive elements are descendants of the overlay. Clicking outside the modal will not close it, maintaining the modal context as required by ARIA specifications. + They should be used when you need to ensure that the user has interacted with the content of the Overlay before continuing with their work. This is commonly used for dialogs that require a user to confirm or cancel an action before continuing. ```html @@ -310,6 +312,8 @@ They should be used when you need to ensure that the user has interacted with th `'page'` Overlays behave similarly to `'modal'` Overlays by creating a modal context and trapping focus, but they will not be allowed to close via the "light dismiss" algorithm (e.g. the Escape key). +**Accessibility behavior:** Page overlays implement strict focus trapping and prevent outside interactions for accessibility compliance, similar to modal overlays. These overlays create a modal context that precludes usage of other content on the page, ensuring all interactive elements are descendants of the overlay. Clicking outside the page overlay will not close it, maintaining the modal context as required by ARIA specifications. + A page overlay could be used for a full-screen menu on a mobile website. When the user clicks on the menu button, the entire screen is covered with the menu options. ```html @@ -811,54 +815,6 @@ Example of proper focus management: ``` -#### External click handling - -The overlay uses a focus trap for `modal` and `page` type overlays that includes special handling for external clicks. The `allowOutsideClick` configuration allows programmatic clicks (non-trusted events) to close the overlay while preventing user-initiated clicks from doing so. - -This means: - -- **Programmatic clicks** (e.g., `element.click()` in JavaScript) will close the overlay -- **User clicks** (trusted events from mouse/touch interaction) will not close the overlay -- This behavior is automatic for `modal` and `page` type overlays - -Example of programmatic click behavior: - -```javascript -// This will close the overlay -const outsideElement = document.createElement('button'); -outsideElement.click(); // Programmatic click - will close overlay - -// User clicking outside will NOT close the overlay -// (unless the overlay type is 'auto' or 'manual') -``` - -Example of external click registration: - -```javascript -// Programmatic click outside will close the overlay -function closeOverlayProgrammatically() { - const outsideElement = document.createElement('div'); - outsideElement.style.position = 'fixed'; - outsideElement.style.top = '0'; - outsideElement.style.left = '0'; - document.body.appendChild(outsideElement); - - outsideElement.click(); // Programmatic click - will close overlay - - document.body.removeChild(outsideElement); -} - -// User clicks outside will NOT close the overlay (default modal behavior) -// This is handled automatically by the overlay's focus trap -// Users clicking outside modal overlays will not close them -``` - -This design ensures that: - -- Users can't accidentally close important modal dialogs by clicking outside -- Developers can programmatically close overlays when needed -- The overlay maintains proper focus management and accessibility - #### Keyboard navigation From 25937df49d4d8e9cf40907be3eedc730a3f666db Mon Sep 17 00:00:00 2001 From: Rajdeep Chandra Date: Tue, 19 Aug 2025 12:34:13 +0530 Subject: [PATCH 8/9] fix(overlay): allow-outside-click added as deprecation --- .changeset/fluffy-ads-send.md | 9 +++++++ packages/overlay/README.md | 18 ++++++++++++++ packages/overlay/src/Overlay.ts | 32 +++++++++++++++++++++++- packages/overlay/test/overlay.test.ts | 35 +++++++++++++++++++++++++++ 4 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 .changeset/fluffy-ads-send.md diff --git a/.changeset/fluffy-ads-send.md b/.changeset/fluffy-ads-send.md new file mode 100644 index 0000000000..82b1c84a72 --- /dev/null +++ b/.changeset/fluffy-ads-send.md @@ -0,0 +1,9 @@ +--- +'@spectrum-web-components/overlay': minor +--- + +Added `allow-outside-click` property to `` with deprecation notice. This property allows clicks outside the overlay to close it, but is not recommended for accessibility reasons and will be removed in a future version. + +This property is being added as deprecated to support the fallback for `showModal()` which was removed as part of performance optimization. We will no longer support outside clicks for modal overlays as they violate accessibility guidelines. + +**Breaking Change**: The property defaults to `false` and shows deprecation warnings when used. Consider using explicit close buttons or modal/page overlay types instead for better accessibility. diff --git a/packages/overlay/README.md b/packages/overlay/README.md index 06116e54fd..432ad22a0e 100644 --- a/packages/overlay/README.md +++ b/packages/overlay/README.md @@ -536,6 +536,7 @@ This means that in both cases, if the transition is meant to be a part of the op .triggerElement=${HTMLElement} .triggerInteraction=${'click' | 'longpress' | 'hover'} type=${'auto' | 'hint' | 'manual' | 'modal' | 'page'} + ?allow-outside-click=${boolean} > ``` @@ -577,6 +578,23 @@ Common in `modal`/`page` overlays for full-screen content +##### Deprecated Properties + +> **⚠️ Deprecation Notice**: The `allow-outside-click` property is deprecated and will be removed in a future version. + +The `allow-outside-click` property allows clicks outside the overlay to close it. **We do not recommend using this property for accessibility reasons** as it can cause unexpected behavior and accessibility issues. When set to `true`, it configures the focus trap to allow outside clicks, which may interfere with proper focus management and user expectations. + +```html + + + +

This overlay can be closed by clicking outside

+
+
+``` + +**Alternative approaches**: Instead of using `allow-outside-click`, consider implementing explicit close buttons or using the `type="modal"` or `type="page"` overlay types which provide better accessibility and user experience. + #### Styling `` element will use the `` element or `popover` attribute to project your content onto the top-layer of the browser, without being moved in the DOM tree. That means that you can style your overlay content with whatever techniques you are already leveraging to style the content that doesn't get overlaid. This means standard CSS selectors, CSS Custom Properties, and CSS Parts applied in your parent context will always apply to your overlaid content. diff --git a/packages/overlay/src/Overlay.ts b/packages/overlay/src/Overlay.ts index 8535f4db63..f1ec3e07f2 100644 --- a/packages/overlay/src/Overlay.ts +++ b/packages/overlay/src/Overlay.ts @@ -79,6 +79,7 @@ if (!browserSupportsPopover) { * @attr {string} receives-focus - How focus should be handled ('true'|'false'|'auto') * @attr {boolean} delayed - Whether the overlay should wait for a warm-up period before opening * @attr {boolean} open - Whether the overlay is currently open + * @attr {boolean} allow-outside-click - @deprecated Whether clicks outside the overlay should close it (not recommended for accessibility) */ export class Overlay extends ComputedOverlayBase { static override styles = [styles]; @@ -289,6 +290,18 @@ export class Overlay extends ComputedOverlayBase { @property({ attribute: 'receives-focus' }) override receivesFocus: 'true' | 'false' | 'auto' = 'auto'; + /** + * @deprecated This property will be removed in a future version. + * We do not recommend using this property for accessibility reasons. + * It allows clicks outside the overlay to close it, which can cause + * unexpected behavior and accessibility issues. + * + * @type {boolean} + * @default false + */ + @property({ type: Boolean, attribute: 'allow-outside-click' }) + allowOutsideClick = false; + /** * A reference to the slot element within the overlay. * @@ -495,7 +508,6 @@ export class Overlay extends ComputedOverlayBase { * * This method handles the necessary steps to open the popover, including managing delays, * ensuring the popover is in the DOM, making transitions, and applying focus. - * * @protected * @override * @returns {Promise} A promise that resolves when the popover has been fully opened. @@ -552,6 +564,7 @@ export class Overlay extends ComputedOverlayBase { }, // disable escape key capture to close the overlay, the focus-trap library captures it otherwise escapeDeactivates: false, + allowOutsideClick: this.allowOutsideClick, }); if (this.type === 'modal' || this.type === 'page') { @@ -972,6 +985,23 @@ export class Overlay extends ComputedOverlayBase { ); } + // Warn about deprecated allowOutsideClick property + if (changes.has('allowOutsideClick') && this.allowOutsideClick) { + if (window.__swc?.DEBUG) { + window.__swc.warn( + this, + `The "allow-outside-click" attribute on <${this.localName}> has been deprecated and will be removed in a future release. We do not recommend using this attribute for accessibility reasons. It allows clicks outside the overlay to close it, which can cause unexpected behavior and accessibility issues.`, + 'https://opensource.adobe.com/spectrum-web-components/components/overlay/', + { level: 'deprecation' } + ); + } else { + // Fallback for testing environments or when SWC is not available + console.warn( + `[${this.localName}] The "allow-outside-click" attribute has been deprecated and will be removed in a future release. We do not recommend using this attribute for accessibility reasons. It allows clicks outside the overlay to close it, which can cause unexpected behavior and accessibility issues.` + ); + } + } + // Manage the open state if the 'open' property has changed. if (changes.has('open') && (this.hasUpdated || this.open)) { this.manageOpen(changes.get('open')); diff --git a/packages/overlay/test/overlay.test.ts b/packages/overlay/test/overlay.test.ts index 11c13b2ece..5469669539 100644 --- a/packages/overlay/test/overlay.test.ts +++ b/packages/overlay/test/overlay.test.ts @@ -1195,3 +1195,38 @@ describe('Overlay should correctly trap focus', () => { expect(document.activeElement).to.equal(input); }); }); + +describe('Overlay - Deprecated Properties', () => { + it('should support allowOutsideClick property with deprecation warning', async () => { + const consoleSpy = spy(console, 'warn'); + + const el = await fixture(html` +
+ Open Overlay + + +

Overlay content

+
+
+
+ `); + + const overlay = el.querySelector('sp-overlay') as Overlay; + await elementUpdated(overlay); + + // Verify the property is set correctly + expect(overlay.allowOutsideClick).to.be.true; + expect(overlay.hasAttribute('allow-outside-click')).to.be.true; + + // Verify the deprecation warning is shown (either via SWC or console.warn fallback) + expect(consoleSpy.calledOnce).to.be.true; + expect(consoleSpy.firstCall.args[0]).to.include('allow-outside-click'); + expect(consoleSpy.firstCall.args[0]).to.include('deprecated'); + + consoleSpy.restore(); + }); +}); From df51141eee5394f84a7d277a4d79bdbd46a36065 Mon Sep 17 00:00:00 2001 From: Rajdeep Chandra Date: Tue, 19 Aug 2025 12:52:48 +0530 Subject: [PATCH 9/9] fix(overlay): removed redundant docs --- packages/overlay/README.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/overlay/README.md b/packages/overlay/README.md index 432ad22a0e..957ff51fc2 100644 --- a/packages/overlay/README.md +++ b/packages/overlay/README.md @@ -279,8 +279,6 @@ The `type` of an Overlay outlines a number of things about the interaction model `'modal'` Overlays create a modal context that traps focus within the content and prevents interaction with the rest of the page. The overlay manages focus trapping and accessibility features like `aria-modal="true"` to ensure proper screen reader behavior. -**Accessibility behavior:** Modal overlays implement strict focus trapping and prevent outside interactions for accessibility compliance. These overlays create a modal context that precludes usage of other content on the page, ensuring all interactive elements are descendants of the overlay. Clicking outside the modal will not close it, maintaining the modal context as required by ARIA specifications. - They should be used when you need to ensure that the user has interacted with the content of the Overlay before continuing with their work. This is commonly used for dialogs that require a user to confirm or cancel an action before continuing. ```html @@ -312,8 +310,6 @@ They should be used when you need to ensure that the user has interacted with th `'page'` Overlays behave similarly to `'modal'` Overlays by creating a modal context and trapping focus, but they will not be allowed to close via the "light dismiss" algorithm (e.g. the Escape key). -**Accessibility behavior:** Page overlays implement strict focus trapping and prevent outside interactions for accessibility compliance, similar to modal overlays. These overlays create a modal context that precludes usage of other content on the page, ensuring all interactive elements are descendants of the overlay. Clicking outside the page overlay will not close it, maintaining the modal context as required by ARIA specifications. - A page overlay could be used for a full-screen menu on a mobile website. When the user clicks on the menu button, the entire screen is covered with the menu options. ```html