Skip to content

Commit

Permalink
Fixing a couple of forced reflows in our tutorial components (#9733)
Browse files Browse the repository at this point in the history
* fix forced reflows from tutorial components

* fix sidebar height in headless tutorials
  • Loading branch information
riknoll authored Oct 23, 2023
1 parent 2e524af commit 7698fc7
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 28 deletions.
2 changes: 1 addition & 1 deletion theme/tutorial-sidebar.less
Original file line number Diff line number Diff line change
Expand Up @@ -520,8 +520,8 @@
min-width: inherit;
max-width: inherit;
width: @simulatorWidth;
height: calc(~'100%' - @mainMenuHeight);
top: @mainMenuHeight;
bottom: 0;
left: 0;

.simPanel {
Expand Down
48 changes: 25 additions & 23 deletions webapp/src/components/tutorial/TutorialCallout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ interface TutorialCalloutProps extends React.PropsWithChildren<{}> {
}

export function TutorialCallout(props: TutorialCalloutProps) {
const { children, className, buttonIcon, buttonLabel } = props;
const { children, className, buttonIcon, buttonLabel, onClick } = props;
const [ visible, setVisible ] = React.useState(false);
const [ maxHeight, setMaxHeight ] = React.useState("unset");
const [ top, setTop ] = React.useState("unset");
Expand All @@ -20,6 +20,8 @@ export function TutorialCallout(props: TutorialCalloutProps) {
const contentRef = React.useRef<HTMLDivElement>(null);

React.useEffect(() => {
if (!visible) return undefined;

function checkSize() {
const lowerBuffer = (document.getElementById("editortools")?.clientHeight ?? 0) + 30;
if (contentRef.current?.getBoundingClientRect().bottom >= window.innerHeight - lowerBuffer) {
Expand All @@ -39,41 +41,41 @@ export function TutorialCallout(props: TutorialCalloutProps) {
if (contentRef.current) observer.observe(contentRef.current);

checkSize();
return () => observer.disconnect();
});

const captureEvent = (e: any) => {
const closeOnOutsideClick = (e: PointerEvent) => {
if (!popupRef?.current?.contains(e.target as Node)) {
setVisible(false);
}
};

document.addEventListener("click", closeOnOutsideClick);

return () => {
observer.disconnect();
document.removeEventListener("click", closeOnOutsideClick);
}
}, [visible]);


const captureEvent = (e: React.MouseEvent) => {
e.preventDefault();
e.stopPropagation();
e.nativeEvent?.stopImmediatePropagation();
}

const closeCallout = (e: any) => {
document.removeEventListener("click", closeCalloutIfClickedOutside, true);
const closeCallout = React.useCallback(() => {
setVisible(false);
}

const closeCalloutIfClickedOutside = (e: PointerEvent) => {
if (!popupRef?.current?.contains(e.target as Node)) {
closeCallout(e);
}
}
}, []);

const toggleCallout = (e: any) => {
const toggleCallout = React.useCallback((e: React.MouseEvent) => {
captureEvent(e);
if (!visible) {
document.addEventListener("click", closeCalloutIfClickedOutside, true);
} else {
document.removeEventListener("click", closeCalloutIfClickedOutside, true);
}
setVisible(!visible);
}
}, [visible]);

const handleButtonClick = (e: any) => {
const { onClick } = props;
const handleButtonClick = React.useCallback((e: React.MouseEvent) => {
if (onClick) onClick(visible);
toggleCallout(e);
}
}, [onClick, visible]);

const buttonTitle = lf("Click to show a hint!");
return <div ref={popupRef} className={className}>
Expand Down
9 changes: 5 additions & 4 deletions webapp/src/components/tutorial/TutorialContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,15 @@ export function TutorialContainer(props: TutorialContainerProps) {
const showImmersiveReader = pxt.appTarget.appTheme.immersiveReader;
const isHorizontal = props.tutorialSimSidebar || pxt.BrowserUtils.isTabletSize();

const container = React.useRef();

React.useEffect(() => {
const observer = new ResizeObserver(updateScrollGradient);
observer.observe(document.body)

// We also want to update the scroll gradient if the tutorial wrapper is resized by the user.
const parent = document.querySelector("#tutorialWrapper");
if (parent) {
observer.observe(parent);
if (container.current) {
observer.observe(container.current);
}

return () => observer.disconnect();
Expand Down Expand Up @@ -248,7 +249,7 @@ export function TutorialContainer(props: TutorialContainerProps) {
const hasHint = !!hintMarkdown;


return <div className="tutorial-container">
return <div className="tutorial-container" ref={container}>
{!isHorizontal && stepCounter}
<div className={classList("tutorial-content", hasHint && "has-hint")} ref={contentRef} onScroll={updateScrollGradient}>
<div className={"tutorial-content-bkg"}>
Expand Down

0 comments on commit 7698fc7

Please sign in to comment.