This commit is contained in:
Tben 2022-06-03 17:36:24 +01:00
parent 74db5bd158
commit 30fb78c4ff
17 changed files with 244 additions and 2446 deletions

View File

@ -1,42 +1,73 @@
import React, { Fragment, useEffect, useState } from 'react'
import React, { Fragment, useEffect, useState } from 'react';
import { gsap } from "gsap";
let timer = 0;
let keyNum = 0;
let textTimeout;
let chars = ("abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()_+=-;.,/?><][}{:`~").split("");
// let chars = ("abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()_+=-;.,/?><][}{:`~").split("");
const TextShuffler = ({ textInput }) => {
const TextShuffler = ({ textInput, delay }) => {
let [text, setText] = useState(textInput);
let [refresh, setRefresh] = useState(0);
let [readyState, setReadyState] = useState(false);
const spanRef = React.useRef();
useEffect(() => {
const spanObserver = new IntersectionObserver((entries, observer) => {
if (entries[0].isIntersecting) {
requestAnimationFrame(() => {
if (delay) {
setTimeout(() => {
gsap.to(spanRef.current, {
opacity: 1,
duration: 2
});
let shuffledText = () => {
let textArray = textInput.split("");
let newTextArray = [];
textArray.forEach(char => {
if (char === " ") {
return newTextArray.push(" ")
setReadyState(true);
}, delay);
} else {
gsap.to(spanRef.current, {
opacity: 1,
duration: 2
});
setReadyState(true);
}
newTextArray.push(chars[Math.floor(Math.random() * 85)])
})
return newTextArray.join("");
observer.unobserve(spanRef.current)
}
}, {
rootMargin: "0px 0px 0px 0px"
});
spanObserver.observe(spanRef.current)
}, [])
useEffect(() => {
if (!readyState) return;
requestAnimationFrame(() => {
textTimeout = setTimeout(() => {
if (timer === 7) {
setText(textInput);
return window.clearTimeout(textTimeout);
};
setText(prev => prev);
setRefresh(prev => prev + 1);
timer++
}, 200);
}, 300);
})
}, [refresh])
return (<span className="shuffled-text-span">{text.split("").map(char => <span key={keyNum++} style={{ animationDelay: Math.random() + "s", animationDuration: (Math.random() * 2) + "s" }}>{char}</span>)}</span>)
return (
<span className="shuffled-text-span" ref={ spanRef } style={ { opacity: 0 } }>
{ text.split("").map(char => <span key={ keyNum++ } style={ { animationDelay: Math.random() * 1.5 + "s", animationDuration: (Math.random() * 2) + "s" } }>{ char }</span>) }
</span>
)
}
export default TextShuffler

View File

@ -2,18 +2,84 @@ import React, { Fragment } from 'react';
import GeneralHeader from './GeneralHeader';
import Head from "next/head"
import GeneralFooter from './GeneralFooter';
import { gsap } from "gsap";
import threeJsAnimations from '../../functions/frontend/threeJsAnimations';
const GeneralLayout = ({ children, pageName }) => {
const [readyState, setReadyState] = React.useState(false)
React.useEffect(() => {
// barba.init({
// transitions: [{
// name: 'default-transition',
// leave() {
// // create your stunning leave animation here
// return gsap.to("main", {
// opacity: 1,
// duration: 1,
// delay: 2
// })
// },
// enter() {
// // create your amazing enter animation here
// return gsap.from("main", {
// opacity: 0,
// duration: 1,
// delay: 2
// })
// }
// }]
// });
window.addEventListener("load", () => {
setReadyState(true);
document.querySelectorAll("nav a").forEach((link) => {
let locationRegex = new RegExp(`${window.location.pathname}.*?`);
if (link.pathname === window.location.pathname) {
link.classList.add("active-page");
}
});
gsap.to("#main-content-wrapper", {
opacity: 1,
duration: 2,
delay: 1
})
gsap.to("#page-loader", {
opacity: 0,
duration: 0.5,
delay: 1,
pointerEvents: "none"
})
threeJsAnimations();
})
}, [])
const GeneralLayout = ({ children }) => {
return (
<Fragment>
<Head>
<meta name="keywords" content="UI/UX designer, Full Stack Web Developer, Web/graphic/motion designer, React Developer, NextJS developer, Node JS developer, Javascript Developer, Linux Ubuntu, DevOps, Nginx, MySQL developer, Freelancer" />
</Head>
<div id='page-loader' className='fixed w-screen h-screen bg-black flex items-center justify-center top-0 left-0' style={ { zIndex: 2000 } }>
<span className='text-xl'>Tben Loading ...</span>
</div>
{ readyState &&
<div id='main-content-wrapper' style={ { opacity: 0 } }>
<GeneralHeader />
<main>
{ children }
</main>
<GeneralFooter />
</div>
}
</Fragment>
)
}

62
package-lock.json generated
View File

@ -9,6 +9,8 @@
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"@barba/core": "^2.9.7",
"gsap": "^3.10.4",
"next": "^12.0.4",
"nodemailer": "^6.7.2",
"react": "^17.0.2",
@ -51,6 +53,15 @@
"node": ">=6.9.0"
}
},
"node_modules/@barba/core": {
"version": "2.9.7",
"resolved": "https://registry.npmjs.org/@barba/core/-/core-2.9.7.tgz",
"integrity": "sha512-GLtpty1fzWnd500AoUHd+hJoSCVElqth20P4W8Bf0IAA9nd1K5e8NbPnCegXC4KzOwV+JHk5DVofAZcoc+I54Q==",
"dependencies": {
"is-promise": "^2.1.0",
"path-to-regexp": "^3.0.0"
}
},
"node_modules/@next/env": {
"version": "12.1.0",
"resolved": "https://registry.npmjs.org/@next/env/-/env-12.1.0.tgz",
@ -642,6 +653,11 @@
"node": ">= 6"
}
},
"node_modules/gsap": {
"version": "3.10.4",
"resolved": "https://registry.npmjs.org/gsap/-/gsap-3.10.4.tgz",
"integrity": "sha512-6QatdkKxXCMfvCW4rM++0RqyLQAzFX5nwl3yHS0XPgkZBkiSEY3VZVbMltrdtsbER/xZonLtyHt684wRp4erlQ=="
},
"node_modules/has": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
@ -739,6 +755,11 @@
"node": ">=0.12.0"
}
},
"node_modules/is-promise": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz",
"integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ=="
},
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@ -799,9 +820,9 @@
}
},
"node_modules/minimist": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
"version": "1.2.6",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
"integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==",
"dev": true
},
"node_modules/nanoid": {
@ -944,6 +965,11 @@
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
"dev": true
},
"node_modules/path-to-regexp": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-3.2.0.tgz",
"integrity": "sha512-jczvQbCUS7XmS7o+y1aEO9OBVFeZBQ1MDSEqmO7xSoPgOPoowY/SxLpZ6Vh97/8qHZOteiCKb7gkG9gA2ZUxJA=="
},
"node_modules/path-type": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
@ -1516,6 +1542,15 @@
"js-tokens": "^4.0.0"
}
},
"@barba/core": {
"version": "2.9.7",
"resolved": "https://registry.npmjs.org/@barba/core/-/core-2.9.7.tgz",
"integrity": "sha512-GLtpty1fzWnd500AoUHd+hJoSCVElqth20P4W8Bf0IAA9nd1K5e8NbPnCegXC4KzOwV+JHk5DVofAZcoc+I54Q==",
"requires": {
"is-promise": "^2.1.0",
"path-to-regexp": "^3.0.0"
}
},
"@next/env": {
"version": "12.1.0",
"resolved": "https://registry.npmjs.org/@next/env/-/env-12.1.0.tgz",
@ -1902,6 +1937,11 @@
"is-glob": "^4.0.1"
}
},
"gsap": {
"version": "3.10.4",
"resolved": "https://registry.npmjs.org/gsap/-/gsap-3.10.4.tgz",
"integrity": "sha512-6QatdkKxXCMfvCW4rM++0RqyLQAzFX5nwl3yHS0XPgkZBkiSEY3VZVbMltrdtsbER/xZonLtyHt684wRp4erlQ=="
},
"has": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
@ -1972,6 +2012,11 @@
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
"dev": true
},
"is-promise": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz",
"integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ=="
},
"js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@ -2020,9 +2065,9 @@
}
},
"minimist": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
"version": "1.2.6",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
"integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==",
"dev": true
},
"nanoid": {
@ -2109,6 +2154,11 @@
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
"dev": true
},
"path-to-regexp": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-3.2.0.tgz",
"integrity": "sha512-jczvQbCUS7XmS7o+y1aEO9OBVFeZBQ1MDSEqmO7xSoPgOPoowY/SxLpZ6Vh97/8qHZOteiCKb7gkG9gA2ZUxJA=="
},
"path-type": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",

