diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/components/ScrollToTop.tsx | 87 | ||||
-rw-r--r-- | src/pages/LandingPage.tsx | 7 |
2 files changed, 91 insertions, 3 deletions
diff --git a/src/components/ScrollToTop.tsx b/src/components/ScrollToTop.tsx new file mode 100644 index 0000000..6af938d --- /dev/null +++ b/src/components/ScrollToTop.tsx @@ -0,0 +1,87 @@ +/** @jsx jsx */ +import { jsx, css } from "@emotion/react"; +import React from "react"; + +const styles = css` + width: 2.5rem; + height: 2.5rem; + + position: fixed; + bottom: 3rem; + right: 3rem; + + background-color: #7289DA; /* Blurple */ + border-radius: 50%; + + opacity: 0; + transition: opacity 300ms; + + :after { + display: inline-block; + content: ""; + + position: fixed; + bottom: 3.5rem; + right: 3.65rem; + + border: solid whitesmoke; + border-width: 0.35rem 0.35rem 0 0; + padding: 0.4rem; + + transform: rotate(-45deg); + } + + @media (max-width: 800px) { + bottom: 1.5rem; + right: 1.5rem; + + :after { + bottom: 2rem; + right: 2.15rem; + } + } +`; + +let last_ref: React.RefObject<HTMLDivElement>; + +class ScrollToTop extends React.Component { + constructor(props: Record<string, never>) { + super(props); + last_ref = React.createRef(); + } + + handleScroll(): void { + if (!last_ref.current) return; + + if (window.pageYOffset > 250) { + last_ref.current.style.opacity = "1"; + } else { + last_ref.current.style.opacity = "0"; + } + } + + componentDidMount(): void { + // Register event handler + window.addEventListener("scroll", this.handleScroll, {passive: true}); + } + + componentDidUpdate(): void { + // Hide previous iterations, and register handler for current one + if (last_ref.current) { + last_ref.current.style.opacity = "0"; + } + + window.addEventListener("scroll", this.handleScroll, {passive: true}); + } + + componentWillUnmount(): void { + // Unregister handler + window.removeEventListener("scroll", this.handleScroll); + } + + render(): JSX.Element { + return <div css={styles} key={Date.now()} ref={last_ref} onClick={() => window.scrollTo({top: 0, behavior: "smooth"})}/>; + } +} + +export default ScrollToTop; diff --git a/src/pages/LandingPage.tsx b/src/pages/LandingPage.tsx index 124bbcf..af968ad 100644 --- a/src/pages/LandingPage.tsx +++ b/src/pages/LandingPage.tsx @@ -4,10 +4,11 @@ import { useEffect, useState } from "react"; import HeaderBar from "../components/HeaderBar"; import FormListing from "../components/FormListing"; - -import { getForms, Form } from "../api/forms"; import OAuth2Button from "../components/OAuth2Button"; import Loading from "../components/Loading"; +import ScrollToTop from "../components/ScrollToTop"; + +import { getForms, Form } from "../api/forms"; function LandingPage(): JSX.Element { const [forms, setForms] = useState<Form[]>(); @@ -25,8 +26,8 @@ function LandingPage(): JSX.Element { return <div> <HeaderBar/> + <ScrollToTop/> <div> - <div css={css` display: flex; align-items: center; |