mirror of
https://github.com/bulwarkmail/webmail.git
synced 2026-11-01 00:13:37 +00:00
fix: keep the undo toast off the header on phones #1472
This commit is contained in:
@@ -207,4 +207,27 @@ describe('toasts and the focused element', () => {
|
||||
act(() => { vi.advanceTimersByTime(20); });
|
||||
expect(toastContainer()).not.toHaveAttribute('data-dodging');
|
||||
});
|
||||
|
||||
// On a phone the top of the screen is the header with Back and the message
|
||||
// actions; an Undo toast that moved there blocked them. (#1472)
|
||||
it('stays at the bottom on a phone, clear of the header', () => {
|
||||
vi.spyOn(window, 'matchMedia').mockImplementation((query: string) => ({
|
||||
matches: query === '(width < 40rem)',
|
||||
media: query, onchange: null,
|
||||
addEventListener: () => {}, removeEventListener: () => {}, addListener: () => {}, removeListener: () => {},
|
||||
dispatchEvent: () => false,
|
||||
}) as MediaQueryList);
|
||||
const h = window.innerHeight;
|
||||
vi.spyOn(HTMLElement.prototype, 'getBoundingClientRect').mockImplementation(function (this: HTMLElement) {
|
||||
if (this.hasAttribute('data-toast-container')) return rect(h - 140, 12, 366, 80);
|
||||
if (this.id === 'list') return rect(56, 0, 390, h - 116);
|
||||
return rect(10, 10, 80, 36);
|
||||
});
|
||||
render(<><Toasts /><div id="list" tabIndex={-1}>Messages</div></>);
|
||||
act(() => { (document.getElementById('list') as HTMLElement).focus(); });
|
||||
act(() => { toast.success('Moved to Trash'); });
|
||||
act(() => { vi.advanceTimersByTime(20); });
|
||||
expect(toastContainer()).not.toHaveAttribute('data-dodging');
|
||||
expect(toastContainer().className).not.toMatch(/(^|\s)(max-sm:)?top-/);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -393,7 +393,10 @@ export function ToastContainer({ toasts, onClose }: { toasts: Toast[]; onClose:
|
||||
const returnFocusRef = useRef<HTMLElement | null>(null);
|
||||
// The stack moves to the top corner while it would cover the element that
|
||||
// has the keyboard focus (WCAG 2.4.11): a Save button at the foot of the
|
||||
// event editor sat right under it.
|
||||
// event editor sat right under it. Not on a phone: there the top of the
|
||||
// screen is the header with Back and the message actions, which an Undo
|
||||
// toast covered after a delete (#1472), and the stack already rides above
|
||||
// the bottom bars.
|
||||
const [dodge, setDodge] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -402,7 +405,7 @@ export function ToastContainer({ toasts, onClose }: { toasts: Toast[]; onClose:
|
||||
|
||||
const hasToasts = toasts.length > 0;
|
||||
useLayoutEffect(() => {
|
||||
if (!hasToasts) {
|
||||
if (!hasToasts || phone) {
|
||||
setDodge(false);
|
||||
return;
|
||||
}
|
||||
@@ -419,7 +422,7 @@ export function ToastContainer({ toasts, onClose }: { toasts: Toast[]; onClose:
|
||||
document.removeEventListener("focusin", check);
|
||||
window.removeEventListener("resize", check);
|
||||
};
|
||||
}, [hasToasts, toasts.length]);
|
||||
}, [hasToasts, toasts.length, phone]);
|
||||
useEffect(() => {
|
||||
if (!hasToasts) return;
|
||||
const onKeyDown = (e: KeyboardEvent) => {
|
||||
@@ -463,7 +466,7 @@ export function ToastContainer({ toasts, onClose }: { toasts: Toast[]; onClose:
|
||||
"max-sm:inset-x-3 max-sm:bottom-[calc(var(--bottom-controls-height,3.75rem)+0.75rem)]",
|
||||
"max-sm:[html[data-composer-open]_&]:bottom-[max(5rem,calc(var(--bottom-controls-height,3.75rem)+0.75rem))]",
|
||||
// Out of the way of the focused element: the top end corner.
|
||||
dodge && "top-5 bottom-auto! max-sm:top-[calc(env(safe-area-inset-top)+0.75rem)]",
|
||||
dodge && "top-5 bottom-auto!",
|
||||
held && "invisible"
|
||||
)}
|
||||
data-dodging={dodge || undefined}
|
||||
|
||||
Reference in New Issue
Block a user