diff --git a/.changeset/clean-cycles-suffer.md b/.changeset/clean-cycles-suffer.md new file mode 100644 index 0000000000..9913340064 --- /dev/null +++ b/.changeset/clean-cycles-suffer.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-techdocs': patch +--- + +Fixed bug in TechDocs sidebar render that prevented scrollbar from being displayed diff --git a/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/dom.tsx b/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/dom.tsx index 3d12718986..bf8a1309b2 100644 --- a/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/dom.tsx +++ b/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/dom.tsx @@ -71,7 +71,7 @@ export const useTechDocsReaderDom = ( const [dom, setDom] = useState(null); const isStyleLoading = useShadowDomStylesLoading(dom); - const updateSidebarPosition = useCallback(() => { + const updateSidebarPositionAndHeight = useCallback(() => { if (!dom) return; const sidebars = dom.querySelectorAll('.md-sidebar'); @@ -92,7 +92,18 @@ export const useTechDocsReaderDom = ( if (domTop < pageTop) { domTop = pageTop; } - element.style.top = `${Math.max(domTop, 0) + tabsHeight}px`; + + const scrollbarTopPx = Math.max(domTop, 0) + tabsHeight; + + element.style.top = `${scrollbarTopPx}px`; + + // set scrollbar height to ensure all links can be seen when content is small + const footer = dom.querySelector('.md-container > .md-footer'); + // if no footer, fallback to using the bottom of the window + const scrollbarEndPx = + footer?.getBoundingClientRect().top ?? window.innerHeight; + + element.style.height = `${scrollbarEndPx - scrollbarTopPx}px`; } // show the sidebar only after updating its position @@ -101,13 +112,17 @@ export const useTechDocsReaderDom = ( }, [dom, isMobileMedia]); useEffect(() => { - window.addEventListener('resize', updateSidebarPosition); - window.addEventListener('scroll', updateSidebarPosition, true); + window.addEventListener('resize', updateSidebarPositionAndHeight); + window.addEventListener('scroll', updateSidebarPositionAndHeight, true); return () => { - window.removeEventListener('resize', updateSidebarPosition); - window.removeEventListener('scroll', updateSidebarPosition, true); + window.removeEventListener('resize', updateSidebarPositionAndHeight); + window.removeEventListener( + 'scroll', + updateSidebarPositionAndHeight, + true, + ); }; - }, [dom, updateSidebarPosition]); + }, [dom, updateSidebarPositionAndHeight]); // dynamically set width of footer to accommodate for pinning of the sidebar const updateFooterWidth = useCallback(() => { @@ -129,10 +144,15 @@ export const useTechDocsReaderDom = ( useEffect(() => { if (!isStyleLoading) { updateFooterWidth(); - updateSidebarPosition(); + updateSidebarPositionAndHeight(); } // eslint-disable-next-line react-hooks/exhaustive-deps - }, [state, isStyleLoading, updateFooterWidth, updateSidebarPosition]); + }, [ + state, + isStyleLoading, + updateFooterWidth, + updateSidebarPositionAndHeight, + ]); // a function that performs transformations that are executed prior to adding it to the DOM const preRender = useCallback(