diff --git a/package-lock.json b/package-lock.json index aad3891..3d1e9d7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,11 @@ { - "name": "wedding-schedule", + "name": "portfolio-2023", "version": "1.0.0", "lockfileVersion": 2, "requires": true, "packages": { "": { - "name": "wedding-schedule", + "name": "portfolio-2023", "version": "1.0.0", "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index 4e01dd8..53345f1 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "wedding-schedule", + "name": "portfolio-2023", "version": "1.0.0", "description": "", "main": "index.js", diff --git a/src/_data/projects.json b/src/_data/projects.json index 60b22af..3d09225 100644 --- a/src/_data/projects.json +++ b/src/_data/projects.json @@ -1,19 +1,21 @@ [ { "slug": "flylocal", + "type": "client", "company": "FlyLocal", - "link": "https://start9.com", + "link": "https://iflylocal.com", "project": "data driven web application", "work": "design, architecture, front end, back end, database, devops", "technologies": [ "VueJS", "OpenStreetMaps" ], "basic-technologies": [ - "HTML", "SCSS", "SQL" + "HTML", "SCSS", "JavaScript", "SQL" ] }, { "slug": "start9", + "type": "client", "company": "Start9 Labs", "link": "https://start9.com", "project": "landing page & company website", @@ -22,12 +24,13 @@ "Eleventy", "GSAP" ], "basic-technologies": [ - "HTML", "SCSS" + "HTML", "SCSS", "JavaScript" ], "github": "https://github.com/start9labs/start9" }, { "slug": "graphic-vizion", + "type": "client", "company": "GraphicViZion", "link": "https://graphicvizion.com", "project": "suite of product websites and blogs", @@ -36,17 +39,46 @@ "Eleventy" ], "basic-technologies": [ - "HTML", "SCSS" + "HTML", "SCSS", "JavaScript" ] }, { "slug": "the-seasteading-institute", + "type": "client", "company": "The Seasteading Institute", "link": "https://seasteading.org", "project": "company website and blog", "work": "design, WP dev, maintenance, migration", "technologies": [ - "Wordpress" + "Wordpress", "SCSS" + ] + }, + { + "slug": "wear-vol", + "type": "client", + "company": "Vol Attire", + "link": "https://wearvol.com", + "project": "web shop", + "work": "design, architecture, full stack dev", + "technologies": [ + "custom ssg" + ], + "basic-technologies": [ + "HTML", "SCSS", "JavaScript" + ] + }, + { + "slug": "embassyos-fans", + "type": "personal", + "company": "EMBASSYOS:FANS", + "link": "https://embassyos.fans", + "project": "feedback platform", + "work": "devops, themeing, maintenance", + "technologies": [ + "Docker", "Coolify", "Linode" + ], + "basic-technologies": [ + "CSS" ] } ] \ No newline at end of file diff --git a/src/_includes/components/arrows-up.svg b/src/_includes/components/arrows-up.svg new file mode 100644 index 0000000..1740479 --- /dev/null +++ b/src/_includes/components/arrows-up.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/src/_includes/components/corner-right-down.svg b/src/_includes/components/corner-right-down.svg new file mode 100644 index 0000000..8df5e31 --- /dev/null +++ b/src/_includes/components/corner-right-down.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/_includes/components/external-link.svg b/src/_includes/components/external-link.svg new file mode 100644 index 0000000..acb4fa2 --- /dev/null +++ b/src/_includes/components/external-link.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/src/_includes/components/header.njk b/src/_includes/components/header.njk index 8a3b282..1f30255 100644 --- a/src/_includes/components/header.njk +++ b/src/_includes/components/header.njk @@ -9,4 +9,15 @@

est. 2007

+ \ No newline at end of file diff --git a/src/_includes/components/list.njk b/src/_includes/components/list.njk index 61e76d2..c2157a0 100644 --- a/src/_includes/components/list.njk +++ b/src/_includes/components/list.njk @@ -1,5 +1,21 @@ +

+ Freelance Work +

\ No newline at end of file + +

+ Personal Projects +

+ + \ No newline at end of file diff --git a/src/_includes/layouts/base.njk b/src/_includes/layouts/base.njk index a196506..cbca068 100644 --- a/src/_includes/layouts/base.njk +++ b/src/_includes/layouts/base.njk @@ -7,6 +7,7 @@ {{ title }} + diff --git a/src/assets/images/embassyos-fans.png b/src/assets/images/embassyos-fans.png new file mode 100644 index 0000000..e9acf60 Binary files /dev/null and b/src/assets/images/embassyos-fans.png differ diff --git a/src/assets/images/flylocal.png b/src/assets/images/flylocal.png new file mode 100644 index 0000000..05620d7 Binary files /dev/null and b/src/assets/images/flylocal.png differ diff --git a/src/assets/images/flylocal2.png~ b/src/assets/images/flylocal2.png~ new file mode 100644 index 0000000..97e2007 Binary files /dev/null and b/src/assets/images/flylocal2.png~ differ diff --git a/src/assets/images/wear-vol.png b/src/assets/images/wear-vol.png new file mode 100644 index 0000000..0f57a7b Binary files /dev/null and b/src/assets/images/wear-vol.png differ diff --git a/src/assets/js/landing.js b/src/assets/js/landing.js index 807efa2..654a630 100644 --- a/src/assets/js/landing.js +++ b/src/assets/js/landing.js @@ -1,110 +1,133 @@ gsap.registerPlugin(ScrollTrigger, ScrollSmoother); + +/* CREATE SMOOTHER */ + const smoother = ScrollSmoother.create({ wrapper: "#wrapper", content: "#content", - smooth: 1, + smooth: 2, normalizeScroll: true, // prevents address bar from showing/hiding on most devices, solves various other browser inconsistencies ignoreMobileResize: true, // skips ScrollTrigger.refresh() on mobile resizes from address bar showing/hiding effects: true, preventDefault: true, }); -// let title = document.querySelectorAll("h1"); -// title.forEach((element) => { -// gsap.fromTo( -// element, -// { -// textShadow: `.25rem .15rem 0 var(--c-offset)`, -// }, -// { -// scrollTrigger: { -// trigger: element, -// scrub: true, -// start: "center center", // element page -// end: "bottom top", -// scrub: true, - -// }, -// textShadow: `.25rem -.15rem 0 var(--c-offset)` -// } -// ); -// }); -// let projectImages = document.querySelectorAll(".project__image"); -// projectImages.forEach((projectImage) => { -// gsap.fromTo( -// projectImage, -// { -// boxShadow: `.5rem .5rem 0 var(--c-offset)`, -// }, -// { -// scrollTrigger: { -// trigger: projectImage, -// scrub: true, -// start: "bottom bottom", // element page -// end: "bottom top", -// scrub: true, - -// }, -// boxShadow: `.5rem -.5rem 0 var(--c-offset)` -// } -// ); -// }); +/* FADE IN PAGE */ -let wrapper = document.querySelectorAll("#wrapper"); - -// First, we need to create a ScrollTrigger and assign it to a variable: -const trigger = ScrollTrigger.create({ - trigger: "body", - start: "top top", - end: "bottom bottom", - scrub: true, - markers: true +gsap.to("#content", { + duration: 1, + //y: "-10rem", + //scale: 1, + opacity: 1, + filter: "blur(0px)", + delay: 0.5, }); -// Next, we can define the function that will be called on every scroll event: -function adjustShadows() { - // Get the horizontal and vertical scroll positions - //const scrollX = window.scrollX; - const scrollY = window.scrollY; - // Get the center of the viewport - //const viewportCenterX = window.innerWidth / 2; - const viewportCenterY = window.innerHeight / 2; +/* ANIMATE SECTIONS */ - // Loop through all divs and text elements on the page - const elements = document.querySelectorAll("h1, h2, span, label, .content__field"); - elements.forEach((element) => { - // Get the position of the element relative to the viewport - const elementRect = element.getBoundingClientRect(); - //const elementCenterX = elementRect.x + elementRect.width / 2; - const elementCenterY = elementRect.y + elementRect.height / 2; +const sections = document.querySelectorAll(".projects .project"); - // Calculate the distance between the element and the center of the viewport - //const distanceX = elementCenterX - viewportCenterX; - const distanceY = elementCenterY - viewportCenterY; - - // Calculate the angle between the element and the center of the viewport - //const angle = Math.atan2(distanceY, distanceX); - - // Calculate the distance between the element and the light source - //const distance = Math.sqrt(distanceX * distanceX + distanceY * distanceY); - - // Calculate the shadow offset based on the angle and distance - //const shadowOffsetX = distance * Math.cos(angle) / 40; - //const shadowOffsetY = distance * Math.sin(angle) / 40; - const shadowOffsetY = distanceY * 0.025 - - // Set the shadow of the element - element.style.textShadow = `0px ${shadowOffsetY}px 4px rgba(0, 0, 0, 0.3)`; +sections.forEach(function (section) { + gsap.from(section, { + duration: 0.5, + y: "5rem", + opacity: 0, + filter: "blur(10px)", + scrollTrigger: { + trigger: section, + start: "top 90%", // "triggerElement page" + //toggleActions: defaultActions, + }, }); -} +}); -// Finally, we can use the ScrollTrigger to call the adjustShadows function on every scroll event: -//window.addEventListener("scroll", adjustShadows); +const headers = document.querySelectorAll("h3"); + +headers.forEach(function (section) { + gsap.from(section, { + duration: 0.75, + //x: "10rem", + opacity: 0, + filter: "blur(10px)", + scrollTrigger: { + trigger: section, + start: "top 90%", // "triggerElement page" + //toggleActions: defaultActions, + }, + }); +}); +/* PIN CONTACT */ + +const contact = document.querySelector(".contact"); + +gsap.to(contact, { + //height: "initial", + //'min-height': "initial", + //padding: "1rem", + scrollTrigger: { + trigger: contact, + start: "top top", + pin: true, + pinSpacing: false, + endTrigger: 'body', // the element that the scrolling should stop at + end: 'bottom', // where the scrolling should stop + toggleActions: 'play none none reverse', // what happens when the element goes off screen + }, +}); + +// gsap.to("#scroll-to-top", { +// scrollTrigger: { +// trigger: contact, +// start: "top top", +// pin: true, +// pinSpacing: false, +// endTrigger: 'body', // the element that the scrolling should stop at +// end: 'bottom', // where the scrolling should stop +// toggleActions: 'play none none reverse', // what happens when the element goes off screen +// }, +// }); -ScrollTrigger.defaults({ scroller: smoother }); +/* SCROLL BUTTONS */ + +document.querySelector("#button-freelance-work").addEventListener("click", e => { + // scroll to the spot where .box-c is in the center. + // parameters: element, smooth, position + smoother.scrollTo("#freelance-work", true, "center center"); + // or you could animate the scrollTop: + // gsap.to(smoother, { + // scrollTop: smoother.offset(".box-c", "center center"), + // duration: 1 + // }); +}); + +document.querySelector("#button-personal-projects").addEventListener("click", e => { + // scroll to the spot where .box-c is in the center. + // parameters: element, smooth, position + smoother.scrollTo("#personal-projects", true, "center center"); + + // or you could animate the scrollTop: + // gsap.to(smoother, { + // scrollTop: smoother.offset(".box-c", "center center"), + // duration: 1 + // }); +}); + +document.querySelector("#back-to-top").addEventListener("click", e => { + // scroll to the spot where .box-c is in the center. + // parameters: element, smooth, position + smoother.scrollTo("h1", true, "center center"); + + // or you could animate the scrollTop: + // gsap.to(smoother, { + // scrollTop: smoother.offset(".box-c", "center center"), + // duration: 1 + // }); +}); + +//ScrollTrigger.defaults({ scroller: smoother }); // this screws up click events \ No newline at end of file diff --git a/src/assets/styles/main.scss b/src/assets/styles/main.scss index 700bb9e..69c8e7f 100644 --- a/src/assets/styles/main.scss +++ b/src/assets/styles/main.scss @@ -1,11 +1,13 @@ @import "normalize"; @import "milligram"; +@import "normalize-custom"; @import "tusker"; @import url("https://api.fonts.coollabs.io/css2?family=Cutive+Mono&display=swap"); @import url("https://api.fonts.coollabs.io/css2?family=Work+Sans:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap"); :root { + scroll-behavior: unset; font-size: 2vmin; --c-bkg: #fff8f1; --c-text: #613100; @@ -31,6 +33,8 @@ h2 { #content { background-color: var(--c-bkg); + opacity: 0; + filter: blur(10px); // background-image: url('../../assets/images/bkg.svg'); // background-repeat: repeat; // background-size: 250px 250px; @@ -56,20 +60,11 @@ html{ body { color: var(--c-text); + font-display: optional; font-family: "Cutive Mono", "Courier New", Courier, monospace; } -h1, -h2, -h3, -ul, -label, -ul ul, -li { - padding: 0; - margin: 0; - line-height: 1; -} + svg{ transition: all 0.2s ease-in-out; @@ -78,7 +73,7 @@ svg{ .btn { display: flex; margin: 0; - padding: 0.5rem 1.5rem; + padding: 0.4rem 1rem; line-height: 1; align-items: center; height: auto; @@ -97,15 +92,10 @@ svg{ } } -li { - list-style-type: none; -} -a { - text-decoration: none; -} h1 { + font-display: optional; font-family: "Tusker Grotesk 2500"; text-transform: uppercase; font-size: 15rem; @@ -115,12 +105,19 @@ h2 { font-size: 2rem; } +h3 { + margin-top: 7rem; + margin-bottom: 2rem; + font-size: 3rem; +} + header { display: flex; flex-direction: column; align-items: center; justify-content: center; - height: calc(75vh - var(--outside-padding)); + height: calc(100vh - (3 * var(--outside-padding)) - (3.1 * 1rem)); + //height: calc(100vh - (2 * var(--outside-padding))); gap: 1rem; h2.left { align-self: flex-start; @@ -131,24 +128,59 @@ header { } } +.menu{ + display: flex; + font-size: 1rem; + gap: 1rem; + flex-direction: column; + align-self: flex-start; + + li{ + border-inline-start: .5rem var(--c-text-light); + padding-inline-start: .2rem; + + a{ + display: flex; + align-items: flex-start; + gap: .5rem; + + svg{ + height: .9rem; + margin-top: .5em; + } + } + } +} + .contact { - min-height: 25vh; + //min-height: 25vh; width: 100vw; box-sizing: border-box; padding: var(--outside-padding); display: flex; + flex-wrap: wrap; align-items: center; justify-content: space-between; background-color: var(--c-offset); gap: 2rem; + z-index: 1; a{ color: var(--c-text); text-decoration: underline; + text-decoration-line: dotted; + text-decoration-color: #6130002f; + text-decoration-thickness: 0.05em; + //text-decoration-style: dotted; + text-underline-offset: .2em; + transition: all 0.2s ease-in-out; + &:hover{ + transform: scale(1.02); + } } #input-container{ - gap: 1rem; + gap: .5rem; align-items: stretch; } @@ -159,7 +191,7 @@ header { line-height: 1; align-items: center; min-height: auto; - max-width: calc(25ch + .2rem); + max-width: calc(15ch + .4rem); background: transparent; color: var(--c-text); border: .12rem solid var(--c-text); @@ -170,12 +202,15 @@ header { } } -@media screen and (max-width: 768px) { - .contact { - flex-direction: column; - align-items: flex-start; - justify-content: center; +@media screen and (max-width: 970px) { + header { + height: calc(100vh - (3 * var(--outside-padding)) - (6.1 * 1rem)); } + // .contact { + // flex-direction: column; + // align-items: flex-start; + // justify-content: center; + // } } main { @@ -188,6 +223,7 @@ main { margin: 3rem; padding-bottom: 25rem; } + .projects { display: flex; flex-direction: column; @@ -221,31 +257,34 @@ main { border-radius: 0; } - .project__image-wrapper { - border-radius: 0; - background-color: white; - } + // .project__image-wrapper { + // border-radius: 0; + // background-color: white; + // } .project__image { border-radius: 0; filter: none; mix-blend-mode: normal; + transform: scale(1.02); } } - .project__image-wrapper { - border-radius: 1.5rem; - background-color: #997d6322; - transition: all 0.2s ease-in-out; - } + // .project__image-wrapper { + // border-radius: 1.5rem; + // background-color: #997d6322; + // transition: all 0.2s ease-in-out; + // } .project__image { border-radius: 1.5rem; box-shadow: var(--shadow); border: 1px solid var(--c-text); - transition: all 0.2s ease-in-out; - filter: grayscale(100%); - mix-blend-mode: multiply; + transition: 0.2s all 0.5s ease-in-out; + //filter: saturate(0) sepia(30%); + filter: multiply(rgba(97, 49, 0, 0.6)); + max-width: none; + width: 16rem; } .project__content { @@ -261,6 +300,7 @@ main { label { font-size: 0.5rem; + font-display: optional; font-family: "Work Sans", sans-serif; text-transform: uppercase; font-weight: 400; diff --git a/src/assets/styles/normalize-custom.scss b/src/assets/styles/normalize-custom.scss new file mode 100644 index 0000000..a74b61e --- /dev/null +++ b/src/assets/styles/normalize-custom.scss @@ -0,0 +1,28 @@ +h1, +h2, +h3, +ul, +label, +ul ul, +li { + padding: 0; + margin: 0; + line-height: 1; +} + +li { + list-style-type: none; + } + + a { + text-decoration: none; + cursor: pointer; + color: var(--c-text); + &:hover{ + color: var(--c-text-light); + + svg{ + stroke: var(--c-text-light); + } + } + } \ No newline at end of file diff --git a/src/index.njk b/src/index.njk index 87790cc..268d86b 100644 --- a/src/index.njk +++ b/src/index.njk @@ -1,7 +1,6 @@ --- -title: The Schedule +title: "Spencer Flagg: Designer, Developer" layout: layouts/base.njk -updated: July 15 --- {% include "components/header.njk" %}