diff --git a/addon/components/dialog.hbs b/addon/components/dialog.hbs index bbf4d2e..fa670ca 100644 --- a/addon/components/dialog.hbs +++ b/addon/components/dialog.hbs @@ -7,9 +7,12 @@ aria-modal='true' ...attributes {{headlessui-focus-trap - focusTrapOptions=(hash initialFocus=@initialFocus) + focusTrapOptions=(hash + initialFocus=@initialFocus + allowOutsideClick=this.allowOutsideClick + setReturnFocus=this.setReturnFocus + ) }} - {{click-outside this.onClose event='mouseup'}} {{this.handleEscapeKey @isOpen this.onClose}} {{did-insert (fn this.dialogStackProvider.push this)}} {{will-destroy (fn this.dialogStackProvider.remove this)}} @@ -17,13 +20,13 @@ {{yield (hash isOpen=@isOpen - onClose=@onClose + onClose=this.onClose Overlay=(component 'dialog/-overlay' guid=this.overlayGuid dialogGuid=this.guid isOpen=@isOpen - onClose=@onClose + onClose=this.onClose ) Title=(component 'dialog/-title' diff --git a/addon/components/dialog.ts b/addon/components/dialog.ts index bc7baf4..56be143 100644 --- a/addon/components/dialog.ts +++ b/addon/components/dialog.ts @@ -30,6 +30,7 @@ export default class DialogComponent extends Component { guid = `${guidFor(this)}-headlessui-dialog`; $portalRoot = getPortalRoot(); + outsideClickedElement: HTMLElement | null = null; handleEscapeKey = modifier( (_element, [isOpen, onClose]: [boolean, () => void]) => { @@ -103,6 +104,24 @@ export default class DialogComponent extends Component { return `${this.guid}-description`; } + @action + setReturnFocus(trigger: HTMLElement) { + return this.outsideClickedElement ? this.outsideClickedElement : trigger; + } + + @action + allowOutsideClick(e: MouseEvent) { + let target = e.target as HTMLElement; + + if (target && target.tagName !== 'BODY') { + this.outsideClickedElement = target; + } + + this.onClose(); + + return true; + } + @action onClose() { if (this.dialogStackProvider.hasOpenChild(this)) return; diff --git a/package.json b/package.json index 277df09..dfe0efb 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,6 @@ "ember-cli-babel": "^7.26.3", "ember-cli-htmlbars": "^5.7.1", "ember-cli-typescript": "^4.2.1", - "ember-click-outside-modifier": "^2.0.0", "ember-concurrency": "^2.1.2", "ember-element-helper": "^0.5.5", "ember-set-helper": "^2.0.1", diff --git a/tests/integration/components/dialog-test.js b/tests/integration/components/dialog-test.js index 62d581f..aabe51f 100644 --- a/tests/integration/components/dialog-test.js +++ b/tests/integration/components/dialog-test.js @@ -429,13 +429,33 @@ module('Integration | Component | ', function (hooks) { assertDialog({ state: DialogState.InvisibleUnmounted }); - assertActiveElement(getByText('Trigger')); + await assertActiveElement(getByText('Trigger')); }); - todo( - 'it should be possible to close the dialog, and keep focus on the focusable element', - async function () {} - ); + test('it should be possible to close the dialog, and keep focus on the focusable element', async function () { + this.set('isOpen', false); + + await render(hbs` + + + + Contents +
+
+ `); + + await click(getByText('Trigger')); + + assertDialog({ state: DialogState.Visible }); + + await click(getByText('Hello')); + + assertDialog({ state: DialogState.InvisibleUnmounted }); + + await assertActiveElement(getByText('Hello')); + }); test('it should stop propagating click events when clicking on the Dialog.Overlay', async function (assert) { this.set('isOpen', true); @@ -792,11 +812,15 @@ module('Integration | Component | ', function (hooks) { //close the top most dialog with ${strategy} await action(); - assert.equal(getDialogs(), 0, 'Verify that we have 0 open dialogs'); + assert.equal( + getDialogs().length, + 0, + 'Verify that we have 0 open dialogs' + ); await assertActiveElement( getByText('Open 1'), - 'Verify that we have 1 open dialog' + 'Verify that the `Open 1` got focused again' ); } ); diff --git a/yarn.lock b/yarn.lock index 2a6f3c6..b2adc19 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6218,15 +6218,6 @@ ember-cli@~3.27.0: workerpool "^6.0.3" yam "^1.0.0" -ember-click-outside-modifier@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ember-click-outside-modifier/-/ember-click-outside-modifier-2.0.0.tgz#8417a44db8bafef87e08f3614ad809ad1a6020e1" - integrity sha512-5FkTsSiSoDh4wL0mqJ2niOZH3ykevcRdLxA2pgZ9JqCMpvMqAQon5valAA4mvW6HiP9lnwm+GR/WijtL0dsdcg== - dependencies: - ember-cli-babel "^7.26.6" - ember-cli-htmlbars "^5.7.1" - ember-modifier "^2.1.2" - ember-compatibility-helpers@^1.1.2, ember-compatibility-helpers@^1.2.0, ember-compatibility-helpers@^1.2.1, ember-compatibility-helpers@^1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/ember-compatibility-helpers/-/ember-compatibility-helpers-1.2.4.tgz#70e0fef7048969141626eed6006f3880df612cd1"