Просмотр исходного кода

use StickyStretchableScroller with Sidebar

Yuki Takei 5 лет назад
Родитель
Сommit
8a57cffa39

+ 21 - 3
src/client/js/components/Sidebar.jsx

@@ -14,6 +14,7 @@ import NavigationContainer from '../services/NavigationContainer';
 
 
 import SidebarNav from './Sidebar/SidebarNav';
 import SidebarNav from './Sidebar/SidebarNav';
 import SidebarContents from './Sidebar/SidebarContents';
 import SidebarContents from './Sidebar/SidebarContents';
+import StickyStretchableScroller from './StickyStretchableScroller';
 
 
 const sidebarDefaultWidth = 240;
 const sidebarDefaultWidth = 240;
 
 
@@ -134,13 +135,30 @@ class Sidebar extends React.Component {
     }
     }
   }
   }
 
 
+  calcViewHeight() {
+    const containerElem = document.querySelector('#grw-sidebar-content-container');
+    return window.innerHeight - containerElem.getBoundingClientRect().top;
+  }
+
   renderGlobalNavigation = () => (
   renderGlobalNavigation = () => (
     <SidebarNav onItemSelected={this.itemSelectedHandler} />
     <SidebarNav onItemSelected={this.itemSelectedHandler} />
   );
   );
 
 
-  renderSidebarContents = () => (
-    <SidebarContents />
-  );
+  renderSidebarContents = () => {
+    const scrollTargetSelector = 'div[data-testid="ContextualNavigation"] div[role="group"]';
+
+    return (
+      <>
+        <StickyStretchableScroller
+          scrollTargetSelector={scrollTargetSelector}
+          contentsElemSelector="#grw-sidebar-content-container"
+          stickyElemSelector=".grw-sidebar"
+          calcViewHeightFunc={this.calcViewHeight}
+        />
+        <SidebarContents />
+      </>
+    );
+  };
 
 
   render() {
   render() {
     const { isDrawerOpened } = this.props.navigationContainer.state;
     const { isDrawerOpened } = this.props.navigationContainer.state;

+ 5 - 1
src/client/js/components/Sidebar/SidebarContents.jsx

@@ -22,7 +22,11 @@ const SidebarContents = (props) => {
       Contents = CustomSidebar;
       Contents = CustomSidebar;
   }
   }
 
 
-  return <div className="grw-sidebar-content-container"><Contents /></div>;
+  return (
+    <div id="grw-sidebar-content-container" className="grw-sidebar-content-container">
+      <Contents />
+    </div>
+  );
 
 
 };
 };
 
 

+ 47 - 6
src/client/js/components/StickyStretchableScroller.jsx

@@ -11,16 +11,56 @@ import { withUnstatedContainers } from './UnstatedUtils';
 const logger = loggerFactory('growi:cli:StickyStretchableScroller');
 const logger = loggerFactory('growi:cli:StickyStretchableScroller');
 
 
 
 
+/**
+ * USAGE:
+ *
+  const calcViewHeight = useCallback(() => {
+    const containerElem = document.querySelector('#sticky-elem');
+    const containerTop = containerElem.getBoundingClientRect().top;
+
+    // stretch to the bottom of window
+    return window.innerHeight - containerTop;
+  });
+
+  return (
+    <StickyStretchableScroller
+      contentsElemSelector="#long-contents-elem"
+      stickyElemSelector="#sticky-elem"
+      calcViewHeightFunc={calcViewHeight}
+    >
+      <div id="scroll-elem">
+        ...
+      </div>
+    </StickyStretchableScroller>
+  );
+
+  or
+
+  return (
+    <StickyStretchableScroller
+      scrollTargetId="scroll-elem"
+      contentsElemSelector="#long-contents-elem"
+      stickyElemSelector="#sticky-elem"
+      calcViewHeightFunc={calcViewHeight}
+    />
+  );
+ */
 const StickyStretchableScroller = (props) => {
 const StickyStretchableScroller = (props) => {
 
 
+  let { scrollTargetSelector } = props;
   const {
   const {
     navigationContainer,
     navigationContainer,
     children, contentsElemSelector, stickyElemSelector,
     children, contentsElemSelector, stickyElemSelector,
     calcViewHeightFunc, calcContentsHeightFunc,
     calcViewHeightFunc, calcContentsHeightFunc,
   } = props;
   } = props;
 
 
-  const id = children.props.id;
+  if (scrollTargetSelector == null && children == null) {
+    throw new Error('Either of scrollTargetSelector or children is required');
+  }
 
 
+  if (scrollTargetSelector == null) {
+    scrollTargetSelector = `#${children.props.id}`;
+  }
 
 
   /**
   /**
    * Reset scrollbar
    * Reset scrollbar
@@ -38,16 +78,16 @@ const StickyStretchableScroller = (props) => {
       ? calcContentsHeightFunc(contentsElem)
       ? calcContentsHeightFunc(contentsElem)
       : contentsElem.getBoundingClientRect().height;
       : contentsElem.getBoundingClientRect().height;
 
 
-    logger.debug('viewHeight', viewHeight);
-    logger.debug('contentsHeight', contentsHeight);
+    logger.debug(`[${scrollTargetSelector}] viewHeight`, viewHeight);
+    logger.debug(`[${scrollTargetSelector}] contentsHeight`, contentsHeight);
 
 
-    $(`#${id}`).slimScroll({
+    $(scrollTargetSelector).slimScroll({
       railVisible: true,
       railVisible: true,
       position: 'right',
       position: 'right',
       height: viewHeight,
       height: viewHeight,
     });
     });
     if (contentsHeight < viewHeight) {
     if (contentsHeight < viewHeight) {
-      $(`#${id}`).slimScroll({ destroy: true });
+      $(scrollTargetSelector).slimScroll({ destroy: true });
     }
     }
   }, [contentsElemSelector, calcViewHeightFunc, calcContentsHeightFunc]);
   }, [contentsElemSelector, calcViewHeightFunc, calcContentsHeightFunc]);
 
 
@@ -106,9 +146,10 @@ const StickyStretchableScroller = (props) => {
 
 
 StickyStretchableScroller.propTypes = {
 StickyStretchableScroller.propTypes = {
   navigationContainer: PropTypes.instanceOf(NavigationContainer).isRequired,
   navigationContainer: PropTypes.instanceOf(NavigationContainer).isRequired,
-  children: PropTypes.node.isRequired,
   contentsElemSelector: PropTypes.string.isRequired,
   contentsElemSelector: PropTypes.string.isRequired,
 
 
+  children: PropTypes.node,
+  scrollTargetSelector: PropTypes.string,
   stickyElemSelector: PropTypes.string,
   stickyElemSelector: PropTypes.string,
 
 
   calcViewHeightFunc: PropTypes.func,
   calcViewHeightFunc: PropTypes.func,

+ 0 - 3
src/client/styles/scss/_sidebar.scss

@@ -87,9 +87,6 @@
       }
       }
     }
     }
   }
   }
-  div[data-testid='ContextualNavigation'] {
-    height: calc(100vh - #{$grw-navbar-height});
-  }
 
 
   .grw-sidebar-nav {
   .grw-sidebar-nav {
     height: 100vh;
     height: 100vh;