diff --git a/components/navigation/sideBar.js b/components/navigation/sideBar.js index b10aac78e..8e26f7c18 100644 --- a/components/navigation/sideBar.js +++ b/components/navigation/sideBar.js @@ -9,6 +9,7 @@ import styles from "./sideBar.module.css"; const SideBar = ({ menu, slug }) => { const [isCondensed, setIsCondensed] = useState(false); + const [isSticky, setIsSticky] = useState("none"); const [isOver, setIsOver] = useState(false); const [isOpen, setIsOpen] = useState(false); const [theme, setTheme] = useState("light-mode"); @@ -40,10 +41,26 @@ const SideBar = ({ menu, slug }) => { } }; + const handleScroll = (e) => { + // We check if the user scrolled on the whole page + const windowScroll = window.scrollY; + // But we also check if the user hasn't scrolled on the page, but scrolled inside the sidebar + const sideBarScroll = e.target.scrollTop; + + if (windowScroll > 20) { + setIsSticky("window"); + } else if (sideBarScroll > 5) { + setIsSticky("scrollbar"); + } else { + setIsSticky("none"); + } + }; + const debouncedCheckExpanded = debounce(checkExpanded, 200); useEffect(() => { window.addEventListener("resize", debouncedCheckExpanded); + window.addEventListener("scroll", handleScroll); window.addEventListener("ChangeTheme", handleTheme); bus.on("streamlit_nav_open", () => setIsOpen(true)); @@ -54,6 +71,7 @@ const SideBar = ({ menu, slug }) => { return () => { window.removeEventListener("resize", debouncedCheckExpanded); + window.removeEventListener("scroll", handleScroll); window.removeEventListener("ChangeTheme", handleTheme); }; }, []); @@ -77,7 +95,18 @@ const SideBar = ({ menu, slug }) => { isOpen ? styles.OpenNav : styles.ClosedNav, isOver ? styles.OverNav : styles.CollapsedNav )} + onScroll={(e) => handleScroll(e)} > +
diff --git a/components/navigation/sideBar.module.css b/components/navigation/sideBar.module.css index 9a878bfe8..f5797b87f 100644 --- a/components/navigation/sideBar.module.css +++ b/components/navigation/sideBar.module.css @@ -1,5 +1,5 @@ .Container { - @apply fixed lg:sticky top-auto lg:top-16 left-0 xl:left-auto px-0 h-screen z-20 w-10/12 md:w-9/12 xl:w-screen max-w-xs md:max-w-none overflow-y-auto shadow-lg lg:shadow-none transition-all; + @apply fixed lg:sticky top-auto lg:top-12 left-0 xl:left-auto px-0 h-screen z-20 w-10/12 md:w-9/12 xl:w-screen max-w-xs md:max-w-none overflow-y-auto shadow-lg lg:shadow-none transition-all; @apply bg-white !important; } @@ -31,3 +31,20 @@ .NavList { @apply list-none overscroll-contain m-0 px-2 lg:px-0; } + +.TopGradient { + @apply hidden lg:block fixed top-0 w-full bg-gradient-to-b from-white z-10; + max-width: 280px; +} + +.WindowStickyGradient { + @apply top-12 h-6; +} + +.ScrollBarStickyGradient { + @apply top-24 h-6; +} + +:global(.dark) .TopGradient { + @apply from-gray-100; +}