diff --git a/public/assets/pointer_down.svg b/public/assets/pointer_down.svg new file mode 100644 index 0000000..e743ce3 --- /dev/null +++ b/public/assets/pointer_down.svg @@ -0,0 +1,21 @@ + + + + + + + + + diff --git a/src/App.tsx b/src/App.tsx index dd011b4..bab2e37 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -7,7 +7,12 @@ function App() {
-
+
+ +
); } diff --git a/src/main_page/Greeting.tsx b/src/main_page/Greeting.tsx index bb52e90..94f19c5 100644 --- a/src/main_page/Greeting.tsx +++ b/src/main_page/Greeting.tsx @@ -2,12 +2,14 @@ import { FunctionComponent } from "react"; import './greeting.css'; import WelcomeText from './WelcomeText'; import Socials from './Socials'; +import ScrollHint from './ScrollHint'; const Greeting: FunctionComponent = () => { return (
- + +
); } diff --git a/src/main_page/ScrollHint.tsx b/src/main_page/ScrollHint.tsx new file mode 100644 index 0000000..660257a --- /dev/null +++ b/src/main_page/ScrollHint.tsx @@ -0,0 +1,22 @@ +import { FunctionComponent, useEffect, useState } from "react"; +import './greeting.css'; + +const ScrollHint: FunctionComponent = () => { + const [arrowHidden, setArrowHidden] = useState(true); + const [textHidden, setTextHidden] = useState(true); + + useEffect(() => { + setTimeout(() => setArrowHidden(false), 2000); + setTimeout(() => setTextHidden(false), 3000); + }); + + return ( +
+ Scroll down +
+ +
+ ); +} + +export default ScrollHint; diff --git a/src/main_page/Socials.tsx b/src/main_page/Socials.tsx index 1ecf200..89e781f 100644 --- a/src/main_page/Socials.tsx +++ b/src/main_page/Socials.tsx @@ -5,11 +5,11 @@ import SocialsEntry from './SocialsEntry'; const Socials: FunctionComponent = () => { return (
- - - - - + + + + +
); } diff --git a/src/main_page/SocialsEntry.tsx b/src/main_page/SocialsEntry.tsx index b630121..e821d49 100644 --- a/src/main_page/SocialsEntry.tsx +++ b/src/main_page/SocialsEntry.tsx @@ -1,24 +1,37 @@ -import { FunctionComponent, useState } from "react"; +import { FunctionComponent, useEffect, useState } from "react"; import './greeting.css'; -type Params = { image: string, link: string, text: string, redactUntilClick?: boolean }; +function reverse(value: string) { + return Array.from( + String(value || '') + ).reverse().join(''); +} + +type Params = { image: string, link: string, text: string, redactUntilClick?: boolean, index: number }; const SocialsEntry: FunctionComponent = (params: Params) => { const [ content, setContent ] = useState(params.redactUntilClick ? 'Click to reveal' : params.text); const [ href, setHref ] = useState(params.redactUntilClick ? '#' : params.link); const [ allowClick, setAllowClick ] = useState(!params.redactUntilClick); + const [ hidden, setHidden ] = useState(true); + + useEffect(() => { + setTimeout(() => setHidden(false), 100 * params.index + 500); + }); return ( -
+
{ if (!allowClick) event.preventDefault(); - setContent(params.text); - setHref(params.link); setAllowClick(true); + + // Lets hope that this stops most scrapers + setContent(reverse(atob(reverse(params.text)))); + setHref(reverse(atob(reverse(params.link)))); } : undefined} > {content} diff --git a/src/main_page/greeting.css b/src/main_page/greeting.css index 63ddf82..43ee633 100644 --- a/src/main_page/greeting.css +++ b/src/main_page/greeting.css @@ -1,3 +1,28 @@ +@keyframes scroll-hint-arrow { + 0% { + transform: translateY(-50%); + opacity: 0; + } + 40% { + opacity: 1; + } + 50% { + transform: translateY(10%); + } + 100% { + transform: translateY(0); + } +} + +@keyframes scroll-hint-text { + 0% { + opacity: 0; + } + 100% { + opacity: 1; + } +} + .greeting-area { width: 100%; height: 100vh; @@ -39,6 +64,12 @@ align-items: flex-start; justify-content: flex-start; padding-bottom: 8px; + opacity: 1; + transition: opacity .5s; +} + +.greeting-socials-container.hidden { + opacity: 0; } .greeting-socials-image { @@ -62,3 +93,34 @@ color: #dddddd; text-decoration: underline; } + +.scroll-hint-container { + position: absolute; + left: 50%; + transform: translateX(-50%); + bottom: 5%; + text-align: center; +} + +.scroll-hint-container img { + position: relative; + height: 30px; + animation-name: scroll-hint-arrow; + animation-duration: 5s; + animation-direction: normal; +} + +.scroll-hint-container img.hidden, .scroll-hint-container span.hidden { + display: none; +} + +.scroll-hint-container span { + position: relative; + animation-name: scroll-hint-text; + animation-duration: 5s; + animation-direction: normal; + bottom: 20px; + text-align: center; + font-weight: 300; + font-size: 18px; +}