fix: bring the quick reply's buttons into view when it takes the focus

This commit is contained in:
Linus Rath
2026-11-03 07:13:03 +01:00
parent e3121e9bcc
commit e78ed0f007
2 changed files with 17 additions and 1 deletions
@@ -425,6 +425,17 @@ describe('reader surfaces in the phone conversation view', () => {
});
});
describe('quick reply', () => {
it('scrolls its buttons into view when it takes the focus', () => {
const scroll = vi.fn();
Element.prototype.scrollIntoView = scroll;
useSettingsStore.setState({ quickReplyEnabled: true });
const { container } = viewer(textMail('Hola'), { onQuickReply: vi.fn() });
fireEvent.focus(container.querySelector('textarea')!);
expect(scroll).toHaveBeenCalledWith({ block: 'nearest' });
});
});
describe('recipients row', () => {
it('says how many recipients are left out, in the phone row as in the desktop one', () => {
const to = ['a', 'b', 'c', 'd'].map((n) => ({ name: n, email: `${n}@example.com` }));
+6 -1
View File
@@ -1613,6 +1613,11 @@ export function EmailViewer({
const [quickReplyText, setQuickReplyText] = useState("");
const quickReplyRef = useRef<HTMLTextAreaElement>(null);
const [isQuickReplyFocused, setIsQuickReplyFocused] = useState(false);
const quickReplyBoxRef = useRef<HTMLDivElement>(null);
// Focused, the box grows by its buttons: bring them up, they'd sit below the fold.
useEffect(() => {
if (isQuickReplyFocused) quickReplyBoxRef.current?.scrollIntoView?.({ block: 'nearest' });
}, [isQuickReplyFocused]);
const [isSendingQuickReply, setIsSendingQuickReply] = useState(false);
/** The recipients and identity the quick reply would be sent with. */
const quickMetadata = (): ComposerMetadata => {
@@ -5937,7 +5942,7 @@ ${printWatermark ? printWatermark.html : ''}
)}
{/* Quick Reply Section - hidden for drafts and while loading a new email */}
{showQuickReply && (<div className="bg-background border-t border-border px-6 mt-auto" style={{ paddingBlock: 'var(--density-header-py)' }}>
{showQuickReply && (<div ref={quickReplyBoxRef} className="bg-background border-t border-border px-6 mt-auto max-sm:scroll-mb-16" style={{ paddingBlock: 'var(--density-header-py)' }}>
<div className="flex items-start" style={{ gap: 'var(--density-item-gap)' }}>
<div className="flex-shrink-0">
<Avatar