aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/components/ScrollToTop.tsx87
-rw-r--r--src/pages/LandingPage.tsx7
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;