fix(markdown): preview TOC dismiss-on-outside-click, popover z-index, code-block banner stickiness
Three preview (render) bugs where DSH's chat-optimized markdown primitives leak into the file-preview scroll world: - CodeBlock banner: DSH's bannerWrap is position:sticky (top:0, z-index:6) so a block keeps its copy action reachable inside a per-message scroll container. In the preview every fence shares one .editorMd scroll container, so the banner pins to the viewport top until the whole block scrolls past and reads as a floating header. Neutralize stickiness for non-mermaid fences in the preview (mermaid chrome replaces the banner and is excluded via data-mermaid-processed). - TOC popover z-index: .tocBar was z-index:3, below the code banner's 6, so the outline panel painted beneath a sticky fence header. Raise the bar to 7. - TOC dismissal: only the toggle re-click closed the popover. Add a document pointerdown listener that closes on an outside press (blank preview space), exempting the button and panel so the toggle still flips. Adds md-toc unit coverage for outside-click dismiss and toggle-preserving behavior; records the deviations in the TOC design doc.
This commit is contained in:
+18
-1
@@ -68,13 +68,30 @@ export function MdToc(): ReactNode {
|
||||
|
||||
// Esc closes the popover (the panel is a sibling of the button, so focus
|
||||
// stays wherever the user came from — a document listener is the simplest).
|
||||
// A document pointerdown also closes it when the click lands outside the
|
||||
// button and the panel, so clicking blank preview space dismisses the
|
||||
// outline instead of requiring a second click on the toggle. The check runs
|
||||
// at pointerdown (before the button's own click toggles), and the button and
|
||||
// panel are exempt so a re-click on the toggle keeps working as a toggle
|
||||
// rather than being eaten by the dismiss.
|
||||
useLayoutEffect(() => {
|
||||
if (!open) return
|
||||
const onKey = (event: KeyboardEvent): void => {
|
||||
if (event.key === 'Escape') setOpen(false)
|
||||
}
|
||||
const onPointerDown = (event: Event): void => {
|
||||
const target = event.target
|
||||
if (!(target instanceof Node)) return
|
||||
const bar = barRef.current
|
||||
if (bar !== null && bar.contains(target)) return
|
||||
setOpen(false)
|
||||
}
|
||||
document.addEventListener('keydown', onKey)
|
||||
return () => { document.removeEventListener('keydown', onKey) }
|
||||
document.addEventListener('pointerdown', onPointerDown)
|
||||
return () => {
|
||||
document.removeEventListener('keydown', onKey)
|
||||
document.removeEventListener('pointerdown', onPointerDown)
|
||||
}
|
||||
}, [open])
|
||||
|
||||
const jump = (entry: TocEntry): void => {
|
||||
|
||||
Reference in New Issue
Block a user