View File

@ -25,6 +25,8 @@
},
"homepage": "https://github.com/BenjaminToby/personal_site#readme",
"dependencies": {
"@barba/core": "^2.9.7",
"gsap": "^3.10.4",
"next": "^12.0.4",
"nodemailer": "^6.7.2",
"react": "^17.0.2",

View File

@ -1,13 +1,11 @@
import "../styles/main.css";
import "../styles/tw_main.css";
import { Fragment } from "react";
import Script from "next/script";
function MyApp({ Component, pageProps }) {
return (
<Fragment>
<Component {...pageProps} />
<Script src="/scripts/main.js" strategy="beforeInteractive" />
</Fragment>
);
}

16
pages/_document.js Normal file
View File

@ -0,0 +1,16 @@
import { Html, Head, Main, NextScript } from "next/document";
export default function Document() {
return (
<Html>
<Head>
{/* <script src="https://unpkg.com/@barba/core"></script> */}
<script src="/scripts/main.js" defer></script>
</Head>
<body className="bg-black">
<Main />
<NextScript />
</body>
</Html>
);
}

View File

@ -5,19 +5,16 @@ import GeneralLayout from '../layouts/general_layout/GeneralLayout'
import threeJsAnimations from '../functions/frontend/threeJsAnimations'
const about = () => {
React.useEffect(() => {
threeJsAnimations()
}, [])
return (
<GeneralLayout>
<GeneralLayout pageName="about">
<Head>
<title>About Me</title>
<meta name="description" content="Ben of all trade, master of all! Learn more about me" />
</Head>
<h1><TextShuffler textInput="Ben of all trade, master of all!" /></h1>
<h1><TextShuffler textInput="Ben of all trade, master of all!" delay={ 1000 } /></h1>
<span className='hero-sub-text'>
<TextShuffler textInput="Quick learner, adaptable, problem solver, curious. I strive to know the system, rather than the status quo. There's no problem too great: no knowledge too vast: no logic too complex. I thrive in difficult situations and complex problems: problem solving is now second nature to me: if you can think it, it can be done." />
<TextShuffler textInput="Quick learner, adaptable, problem solver, curious. I strive to know the system, rather than the status quo. There's no problem too great: no knowledge too vast: no logic too complex. I thrive in difficult situations and complex problems: problem solving is now second nature to me: if you can think it, it can be done." delay={ 1500 } />
</span>
<div className='w-full h-6'></div>

View File

@ -9,11 +9,6 @@ const contact = () => {
let [success, setSuccess] = React.useState(false);
React.useEffect(() => {
threeJsAnimations()
}, [])
return (
<GeneralLayout>
<Head>
@ -21,9 +16,9 @@ const contact = () => {
<meta name="description" content="Get in touch" />
</Head>
<h1><TextShuffler textInput="Great things await ..." /></h1>
<h1><TextShuffler textInput="Great things await ..." delay={ 1000 } /></h1>
<span className='hero-sub-text'>
<TextShuffler textInput="Let's talk" />
<TextShuffler textInput="Let's talk" delay={ 1500 } />
</span>
<form autoComplete='on' onSubmit={ (e) => { submitContactForm(e, setSuccess) } }>

View File

@ -5,18 +5,16 @@ import threeJsAnimations from '../functions/frontend/threeJsAnimations'
import GeneralLayout from '../layouts/general_layout/GeneralLayout'
const index = () => {
React.useEffect(() => {
threeJsAnimations()
}, [])
return (
<GeneralLayout>
<GeneralLayout pageName="home">
<Head>
<title>Benjamin Toby | Fullstack developer, UI UX designer</title>
<meta name="description" content="UI/UX designer, Full Stack Web Developer, Web/graphic/motion designer, React Developer, Next JS developer, Node JS developer, Javascript Developer, Linux Ubuntu, DevOps, Nginx, MySQL developer, Freelancer" />
</Head>
<h1><TextShuffler textInput="UI/UX designer, Full Stack Web Developer, Web/graphic/motion designer" /></h1>
<h1><TextShuffler textInput="UI/UX designer, Full Stack Web Developer, Web/graphic/motion designer" delay={ 1000 } /></h1>
<span className='hero-sub-text'>
<TextShuffler textInput="Hi, I'm Benjamin Toby, a fullstack web developer and UI/UX expert." />
<TextShuffler textInput="Hi, I'm Benjamin Toby, a fullstack web developer and UI/UX expert." delay={ 2000 } />
</span>
<div className="hero-ctas-section">
<a href='/documents/Benjamin_Toby_CV-updated.pdf' download={ true }>See my resume</a>

View File

@ -8,19 +8,15 @@ import threeJsAnimations from '../functions/frontend/threeJsAnimations'
const myWork = () => {
const portfolioEntries = require("../components/portfolioEntries.json");
React.useEffect(() => {
threeJsAnimations()
}, [])
return (
<GeneralLayout>
<Head>
<title>My Work | Tben</title>
<meta name="description" content="Some of my Work" />
</Head>
<h1><TextShuffler textInput="My Work" /></h1>
<h1><TextShuffler textInput="My Work" delay={ 1000 } /></h1>
<span className='hero-sub-text'>
<TextShuffler textInput="Some of my work ..." />
<TextShuffler textInput="Some of my work ..." delay={ 1500 } />
</span>
<div className='portfolio-entries-block mt-4'>

View File

@ -1,6 +1 @@
document.querySelectorAll("nav a").forEach((link) => {
let locationRegex = new RegExp(`${window.location.pathname}.*?`);
if (link.pathname === window.location.pathname) {
link.classList.add("active-page");
}
});

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -59,28 +59,16 @@
z-index: -10
}
.mt-10 {
margin-top: 2.5rem
}
.mt-auto {
margin-top: auto
}
.mb-2 {
margin-bottom: 0.5rem
}
.mb-1 {
margin-bottom: 0.25rem
}
.mt-4 {
margin-top: 1rem
}
.block {
display: block
.mt-10 {
margin-top: 2.5rem
}
.mb-1 {
margin-bottom: 0.25rem
}
.flex {
@ -91,21 +79,37 @@
height: 1.5rem
}
.h-screen {
height: 100vh
}
.w-full {
width: 100%
}
.w-screen {
width: 100vw
}
.flex-col {
flex-direction: column
}
.items-center {
align-items: center
}
.justify-center {
justify-content: center
}
.border {
border-width: 1px
}
.text-sm {
font-size: 0.875rem;
line-height: 1.25rem
.bg-black {
--tw-bg-opacity: 1;
background-color: rgb(0 0 0 / var(--tw-bg-opacity))
}
.text-xl {
@ -113,6 +117,11 @@
line-height: 1.75rem
}
.text-sm {
font-size: 0.875rem;
line-height: 1.25rem
}
.font-bold {
font-weight: 700
}
@ -121,10 +130,6 @@
opacity: 0.5
}
.opacity-20 {
opacity: 0.2
}
.opacity-40 {
opacity: 0.4
}