fix(coach): move focus to the composer before hiding the jump button

Jumping to the latest message pinned the thread first, which hides the
button behind aria-hidden, and only then moved focus to the composer.
Focus now leaves the button before its state changes.
This commit is contained in:
Marc-André Bombeck committed 2026-10-05 08:34:27 +02:00
1 parent 3b283507b5
commit 308e154978
2 files changed
+6 -2

No files matched your search

@@ -57,8 +57,10 @@ describe("<ScrollToBottomButton>", () => {
expect(src).toContain(
"<ScrollToBottomButton visible={!pinned} onClick={scrollToLatest} />",
);
// Focus leaves the button BEFORE the state that hides it changes: a
// focused control under aria-hidden is announced as nothing.
expect(src).toMatch(
/scrollToLatest = useCallback\([\s\S]*?wasPinnedRef\.current = true;[\s\S]*?focusCoachComposer\(\);/,
/scrollToLatest = useCallback\(\(\) => \{[^}]*?focusCoachComposer\(\);[^}]*?setPinned\(true\);/,
);
});
});
@@ -394,10 +394,12 @@ export function MessageThread({
const scrollToLatest = useCallback(() => {
const el = scrollerRef.current;
if (!el) return;
// Focus first: pinning hides this button (aria-hidden), and focus must
// not sit on a control that has left the accessibility tree.
focusCoachComposer();
wasPinnedRef.current = true;
setPinned(true);
el.scrollTo({ top: el.scrollHeight, behavior: scrollBehaviorForUser() });
focusCoachComposer();
}, []);
// Auto-scroll on new messages OR streaming-content growth, but only