fix(reply-modal): blur TeX button when preview closes

Blur the TeX preview trigger on close so Escape does not leave a
lingering focus outline or tooltip on the button.
This commit is contained in:
Tommaso Casaburi
2026-06-11 16:35:18 +07:00
parent 15fb1bf57c
commit 8456295eee
3 changed files with 36 additions and 8 deletions
@@ -544,6 +544,33 @@ describe('ReplyModal', () => {
expect(texPreview?.textContent).toContain('tex_preview_title');
});
it('clears TeX button focus after closing the TeX preview with Escape', async () => {
testState.directoryByAddress['science-and-math.bso'] = {
address: 'science-and-math.bso',
directoryCode: 'sci',
features: {},
title: '/sci/ - Science & Math',
};
testState.communities['science-and-math.bso'] = { address: 'science-and-math.bso' };
await renderReplyModal('/sci/thread/post-1', 'science-and-math.bso');
const texButton = container.querySelector<HTMLButtonElement>('button[aria-label="preview_tex_equations"]');
expect(texButton).toBeTruthy();
await act(async () => {
texButton?.focus();
texButton?.dispatchEvent(new MouseEvent('click', { bubbles: true }));
});
expect(document.activeElement).toBe(texButton);
await act(async () => {
document.dispatchEvent(new KeyboardEvent('keydown', { bubbles: true, cancelable: true, key: 'Escape' }));
});
expect(document.activeElement).not.toBe(texButton);
});
it('shows a flag selector on flag boards and publishes the default geographic request', async () => {
await renderReplyModal('/pol/thread/post-1', 'politically-incorrect.bso');
@@ -58,17 +58,11 @@
text-decoration: none;
}
.texButton:hover,
.texButton:focus-visible {
.texButton:hover {
color: var(--button-desktop-text-color-hover);
text-decoration: none;
}
.texButton:focus-visible {
outline: 1px dotted currentColor;
outline-offset: 1px;
}
.texButton sub {
font-size: 80%;
pointer-events: none;
+8 -1
View File
@@ -127,7 +127,13 @@ const ReplyModal = ({ closeModal, showReplyModal, parentCid, parentNumber, threa
const [isBbcodePreviewing, setIsBbcodePreviewing] = useState(false);
const [bbcodePreviewContent, setBbcodePreviewContent] = useState('');
const [showTexPreview, setShowTexPreview] = useState(false);
const closeTexPreview = useCallback(() => setShowTexPreview(false), []);
const texButtonRef = useRef<HTMLButtonElement>(null);
// Blur in the close handler so the TeX button doesn't keep a lingering focus state
// (focus-visible promotion on Escape, focus-triggered tooltip) after the preview closes.
const closeTexPreview = useCallback(() => {
setShowTexPreview(false);
texButtonRef.current?.blur();
}, []);
const checkContentLengthRef = useRef(
debounce((content: string, t: TFunction, options: string, directoryCode: string | undefined) => {
@@ -550,6 +556,7 @@ const ReplyModal = ({ closeModal, showReplyModal, parentCid, parentNumber, threa
{showTexButton && !isMobile && (
<Tooltip content={t('preview_tex_equations')} className={styles.texButtonTooltip}>
<button
ref={texButtonRef}
type='button'
className={styles.texButton}
onClick={(e) => {