diff --git a/src/__tests__/renderer/components/FilePreview.test.tsx b/src/__tests__/renderer/components/FilePreview.test.tsx index ff4f2554..a2ba667b 100644 --- a/src/__tests__/renderer/components/FilePreview.test.tsx +++ b/src/__tests__/renderer/components/FilePreview.test.tsx @@ -753,9 +753,9 @@ print("world") expect(screen.getByText('Contents')).toBeInTheDocument(); }); - it('stops wheel event propagation on TOC overlay to isolate scrolling', () => { + it('closes TOC when clicking outside of it', async () => { const markdownWithHeadings = '# Heading 1\n## Heading 2\n## Heading 3'; - render( + const { container } = render( setTimeout(resolve, 10)); - // Dispatch the wheel event on the TOC container - tocContainer?.dispatchEvent(wheelEvent); + // Click outside the TOC (on the main container) + const mainContainer = container.firstChild as HTMLElement; + fireEvent.mouseDown(mainContainer); - // The onWheel handler should have called stopPropagation - expect(stopPropagationSpy).toHaveBeenCalled(); + // TOC should be closed + expect(screen.queryByText('Contents')).not.toBeInTheDocument(); }); }); diff --git a/src/renderer/components/FilePreview.tsx b/src/renderer/components/FilePreview.tsx index d9f15eef..84feb3fd 100644 --- a/src/renderer/components/FilePreview.tsx +++ b/src/renderer/components/FilePreview.tsx @@ -689,6 +689,8 @@ export const FilePreview = forwardRef(funct const matchElementsRef = useRef([]); const cancelButtonRef = useRef(null); const scrollSaveTimerRef = useRef | null>(null); + const tocButtonRef = useRef(null); + const tocOverlayRef = useRef(null); // Expose focus method to parent via ref useImperativeHandle( @@ -1158,6 +1160,11 @@ export const FilePreview = forwardRef(funct // Disable click-outside in tab mode - tabs should only close via explicit user action useClickOutside(containerRef, handleEscapeRequest, !!file && !isTabMode, { delay: true }); + // Click outside ToC overlay to dismiss (exclude both overlay and the toggle button) + // Use delay to prevent the click that opened it from immediately closing it + const closeTocOverlay = useCallback(() => setShowTocOverlay(false), []); + useClickOutside([tocOverlayRef, tocButtonRef], closeTocOverlay, showTocOverlay, { delay: true }); + // Keep search input focused when search is open useEffect(() => { if (searchOpen && searchInputRef.current) { @@ -2231,6 +2238,7 @@ export const FilePreview = forwardRef(funct <> {/* Floating TOC Button */} - {/* TOC Overlay */} + {/* TOC Overlay - click outside handled by useClickOutside hook */} {showTocOverlay && ( - <> - {/* Click-outside backdrop */} -
setShowTocOverlay(false)} - /> -
(funct Bottom
- )} )}