mirror of
https://github.com/bulwarkmail/webmail.git
synced 2026-10-31 00:12:39 +00:00
fix: keep admin toasts above the save bar so they never cover discard or save
This commit is contained in:
@@ -50,4 +50,18 @@ describe('AdminSaveBar', () => {
|
||||
expect(screen.getByTestId('page').querySelector('[data-testid="admin-save-bar"]')).toBeNull();
|
||||
host.remove();
|
||||
});
|
||||
it('lifts toasts above itself while it is shown', () => {
|
||||
// A toast over Discard / Save changes caught the clicks meant for them.
|
||||
const rect = vi.spyOn(HTMLElement.prototype, 'getBoundingClientRect').mockImplementation(function (this: HTMLElement) {
|
||||
return this.dataset.testid === 'admin-save-bar'
|
||||
? ({ top: window.innerHeight - 57, bottom: window.innerHeight, left: 0, right: 800, width: 800, height: 57 } as DOMRect)
|
||||
: ({ top: 0, bottom: 0, left: 0, right: 0, width: 0, height: 0 } as DOMRect);
|
||||
});
|
||||
const root = document.documentElement.style;
|
||||
const { rerender } = render(<AdminSaveBar dirty onSave={() => {}} />);
|
||||
expect(root.getPropertyValue('--bottom-controls-height')).toBe('57px');
|
||||
rerender(<AdminSaveBar dirty={false} onSave={() => {}} />);
|
||||
expect(root.getPropertyValue('--bottom-controls-height')).toBe('');
|
||||
rect.mockRestore();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -4,6 +4,7 @@ import { useEffect, type ReactNode } from 'react';
|
||||
import { createPortal } from 'react-dom';
|
||||
import { Loader2 } from '@/components/icons';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { useBottomControls } from '@/hooks/use-bottom-controls';
|
||||
import { useAdminShell } from './shell-context';
|
||||
|
||||
interface AdminSaveBarProps {
|
||||
@@ -21,9 +22,12 @@ interface AdminSaveBarProps {
|
||||
* The one place a page saves from. It appears at the bottom of the panel
|
||||
* while something is unsaved (through the shell's portal host, so it sits
|
||||
* below the scrolling content and above the mobile rail) and takes Ctrl+S.
|
||||
* It registers as a bottom bar, so toasts sit above it instead of over its
|
||||
* buttons.
|
||||
*/
|
||||
export function AdminSaveBar({ dirty, saving = false, onSave, onDiscard, saveLabel = 'Save changes', note }: AdminSaveBarProps) {
|
||||
const host = useAdminShell()?.saveBarHost ?? null;
|
||||
const barRef = useBottomControls(dirty);
|
||||
|
||||
useEffect(() => {
|
||||
if (!dirty) return;
|
||||
@@ -41,6 +45,7 @@ export function AdminSaveBar({ dirty, saving = false, onSave, onDiscard, saveLab
|
||||
|
||||
const bar = (
|
||||
<div
|
||||
ref={barRef}
|
||||
role="region"
|
||||
aria-label="Unsaved changes"
|
||||
data-testid="admin-save-bar"
|
||||
|
||||
Reference in New Issue
Block a user