diff --git a/.changeset/tidy-tigers-care.md b/.changeset/tidy-tigers-care.md new file mode 100644 index 00000000000..abb2ed58e13 --- /dev/null +++ b/.changeset/tidy-tigers-care.md @@ -0,0 +1,5 @@ +--- +"@hashicorp/design-system-components": patch +--- + +`Modal` - Reverted changes introduced in [#2846](https://github.com/hashicorp/design-system/pull/2846) and [#2902](https://github.com/hashicorp/design-system/pull/2902) related to the click behaviour outside the modal when dismissing is disabled diff --git a/packages/components/src/components/hds/modal/index.hbs b/packages/components/src/components/hds/modal/index.hbs index 7ddc96915d0..ea32f64eb5b 100644 --- a/packages/components/src/components/hds/modal/index.hbs +++ b/packages/components/src/components/hds/modal/index.hbs @@ -9,7 +9,7 @@ {{did-insert this.didInsert}} {{will-destroy this.willDestroyNode}} {{! @glint-expect-error - https://github.com/josemarluedke/ember-focus-trap/issues/86 }} - {{focus-trap isActive=this._isOpen focusTrapOptions=(hash onDeactivate=this.onDismiss)}} + {{focus-trap isActive=this._isOpen focusTrapOptions=(hash onDeactivate=this.onDismiss clickOutsideDeactivates=true)}} > <:header> {{yield diff --git a/packages/components/src/components/hds/modal/index.ts b/packages/components/src/components/hds/modal/index.ts index 9a2c8acb194..9374808c118 100644 --- a/packages/components/src/components/hds/modal/index.ts +++ b/packages/components/src/components/hds/modal/index.ts @@ -9,10 +9,8 @@ import { action } from '@ember/object'; import { assert } from '@ember/debug'; import { getElementId } from '../../../utils/hds-get-element-id.ts'; import { buildWaiter } from '@ember/test-waiters'; -import { registerDestructor } from '@ember/destroyable'; import type { WithBoundArgs } from '@glint/template'; -import type Owner from '@ember/owner'; import type { HdsModalSizes, HdsModalColors } from './types.ts'; import HdsDialogPrimitiveHeaderComponent from '../dialog-primitive/header.ts'; @@ -63,15 +61,6 @@ export default class HdsModal extends Component { private _element!: HTMLDialogElement; private _body!: HTMLElement; private _bodyInitialOverflowValue = ''; - private _clickHandler!: (event: MouseEvent) => void; - - constructor(owner: Owner, args: HdsModalSignature['Args']) { - super(owner, args); - - registerDestructor(this, (): void => { - document.removeEventListener('click', this._clickHandler, true); - }); - } get isDismissDisabled(): boolean { return this.args.isDismissDisabled ?? false; @@ -139,29 +128,6 @@ export default class HdsModal extends Component { } } else { this._isOpen = false; - - // Reset page `overflow` property - if (this._body) { - this._body.style.removeProperty('overflow'); - if (this._bodyInitialOverflowValue === '') { - if (this._body.style.length === 0) { - this._body.removeAttribute('style'); - } - } else { - this._body.style.setProperty( - 'overflow', - this._bodyInitialOverflowValue - ); - } - } - - // Return focus to a specific element (if provided) - if (this.args.returnFocusTo) { - const initiator = document.getElementById(this.args.returnFocusTo); - if (initiator) { - initiator.focus(); - } - } } } @@ -185,20 +151,6 @@ export default class HdsModal extends Component { if (!this._element.open) { this.open(); } - - this._clickHandler = (event: MouseEvent) => { - // check if the click is outside the modal and the modal is open - if (!this._element.contains(event.target as Node) && this._isOpen) { - if (!this.isDismissDisabled) { - void this.onDismiss(); - } - } - }; - - document.addEventListener('click', this._clickHandler, { - capture: true, - passive: false, - }); } @action @@ -233,6 +185,7 @@ export default class HdsModal extends Component { async onDismiss(): Promise { // allow ember test helpers to be aware of when the `close` event fires // when using `click` or other helpers from '@ember/test-helpers' + // Notice: this code will get stripped out in production builds (DEBUG evaluates to `true` in dev/test builds, but `false` in prod builds) if (this._element.open) { const token = waiter.beginAsync(); const listener = () => { @@ -244,5 +197,28 @@ export default class HdsModal extends Component { // Make modal dialog invisible using the native `close` method this._element.close(); + + // Reset page `overflow` property + if (this._body) { + this._body.style.removeProperty('overflow'); + if (this._bodyInitialOverflowValue === '') { + if (this._body.style.length === 0) { + this._body.removeAttribute('style'); + } + } else { + this._body.style.setProperty( + 'overflow', + this._bodyInitialOverflowValue + ); + } + } + + // Return focus to a specific element (if provided) + if (this.args.returnFocusTo) { + const initiator = document.getElementById(this.args.returnFocusTo); + if (initiator) { + initiator.focus(); + } + } } } diff --git a/showcase/tests/integration/components/hds/modal/index-test.js b/showcase/tests/integration/components/hds/modal/index-test.js index 91d5886a49b..3f4067bdc7a 100644 --- a/showcase/tests/integration/components/hds/modal/index-test.js +++ b/showcase/tests/integration/components/hds/modal/index-test.js @@ -169,27 +169,6 @@ module('Integration | Component | hds/modal/index', function (hooks) { assert.dom('#test-modal').isNotVisible(); }); - test('it should appropriately dismiss the modal when clicking outside the modal', async function (assert) { - this.set('isDismissDisabled', true); - await render( - hbs` - Title - - - - `, - ); - - await click('.hds-modal__overlay'); - assert.dom('#test-modal').isVisible(); - - // now let's check that the state is reset and it can be closed - this.set('isDismissDisabled', false); - await rerender(); - await click('.hds-modal__overlay'); - assert.dom('#test-modal').isNotVisible(); - }); - // ACCESSIBILITY test('it uses the title as name for the dialog', async function (assert) {