mirror of
https://github.com/pybricks/pybricks-code.git
synced 2026-09-12 01:23:52 +00:00
restore docs position after hide/show
Previously, the docs iframe was removed from the DOM when the docs were hidden. This caused the docs to always go back to the main page when shown. This fixes it by using CSS to hide the docs instead of removing them from the DOM. However, this comes with its own complications regarding maintaining the scroll position.
This commit is contained in:
+81
-14
@@ -22,7 +22,7 @@ function App(): JSX.Element {
|
||||
<div className="app">
|
||||
<Toolbar />
|
||||
<SplitterLayout
|
||||
customClassName="h-body"
|
||||
customClassName={`h-body ${showDocs ? 'pb-show-docs' : 'pb-hide-docs'}`}
|
||||
onDragStart={(): void => setDragging(true)}
|
||||
onDragEnd={(): void => setDragging(false)}
|
||||
percentage={true}
|
||||
@@ -48,19 +48,86 @@ function App(): JSX.Element {
|
||||
<Terminal />
|
||||
</div>
|
||||
</SplitterLayout>
|
||||
{showDocs && (
|
||||
<div className="h-100 w-100">
|
||||
{dragging && <div className="h-100 w-100 p-absolute" />}
|
||||
<iframe
|
||||
src="static/docs/index.html"
|
||||
allowFullScreen={true}
|
||||
title="docs"
|
||||
width="100%"
|
||||
height="100%"
|
||||
frameBorder="none"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<div className="h-100 w-100">
|
||||
{dragging && <div className="h-100 w-100 p-absolute" />}
|
||||
<iframe
|
||||
onLoad={(e) => {
|
||||
// HACK: this mess restores the scroll position when
|
||||
// the documentation iframe visibility is toggled.
|
||||
// The iframe will be automatically scrolled to 0 when
|
||||
// CSS `display: none` is set.
|
||||
|
||||
const target = e.target as HTMLIFrameElement;
|
||||
const contentWindow = target.contentWindow;
|
||||
if (!contentWindow) {
|
||||
console.error('could not get iframe content window');
|
||||
return;
|
||||
}
|
||||
|
||||
// the last "good" scrollY value of the iframe
|
||||
let iframeScroll = 0;
|
||||
|
||||
// This bit monitors the visibility.
|
||||
// https://stackoverflow.com/a/44670818/1976323
|
||||
const observer = new IntersectionObserver(
|
||||
(entries) => {
|
||||
entries.forEach((entry) => {
|
||||
// Restore the scroll position when the
|
||||
// iframe is shown. Toggling the visibility
|
||||
// prevents flashing the contents from the
|
||||
// top of the page before the scroll is
|
||||
// done.
|
||||
if (entry.intersectionRatio > 0) {
|
||||
contentWindow.scrollTo(0, iframeScroll);
|
||||
contentWindow.document.documentElement.style.visibility =
|
||||
'visible';
|
||||
} else {
|
||||
contentWindow.document.documentElement.style.visibility =
|
||||
'hidden';
|
||||
}
|
||||
});
|
||||
},
|
||||
{
|
||||
root: target.parentElement,
|
||||
},
|
||||
);
|
||||
|
||||
observer.observe(target);
|
||||
|
||||
// Have to remove he observer, otherwise we end up
|
||||
// with conflicting values when a new page is loaded
|
||||
// in the iframe.
|
||||
contentWindow.addEventListener('unload', () => {
|
||||
observer.unobserve(target);
|
||||
});
|
||||
|
||||
// And this keeps track of the scroll position.
|
||||
contentWindow.addEventListener('scroll', () => {
|
||||
if (contentWindow.scrollY !== 0) {
|
||||
// Record the current scroll position.
|
||||
// If it is 0, it could be that the iframe
|
||||
// has been hidden or the user scrolled
|
||||
// there. So we have to ignore 0. But we
|
||||
// don't want to be one pixel off if the
|
||||
// user really did scroll there, so we
|
||||
// assume that if the last scroll is 1, then
|
||||
// the user probably went all the way to 0.
|
||||
if (contentWindow.scrollY === 1) {
|
||||
iframeScroll = 0;
|
||||
} else {
|
||||
iframeScroll = contentWindow.scrollY;
|
||||
}
|
||||
}
|
||||
});
|
||||
}}
|
||||
src="static/docs/index.html"
|
||||
allowFullScreen={true}
|
||||
title="docs"
|
||||
width="100%"
|
||||
height="100%"
|
||||
frameBorder="none"
|
||||
/>
|
||||
</div>
|
||||
</SplitterLayout>
|
||||
<StatusBar />
|
||||
<SettingsDrawer />
|
||||
|
||||
@@ -22,3 +22,9 @@
|
||||
.terminal-padding {
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
// hide the docs and resize separator
|
||||
|
||||
div.pb-hide-docs > :not(.layout-pane-primary) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user