diff --git a/src/dialog/Dialog.ts b/src/dialog/Dialog.ts index 78b270aaf7..881c803b33 100644 --- a/src/dialog/Dialog.ts +++ b/src/dialog/Dialog.ts @@ -3,6 +3,8 @@ import { WidgetBase } from '@dojo/widget-core/WidgetBase'; import { ThemeableMixin, ThemeableProperties, theme } from '@dojo/widget-core/mixins/Themeable'; import { v } from '@dojo/widget-core/d'; import uuid from '@dojo/core/uuid'; +import { Keys } from '../common/util'; +import { createHandle } from '@dojo/core/lang'; import * as css from './styles/dialog.m.css'; import * as iconCss from '../common/styles/icons.m.css'; @@ -65,6 +67,22 @@ export default class Dialog extends DialogBase { !this.properties.modal && this._onCloseClick(); } + private _onKeyUp(event: KeyboardEvent) { + if (event.which === Keys.Escape) { + this._onCloseClick(); + } + } + + constructor() { + super(); + + const keyUpFunc = this._onKeyUp.bind(this); + document.addEventListener('keyup', keyUpFunc); + this.own(createHandle(() => { + document.removeEventListener('keyup', keyUpFunc); + })); + } + render(): DNode { const { closeable = true, @@ -82,7 +100,9 @@ export default class Dialog extends DialogBase { this._wasOpen = open; - return v('div', { classes: this.classes(css.root) }, open ? [ + return v('div', { + classes: this.classes(css.root) + }, open ? [ v('div', { classes: this.classes(underlay ? css.underlayVisible : null).fixed(css.underlay), enterAnimation: animations.fadeIn, diff --git a/src/dialog/tests/unit/Dialog.ts b/src/dialog/tests/unit/Dialog.ts index eae0cf6b4f..4315098f32 100644 --- a/src/dialog/tests/unit/Dialog.ts +++ b/src/dialog/tests/unit/Dialog.ts @@ -11,6 +11,7 @@ import Dialog, { DialogProperties } from '../../Dialog'; import * as css from '../../styles/dialog.m.css'; import * as iconCss from '../../../common/styles/icons.m.css'; import * as animations from '../../../common/styles/animations.m.css'; +import { Keys } from '../../../common/util'; const compareId = compareProperty((value: any) => { return typeof value === 'string'; @@ -207,6 +208,32 @@ registerSuite('Dialog', { selector: `.${css.underlay}` }); assert.isTrue(onRequestClose.called, 'onRequestClose is called when the underlay is clicked and modal is false'); + }, + + escapeKey() { + const onRequestClose = sinon.stub(); + + widget.setProperties({ + open: true, + onRequestClose + }); + widget.getRender(); + + widget.sendEvent('keyup', { + eventInit: { + which: Keys.Down + } + }); + + assert.isTrue(onRequestClose.notCalled); + + widget.sendEvent('keyup', { + eventInit: { + which: Keys.Escape + } + }); + + assert.isTrue(onRequestClose.calledOnce); } } });