fix: close the dialog on top with Escape, not the file preview behind it

This commit is contained in:
Linus Rath
2026-11-04 14:35:35 +01:00
parent f2f96e0f87
commit 438a31b34a
2 changed files with 42 additions and 0 deletions
@@ -0,0 +1,37 @@
import { render, fireEvent } from '@testing-library/react';
import { describe, it, expect, vi } from 'vitest';
import { PreviewShell } from '../preview-shell';
import { Dialog } from '@/components/ui/dialog';
// pim-p2-7: Escape in "Import to a mail folder…", opened from a saved mail's
// preview, closed the preview behind the dialog and left the dialog open.
describe('Escape with a dialog over the file preview', () => {
it('closes the dialog, not the preview', () => {
const closePreview = vi.fn();
const closeDialog = vi.fn();
const { getByLabelText } = render(
<>
<PreviewShell name="saved.eml" onClose={closePreview} onDownload={vi.fn()}>
<p>mail</p>
</PreviewShell>
<Dialog isOpen onClose={closeDialog} title="Import to a mail folder">
<input aria-label="Filter" />
</Dialog>
</>,
);
fireEvent.keyDown(getByLabelText('Filter'), { key: 'Escape' });
expect(closePreview).not.toHaveBeenCalled();
expect(closeDialog).toHaveBeenCalledTimes(1);
});
it('still closes the preview when nothing is above it', () => {
const closePreview = vi.fn();
render(
<PreviewShell name="saved.eml" onClose={closePreview} onDownload={vi.fn()}>
<button type="button">inside</button>
</PreviewShell>,
);
fireEvent.keyDown(document.body, { key: 'Escape' });
expect(closePreview).toHaveBeenCalledTimes(1);
});
});
+5
View File
@@ -69,6 +69,11 @@ export function PreviewShell({ name, onClose, onDownload, actions, neighbours, c
useEffect(() => {
const onKey = (e: KeyboardEvent) => {
if (e.key === "Escape") {
// A dialog opened from the preview (Import to a mail folder…) sits on top
// and closes first; the preview stays.
const target = e.target instanceof Element ? e.target : null;
const above = target?.closest('[role="dialog"], [role="alertdialog"]');
if (above && shellRef.current && !shellRef.current.contains(above)) return;
e.stopPropagation();
onClose();
return;