mirror of
https://github.com/bulwarkmail/webmail.git
synced 2026-11-02 08:15:55 +00:00
fix: let Escape close a dialog right after its form closed
This commit is contained in:
@@ -157,3 +157,23 @@ describe('useFocusTrap and the page behind', () => {
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Presses Escape in its layout effect: after the DOM of a render is in
|
||||
// place, before that render's passive effects have run.
|
||||
function EscapeOnCommit({ press }: { press: number }) {
|
||||
React.useLayoutEffect(() => {
|
||||
if (press) fireEvent.keyDown(document.body, { key: 'Escape' });
|
||||
}, [press]);
|
||||
return null;
|
||||
}
|
||||
|
||||
describe('useFocusTrap handler timing', () => {
|
||||
it('answers an Escape right after a render with that render\'s handler', () => {
|
||||
const before = vi.fn();
|
||||
const after = vi.fn();
|
||||
const { rerender } = render(<><Dialog onEscape={before} /><EscapeOnCommit press={0} /></>);
|
||||
rerender(<><Dialog onEscape={after} /><EscapeOnCommit press={1} /></>);
|
||||
expect(after).toHaveBeenCalledTimes(1);
|
||||
expect(before).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { useEffect, useLayoutEffect, useRef } from 'react';
|
||||
|
||||
// The traps that are active, the one opened last at the end. Only that one
|
||||
// answers Escape, so a dialog over a dialog closes alone.
|
||||
@@ -24,9 +24,12 @@ export function useFocusTrap({
|
||||
// one from here instead of starting over for it: each new start moved the
|
||||
// focus back to the opener and then to the first element, out of the field
|
||||
// the user was typing in whenever the page behind rendered again.
|
||||
// Updated during the commit, not after it: an Escape pressed once the
|
||||
// DOM has changed must reach the handler of that render, not the one
|
||||
// before (a form that just closed would ask about its input again).
|
||||
const onEscapeRef = useRef(onEscape);
|
||||
const initialFocusRef = useRef(initialFocus);
|
||||
useEffect(() => {
|
||||
useLayoutEffect(() => {
|
||||
onEscapeRef.current = onEscape;
|
||||
initialFocusRef.current = initialFocus;
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user