Browse Source

fix(issues): Fix guide scroll into screen (#66829)

Scott Cooper 1 year ago
parent
commit
2813e2db41
2 changed files with 27 additions and 18 deletions
  1. 21 17
      static/app/components/assistant/guideAnchor.tsx
  2. 6 1
      static/app/stores/guideStore.tsx

+ 21 - 17
static/app/components/assistant/guideAnchor.tsx

@@ -1,4 +1,4 @@
-import {Component, createRef, Fragment} from 'react';
+import {Component, createRef, Fragment, useEffect} from 'react';
 import styled from '@emotion/styled';
 import * as Sentry from '@sentry/react';
 import type {Query} from 'history';
@@ -43,6 +43,25 @@ type Props = {
   };
 };
 
+function ScrollToGuide({children}: {children: React.ReactNode}) {
+  const containerElement = createRef<HTMLSpanElement>();
+
+  useEffect(() => {
+    if (containerElement.current) {
+      try {
+        const {top} = containerElement.current.getBoundingClientRect();
+        const scrollTop = window.pageYOffset;
+        const centerElement = top + scrollTop - window.innerHeight / 2;
+        window.scrollTo({top: centerElement});
+      } catch (err) {
+        Sentry.captureException(err);
+      }
+    }
+  }, [containerElement]);
+
+  return <span ref={containerElement}>{children}</span>;
+}
+
 type State = {
   active: boolean;
   org: Organization | null;
@@ -66,19 +85,6 @@ class BaseGuideAnchor extends Component<Props, State> {
     registerAnchor(target);
   }
 
-  componentDidUpdate(_prevProps: Props, prevState: State) {
-    if (this.containerElement.current && !prevState.active && this.state.active) {
-      try {
-        const {top} = this.containerElement.current.getBoundingClientRect();
-        const scrollTop = window.pageYOffset;
-        const centerElement = top + scrollTop - window.innerHeight / 2;
-        window.scrollTo({top: centerElement});
-      } catch (err) {
-        Sentry.captureException(err);
-      }
-    }
-  }
-
   componentWillUnmount() {
     const {target} = this.props;
     unregisterAnchor(target);
@@ -90,8 +96,6 @@ class BaseGuideAnchor extends Component<Props, State> {
     undefined
   );
 
-  containerElement = createRef<HTMLSpanElement>();
-
   onGuideStateChange(data: GuideStoreState) {
     const active =
       data.currentGuide?.steps[data.currentStep]?.target === this.props.target &&
@@ -234,7 +238,7 @@ class BaseGuideAnchor extends Component<Props, State> {
         offset={offset}
         containerClassName={containerClassName}
       >
-        <span ref={this.containerElement}>{children}</span>
+        <ScrollToGuide>{children}</ScrollToGuide>
       </StyledHovercard>
     );
   }

+ 6 - 1
static/app/stores/guideStore.tsx

@@ -81,6 +81,10 @@ const defaultState: GuideStoreState = {
   prevGuide: null,
 };
 
+function isForceEnabled() {
+  return window.location.hash === '#assistant';
+}
+
 interface GuideStoreDefinition extends CommonStoreDefinition<GuideStoreState> {
   browserHistoryListener: null | (() => void);
   closeGuide(dismissed?: boolean): void;
@@ -111,6 +115,7 @@ const storeConfig: GuideStoreDefinition = {
 
     this.state = defaultState;
 
+    this.state.forceShow = isForceEnabled();
     window.addEventListener('load', this.onURLChange, false);
     this.browserHistoryListener = browserHistory.listen(() => this.onURLChange());
 
@@ -143,7 +148,7 @@ const storeConfig: GuideStoreDefinition = {
   },
 
   onURLChange() {
-    this.state.forceShow = window.location.hash === '#assistant';
+    this.state.forceShow = isForceEnabled();
     this.updateCurrentGuide();
   },