diff --git a/frontend/src/components/common/BaseDialog.vue b/frontend/src/components/common/BaseDialog.vue index ba0fe6a051..5bdef2ba62 100644 --- a/frontend/src/components/common/BaseDialog.vue +++ b/frontend/src/components/common/BaseDialog.vue @@ -111,7 +111,7 @@ const handleClose = () => { } const handleEscape = (event: KeyboardEvent) => { - if (props.show && props.closeOnEscape && event.key === 'Escape') { + if (props.show && props.closeOnEscape && event.key === 'Escape' && [...openDialogs].pop() === dialogId) { emit('close') } } diff --git a/frontend/src/components/common/__tests__/BaseDialog.escape.spec.ts b/frontend/src/components/common/__tests__/BaseDialog.escape.spec.ts new file mode 100644 index 0000000000..dadf10f621 --- /dev/null +++ b/frontend/src/components/common/__tests__/BaseDialog.escape.spec.ts @@ -0,0 +1,30 @@ +import { afterEach, describe, expect, it } from 'vitest' +import { enableAutoUnmount, mount } from '@vue/test-utils' +import BaseDialog from '../BaseDialog.vue' + +enableAutoUnmount(afterEach) +const pressEscape = () => document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape' })) + +describe('stacked dialog Escape handling', () => { + it('closes only the most recently opened dialog, then allows the parent to close', async () => { + const parent = mount(BaseDialog, { props: { show: true, title: 'Parent' } }) + const child = mount(BaseDialog, { props: { show: true, title: 'Child' } }) + pressEscape() + expect(child.emitted('close')).toHaveLength(1) + expect(parent.emitted('close')).toBeUndefined() + await child.setProps({ show: false }) + pressEscape() + expect(parent.emitted('close')).toHaveLength(1) + }) + + it('does not dismiss a parent behind a child that disallows Escape', () => { + const parent = mount(BaseDialog, { props: { show: true, title: 'Parent' } }) + const child = mount(BaseDialog, { props: { show: true, title: 'Child', closeOnEscape: false } }) + pressEscape() + expect(child.emitted('close')).toBeUndefined() + expect(parent.emitted('close')).toBeUndefined() + child.unmount() + pressEscape() + expect(parent.emitted('close')).toHaveLength(1) + }) +})