Explorar o código

Merge pull request #3254 from pycbouh/add-navbar-scroll-v2

Add a scroll to navbar, second attempt
Rémi Verschelde %!s(int64=5) %!d(string=hai) anos
pai
achega
8d561e5eb6
Modificáronse 2 ficheiros con 82 adicións e 25 borrados
  1. 37 6
      _static/css/custom.css
  2. 45 19
      _static/js/custom.js

+ 37 - 6
_static/css/custom.css

@@ -21,6 +21,7 @@
     --navbar-level-2-color: #b8d6f0;
     --navbar-level-3-color: #a3c4e1;
     --navbar-heading-color: #ff7381;
+    --navbar-scrollbar-background: #131e2b;
 
     --link-color: #2980b9;
     --link-color-hover: #3091d1;
@@ -100,6 +101,7 @@
         --navbar-level-2-color: #ccc;
         --navbar-level-3-color: #bbb;
         --navbar-heading-color: #ee7381;
+        --navbar-scrollbar-background: #1c1e21;
 
         --link-color: #8cf;
         --link-color-hover: #9df;
@@ -602,7 +604,7 @@ kbd, .kbd {
 @media only screen and (min-width: 769px) {
     /* Simulate a drop shadow that only affects the bottom edge */
     /* This is used to indicate the search bar is fixed */
-    .wy-side-nav-search.fixed::after {
+    .wy-side-nav-search.fixed-and-scrolled::after {
         content: '';
         position: absolute;
         left: 0;
@@ -681,11 +683,6 @@ kbd, .kbd {
 
 /* First level of navigation items */
 
-.wy-menu-vertical {
-    /* Account for the increased `toctree-expand` button margins */
-    width: 308px;
-}
-
 .wy-menu-vertical a {
     color: var(--navbar-level-1-color);
 }
@@ -753,6 +750,11 @@ kbd, .kbd {
     background-color: var(--navbar-current-background-color-active);
 }
 
+.wy-menu-vertical a {
+    /* This overrides 8px margin added in other multi-selector rules */
+    margin-right: 0;
+}
+
 /* Version selector (only visible on Read the Docs) */
 
 .rst-versions {
@@ -803,3 +805,32 @@ kbd, .kbd {
     font-weight: inherit;
     padding: 0;
 }
+
+/* Allows the navbar's scrollbar to be shown */
+.wy-menu.wy-menu-vertical {
+    overflow-y: auto;
+    max-height: calc(100% - 348px);
+}
+@media screen and (max-width: 768px) {
+    .wy-nav-side {
+        padding-bottom: 44px;
+    }
+    .wy-menu.wy-menu-vertical {
+        overflow-y: initial;
+        max-height: initial;
+    }
+}
+
+/* Navbar's scrollbar styling */
+.wy-menu.wy-menu-vertical {
+    scrollbar-color: var(--navbar-heading-color) var(--navbar-scrollbar-background);
+}
+.wy-menu.wy-menu-vertical::-webkit-scrollbar {
+    width: .75rem;
+}
+.wy-menu.wy-menu-vertical::-webkit-scrollbar-track {
+    background-color: var(--navbar-scrollbar-background);
+}
+.wy-menu.wy-menu-vertical::-webkit-scrollbar-thumb {
+    background-color: var(--navbar-heading-color);
+}

+ 45 - 19
_static/js/custom.js

@@ -4,40 +4,66 @@ const scrollTopPixels = 234;
 // The margin to apply to the menu when the search bar is made fixed.
 // Should roughly match the logo's height as to not hide the top menu items
 // behind it.
-const menuTopMargin = '330px';
+const menuTopMargin = 90;
+const menuHeightOffset_default = 338;
+const menuHeightOffset_fixed = 102;
+const menuHeightOffset_diff = (menuHeightOffset_default - menuHeightOffset_fixed);
 
 // Hide the navigation bar logo when scrolling down on desktop platforms.
 // The logo is quite tall, so this helps make the rest of the navigation bar
 // more readable.
 function registerOnScrollEvent(mediaQuery) {
-  // The navigation bar that contains the logo.
-  const $navbar = $('.wy-side-scroll');
+  const $window = $(window);
   const $menu = $('.wy-menu-vertical');
   const $search = $('.wy-side-nav-search');
 
-  // The anchor that contains the logo. This element will be hidden
-  // (instead of hiding just the logo), otherwise, a small clickable area
-  // would remain visible.
-  const $logo = $('.wy-side-nav-search > a');
-
   if (mediaQuery.matches) {
     // We're on desktop; register the scroll event.
-    $navbar.scroll(function() {
-      if ($(this).scrollTop() >= scrollTopPixels) {
-        $logo.hide();
-        $search.addClass('fixed');
-        $menu.css('margin-top', menuTopMargin);
+    const handleEarlyScroll = (currentScroll) => {
+      $search.css('margin-top', `-${currentScroll}px`);
+      $menu.css('margin-top', `${menuTopMargin + (scrollTopPixels - currentScroll)}px`);
+
+      if (currentScroll > 0) {
+        const scrolledPercent = (scrollTopPixels - currentScroll) / scrollTopPixels;
+        const offsetValue = menuHeightOffset_fixed + menuHeightOffset_diff * scrolledPercent;
+        $menu.css('max-height', `calc(100% - ${offsetValue}px)`);
       } else {
-        $logo.show();
-        $search.removeClass('fixed');
-        $menu.css('margin-top', 0);
+        $menu.css('max-height', `calc(100% - ${menuHeightOffset_default}px)`);
+      }
+    };
+
+    $search.addClass('fixed');
+    $window.scroll(function() {
+      const currentScroll = window.scrollY;
+
+      if (currentScroll >= scrollTopPixels) {
+        $search.css('margin-top', `-${scrollTopPixels}px`);
+        $menu.css('margin-top', `${menuTopMargin}px`);
+
+        $menu.css('max-height', `calc(100% - ${menuHeightOffset_fixed}px)`);
+      }
+      else {
+        handleEarlyScroll(currentScroll);
       }
     });
+
+    $menu.scroll(function() {
+      if ($(this).scrollTop() > 0) {
+        $search.addClass('fixed-and-scrolled');
+      } else {
+        $search.removeClass('fixed-and-scrolled');
+      }
+    })
+
+    handleEarlyScroll(window.scrollY);
   } else {
     // We're on mobile; unregister the scroll event so the logo isn't hidden
-    // when scrolling.
-    $logo.show();
-    $navbar.unbind('scroll');
+    // when scrolling and clean up any changed properties.
+    $window.unbind('scroll');
+    $search.removeClass('fixed');
+    $search.css('margin-top', `0px`);
+    $menu.css('margin-top', `0px`);
+    $menu.css('max-height', 'initial');
   }
 }