From 39d88b6ffd840255f7bc16c2a74f97b47bc20db1 Mon Sep 17 00:00:00 2001 From: Tobias Date: Sun, 17 Mar 2024 19:41:25 +0100 Subject: [PATCH] Added scroll-snapping --- src/App.tsx | 33 ++++++++---- src/components/Navbar.tsx | 102 +++++++++++++++++++++++--------------- src/index.css | 11 +++- 3 files changed, 95 insertions(+), 51 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index 0f3d663..ccc4ef6 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,6 +1,6 @@ import theme from "./theme"; import { ThemeProvider } from "@emotion/react"; -import { useState } from "react"; +import { useState, useRef, useEffect } from "react"; import Hero from "./views/Hero"; import Navbar from "./components/Navbar"; import WeAreSprout from "./views/WeAreSprout"; @@ -9,23 +9,38 @@ import OurVision from "./views/OurVision"; import OurCases from "./views/OurCases"; import Contact from "./views/Contact"; import { useCurrentView } from "./hooks"; - +import styled from "@emotion/styled"; function App() { useCurrentView(); const [introVisited, setIntroVisited] = useState(false); + const scrollContainer = useRef(null); return ( - {!introVisited && } - - - - - - + + {!introVisited && } + + + + + + + ); } +const ScrollSnapContainer = styled.div` + position : relative; + scroll-snap-type: y mandatory; + height : 100%; + scroll-behavior: smooth; + overflow : auto; + > * { + scroll-snap-align: start; + } +`; + + export default App; diff --git a/src/components/Navbar.tsx b/src/components/Navbar.tsx index 249ceeb..9197345 100644 --- a/src/components/Navbar.tsx +++ b/src/components/Navbar.tsx @@ -1,4 +1,4 @@ -import { useState, useEffect } from "react"; +import { useState, useEffect, Ref } from "react"; import styled from "@emotion/styled"; import { css } from "@emotion/react"; @@ -7,11 +7,14 @@ import HamburgerMenu from "./HamburgerMenu"; import { mq } from "../theme"; import NavLink from "./NavLink"; + interface Props { - showMenu: boolean; + introVisited: boolean; + scrollContainer : React.MutableRefObject } -function Navbar({ showMenu }: Props) { +function Navbar({ scrollContainer, introVisited }: Props) { + function handleOpen(open: boolean) { if (open) { document.documentElement.classList.add("fullscreen-modal"); @@ -20,64 +23,77 @@ function Navbar({ showMenu }: Props) { } setOpen(open); } - + const [fixed, setFixed] = useState(false); const [open, setOpen] = useState(false); - const [visible, setVisible] = useState(true); + const [visible, setVisible] = useState(false); useEffect(() => { + if(scrollContainer.current) { + + setVisible(scrollContainer.current?.scrollTop > 0 || scrollContainer.current?.scrollTop === 0 && introVisited) + type ScrollDirection = "up" | "down"; const scrollOffset = 50; const visibleOffset = -100; const fixedOffset = 0; - let prevScrollPos = window.scrollY; + let prevScrollPos = scrollContainer.current?.scrollTop; let totalScrollDiff = 0; let prevScrollDirection: ScrollDirection = "down"; const handleScroll = () => { - const currentScrollPos = window.scrollY; - const scrollDirection = prevScrollPos > currentScrollPos ? "up" : "down"; - let alwaysVisible = false; - - // Handle fixed/static menu - const homeRect = document.getElementById("Home")?.getBoundingClientRect(); - if (homeRect) { - if (homeRect.top > visibleOffset) { - alwaysVisible = true; - } - - if (homeRect.top < fixedOffset && scrollDirection == "up") { - setFixed(true); - } else { - setFixed(false); + if(scrollContainer.current) { + setVisible(scrollContainer.current?.scrollTop > 0 || scrollContainer.current?.scrollTop === 0 && introVisited) + const currentScrollPos = scrollContainer.current?.scrollTop; + if(currentScrollPos) { + const scrollDirection = prevScrollPos > currentScrollPos ? "up" : "down"; + let alwaysVisible = false; + + // Handle fixed/static menu + const homeRect = document.getElementById("Home")?.getBoundingClientRect(); + if (homeRect) { + if (homeRect.top > visibleOffset) { + alwaysVisible = true; + } + + if (homeRect.top < fixedOffset && scrollDirection == "up") { + setFixed(scrollContainer.current?.scrollTop > 10 && introVisited || scrollContainer.current?.scrollTop !== 0 && !introVisited ); + + } else { + setFixed(false); + } + } + + if (scrollDirection === prevScrollDirection) { + totalScrollDiff += currentScrollPos - prevScrollPos; + } else { + totalScrollDiff = 0; + prevScrollDirection = scrollDirection; + } + + if (Math.abs(totalScrollDiff) > scrollOffset || alwaysVisible) { + setVisible(scrollDirection === "up" ? true : alwaysVisible); + } + + prevScrollPos = currentScrollPos; } } - - if (scrollDirection === prevScrollDirection) { - totalScrollDiff += currentScrollPos - prevScrollPos; - } else { - totalScrollDiff = 0; - prevScrollDirection = scrollDirection; - } - - if (Math.abs(totalScrollDiff) > scrollOffset || alwaysVisible) { - setVisible(scrollDirection === "up" ? true : alwaysVisible); - } - - prevScrollPos = currentScrollPos; + + }; - window.addEventListener("scroll", handleScroll, { passive: true }); + scrollContainer.current.addEventListener("scroll", handleScroll, { passive: true }); return () => { - window.removeEventListener("scroll", handleScroll); + scrollContainer.current?.removeEventListener("scroll", handleScroll); }; - }, []); + } + }, [scrollContainer, introVisited]); return (