diff --git a/locales/de/translation.json b/locales/de/translation.json index 2f7e627..181eca8 100644 --- a/locales/de/translation.json +++ b/locales/de/translation.json @@ -1,36 +1,45 @@ { - "siteDescription": "Hallo, ich bin Kevin Kandlbinder, ein Entwickler und Hobby-Fotograf aus Norddeutschland.", - "imprint": "Impressum", - "datasec": "Datenschutz", - "disclaimer": "Disclaimer", - "projects": "Projekte", - "project": "Projekt", - "social": "Soziales", - "homeHello": "Hallo, ich bin", - "homeMe": "Ich bin", - "homeWebDeveloper": "Web Developer", - "homeMyLocation": "Quickborn, Schleswig-Holstein, Deutschland", - "donationCatchphrase": "Gefällt dir was du siehst? Spende doch etwas.", - "homeImageCredit": "Portrait aufgenommen von Jannik Kiel", - "de": "Deutsch", - "en": "Englisch", - "projectAboutHeader": "Über {{projectName}}", - "projectViewGitHub": "Auf GitHub anschauen", - "projectViewWebsite": "Projekt-Website anschauen", - "projectsDescription": "Das ist woran ich grade arbeite oder woran ich gearbeitet habe.", - "projectView": "Anschauen", - "socialDescriptionWithLink": "Finde mich auf anderen Plattformen oder <1>besuche meine Freunde!", - "socialDescription": "Finde mich auf anderen Plattformen!", - "friends": "Freunde", - "friendsDescription": "In dieser Liste stehen Freunde von mir und meiner Seite. Schau doch bei ihnen mal rein, wenn du mehr interessante Projekte sehen willst.", - "donateThanksText": "Ich finde es schön, dass du meine Arbeit schön findest und das zeigst! Sende mir gerne eine E-Mail an <1>{{contactEmail}} wenn du mit mir über irgendwas reden möchtest!", - "donateThanks": "Danke für die Spende!", - "donateDescription": "Hey! Es sieht so aus als würdest du über eine Spende nachdenken. Das ist nett! Wenn du ein bestimmtes Projekt unterstützen willst, schreibe deine Wünsche gerne in den Spendenkommentar.", - "donate": "Spenden", - "featuredProjects": "Vorgestellte Projekte", - "seeMore": "Mehr Projekte erkunden", - "donateGitHub": "Du kannst mich mit dem folgenden Button ganz einfach über GitHub Sponsors unterstützen!", - "donatePayPal": "Wenn du mich lieber über PayPal unterstützen willst ist hier der Button für dich:", - "sponsorGitHub": "Über GitHub unterstützen", - "mySkills": "Meine Fähigkeiten" + "siteDescription": "Hallo, ich bin Kevin Kandlbinder, ein Entwickler und Hobby-Fotograf aus Norddeutschland.", + "imprint": "Impressum", + "datasec": "Datenschutz", + "disclaimer": "Disclaimer", + "projects": "Projekte", + "project": "Projekt", + "social": "Soziales", + "homeHello": "Hallo, ich bin", + "homeMe": "Ich bin", + "homeWebDeveloper": "Web Developer", + "homeMyLocation": "Quickborn, Schleswig-Holstein, Deutschland", + "donationCatchphrase": "Gefällt dir was du siehst? Spende doch etwas.", + "homeImageCredit": "Portrait aufgenommen von Jannik Kiel", + "de": "Deutsch", + "en": "Englisch", + "projectAboutHeader": "Über {{projectName}}", + "projectViewGitHub": "Auf GitHub anschauen", + "projectViewWebsite": "Projekt-Website anschauen", + "projectsDescription": "Das ist woran ich grade arbeite oder woran ich gearbeitet habe.", + "projectView": "Anschauen", + "socialDescriptionWithLink": "Finde mich auf anderen Plattformen oder <1>besuche meine Freunde!", + "socialDescription": "Finde mich auf anderen Plattformen!", + "friends": "Freunde", + "friendsDescription": "In dieser Liste stehen Freunde von mir und meiner Seite. Schau doch bei ihnen mal rein, wenn du mehr interessante Projekte sehen willst.", + "donateThanksText": "Ich finde es schön, dass du meine Arbeit schön findest und das zeigst! Sende mir gerne eine E-Mail an <1>{{contactEmail}} wenn du mit mir über irgendwas reden möchtest!", + "donateThanks": "Danke für die Spende!", + "donateDescription": "Hey! Es sieht so aus als würdest du über eine Spende nachdenken. Das ist nett! Wenn du ein bestimmtes Projekt unterstützen willst, schreibe deine Wünsche gerne in den Spendenkommentar.", + "donate": "Spenden", + "featuredProjects": "Vorgestellte Projekte", + "seeMore": "Mehr Projekte erkunden", + "donateGitHub": "Du kannst mich mit dem folgenden Button ganz einfach über GitHub Sponsors unterstützen!", + "donatePayPal": "Wenn du mich lieber über PayPal unterstützen willst ist hier der Button für dich:", + "sponsorGitHub": "Über GitHub unterstützen", + "mySkills": "Meine Fähigkeiten", + "about": "Über", + "explore": "Erkunde", + "myProjects": "meine Projekte", + "discover": "Entdecke", + "mySocials": "meine Accounts", + "learn": "Erfahre", + "moreAboutMe": "mehr über mich", + "home": "Home", + "menu": "Menü" } diff --git a/locales/en/translation.json b/locales/en/translation.json index 2f34cda..892ec13 100644 --- a/locales/en/translation.json +++ b/locales/en/translation.json @@ -1,36 +1,45 @@ { - "siteDescription": "Hello, I am Kevin Kandlbinder, a developer and hobby photographer from northern Germany.", - "imprint": "Imprint", - "datasec": "Data Protection", - "disclaimer": "Disclaimer", - "projects": "Projects", - "project": "Project", - "social": "Social", - "homeHello": "Hello, I am", - "homeMe": "I am", - "homeWebDeveloper": "a web developer", - "homeMyLocation": "Quickborn, Schleswig-Holstein, Germany", - "donationCatchphrase": "Like what you're seeing? Consider donating.", - "homeImageCredit": "Portrait taken by Jannik Kiel", - "de": "German", - "en": "English", - "projectAboutHeader": "About {{projectName}}", - "projectViewGitHub": "View on GitHub", - "projectViewWebsite": "View Project-Website", - "projectsDescription": "This is what I am working on or have worked on.", - "projectView": "View", - "socialDescriptionWithLink": "Find me on other platforms or <1>visit my friends!", - "socialDescription": "Find me on other platforms!", - "friends": "Friends", - "friendsDescription": "In this list you can find friends of mine and this site. Feel free to check them out for more interesting projects.", - "donate": "Donate", - "donateDescription": "Hey! It looks like you're thinking about donating to me. That's nice of you! If you want your donation to go towards a specific project, feel free to write your wishes into the donation comment.", - "donateThanks": "Thanks for donating!", - "donateThanksText": "I really appreciate you appreciating my work and showing it! Feel free to mail me at <1>{{contactEmail}} if you have anything you want to talk about!", - "featuredProjects": "Featured Projects", - "seeMore": "Explore more Projects", - "donateGitHub": "You can very easily support me via GitHub Sponsors using the following button!", - "donatePayPal": "If you'd rather support me via PayPal the following button is for you:", - "sponsorGitHub": "Sponsor using GitHub", - "mySkills": "My Skills" + "siteDescription": "Hello, I am Kevin Kandlbinder, a developer and hobby photographer from northern Germany.", + "imprint": "Imprint", + "datasec": "Data Protection", + "disclaimer": "Disclaimer", + "projects": "Projects", + "project": "Project", + "social": "Social", + "homeHello": "Hello, I am", + "homeMe": "I am", + "homeWebDeveloper": "a web developer", + "homeMyLocation": "Quickborn, Schleswig-Holstein, Germany", + "donationCatchphrase": "Like what you're seeing? Consider donating.", + "homeImageCredit": "Portrait taken by Jannik Kiel", + "de": "German", + "en": "English", + "projectAboutHeader": "About {{projectName}}", + "projectViewGitHub": "View on GitHub", + "projectViewWebsite": "View Project-Website", + "projectsDescription": "This is what I am working on or have worked on.", + "projectView": "View", + "socialDescriptionWithLink": "Find me on other platforms or <1>visit my friends!", + "socialDescription": "Find me on other platforms!", + "friends": "Friends", + "friendsDescription": "In this list you can find friends of mine and this site. Feel free to check them out for more interesting projects.", + "donate": "Donate", + "donateDescription": "Hey! It looks like you're thinking about donating to me. That's nice of you! If you want your donation to go towards a specific project, feel free to write your wishes into the donation comment.", + "donateThanks": "Thanks for donating!", + "donateThanksText": "I really appreciate you appreciating my work and showing it! Feel free to mail me at <1>{{contactEmail}} if you have anything you want to talk about!", + "featuredProjects": "Featured Projects", + "seeMore": "Explore more Projects", + "donateGitHub": "You can very easily support me via GitHub Sponsors using the following button!", + "donatePayPal": "If you'd rather support me via PayPal the following button is for you:", + "sponsorGitHub": "Sponsor using GitHub", + "mySkills": "My Skills", + "about": "About", + "explore": "Explore", + "myProjects": "my projects", + "discover": "Discover", + "mySocials": "my socials", + "learn": "Learn", + "moreAboutMe": "more about me", + "home": "Home", + "menu": "Menu" } diff --git a/package.json b/package.json index 79e5fbf..a3078f5 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,7 @@ "gatsby-source-filesystem": "3.14.0", "gatsby-transformer-json": "3.14.0", "gatsby-transformer-sharp": "3.14.0", + "hamburger-react": "^2.4.1", "i18next": "21.3.1", "locale": "0.1.0", "lucide-react": "0.16.11", diff --git a/src/_mixins.scss b/src/_mixins.scss index f9db90a..3fcfae6 100644 --- a/src/_mixins.scss +++ b/src/_mixins.scss @@ -9,7 +9,7 @@ @mixin cardGeneric { border-radius: 5px; overflow: hidden; - box-shadow: -1px 11px 33px -10px rgba(127, 127, 127, 0.3); + box-shadow: -1px 11px 33px -10px rgba(27, 27, 27, 0.3); transition: transform 0.25s, box-shadow 0.25s, background-color 0.25s, color 0.25s; color: $textColor; diff --git a/src/components/navigation.js b/src/components/navigation.js index c01e94e..31cc1d8 100644 --- a/src/components/navigation.js +++ b/src/components/navigation.js @@ -1,12 +1,56 @@ +/* eslint-disable no-undef */ import React, { useEffect, useState } from "react"; import PropTypes from "prop-types"; import { Trans, Link } from "gatsby-plugin-react-i18next"; import { graphql, StaticQuery } from "gatsby"; +import { createPortal } from "react-dom"; import * as styles from "./navigation.module.scss"; +import { X } from "lucide-react"; +import { Fade as Hamburger } from 'hamburger-react'; + +const OffScreenNav = ({active, close}) => { + if(typeof window === "undefined") { + return null; + } + + return createPortal(
+
+ + menu + + home + + + about + + + projects + + + social + +
+
, window.document.body) +} const Navigation = ({ isHome }) => { let [atTop, setAtTop] = useState(false); + const [offscreenNavActive, setOffscreenNavActive] = useState(false); + + const closeOffscreenNav = () => setOffscreenNavActive(false); const updateTransparency = () => { if (typeof window === "undefined") return; @@ -52,6 +96,7 @@ const Navigation = ({ isHome }) => { } > ); diff --git a/src/components/navigation.module.scss b/src/components/navigation.module.scss index 83a264f..2a98fd4 100644 --- a/src/components/navigation.module.scss +++ b/src/components/navigation.module.scss @@ -1,6 +1,75 @@ @import "../variables"; @import "../mixins"; +.offscreenNav { + position: fixed; + top: 0; + left: 120px; + width: 100%; + height: 100%; + z-index: 1200; + background-color: rgba($background, 0.9); + backdrop-filter: blur(10px); + color: white; + overflow: auto; + opacity: 0; + transition: opacity .25s, left .25s; + pointer-events: none; + overscroll-behavior: contain; + + &.active { + left: 0; + opacity: 1; + pointer-events: auto; + } + + @media(prefers-color-scheme: light) { + background-color: rgba($lightBackground, 0.9); + color: black; + } + + .inner { + display: flex; + flex-direction: column; + max-width: $layoutWidth; + margin: 0 auto; + position: relative; + + text-align: center; + font-size: 1.25em; + + .close { + position: absolute; + top: 0; + right: 0; + padding: $layoutPadding; + color: inherit; + background-color: transparent; + border: none; + font: inherit; + } + + > a { + text-decoration: underline dotted currentColor; + } + + > * { + padding: $layoutPadding; + color: inherit; + + &.active { + border-left: 3px solid white; + border-right: 3px solid white; + + @media(prefers-color-scheme: light) { + border-left: 3px solid black; + border-right: 3px solid black; + } + } + } + } +} + .topBar { position: fixed; top: 0; @@ -40,8 +109,18 @@ padding-right: $layoutPadding; } + .hamburger { + display: none; + height: 43px; + + @media(max-width: 500px) { + display: block; + } + } + a { - display: block; + display: flex; + align-items: center; padding: 10px $layoutPadding; color: inherit; text-decoration: none; @@ -59,6 +138,12 @@ border-color: $accentColor; } } + + @media(max-width: 500px) { + &:not(.logo) { + display: none; + } + } } } } diff --git a/src/layouts/default.scss b/src/layouts/default.scss index 2db4737..b4b3a69 100644 --- a/src/layouts/default.scss +++ b/src/layouts/default.scss @@ -17,6 +17,7 @@ html, width: 100%; min-height: 100vh; font-family: $mainFont; + scroll-behavior: smooth; } #gatsby-focus-wrapper { diff --git a/src/pages/about.js b/src/pages/about.js new file mode 100644 index 0000000..c55cc72 --- /dev/null +++ b/src/pages/about.js @@ -0,0 +1,217 @@ +import * as React from "react"; +import Layout from "../layouts/default"; +import PropTypes from "prop-types"; + +import * as styles from "./index.module.scss"; +import * as projectStyles from "./projects.module.scss"; + +import { Trans, Link } from "gatsby-plugin-react-i18next"; +import { graphql } from "gatsby"; +import { MDXRenderer } from "gatsby-plugin-mdx"; +import { GatsbyImage } from "gatsby-plugin-image"; + +import anime from "animejs"; + +import { ArrowRight } from "lucide-react"; +import { useTranslation } from "react-i18next"; + +export const query = graphql` + query GetProjectsAndSkills($language: String) { + allSkillsJson(sort: { fields: type, order: ASC }) { + nodes { + name + type + href + } + } + allProjectsJson( + filter: { lang: { eq: $language }, featured: { gte: 0 } } + sort: { fields: featured, order: ASC } + ) { + nodes { + lang + urlname + name + image { + childImageSharp { + gatsbyImageData(placeholder: BLURRED, layout: FULL_WIDTH) + } + } + shortDescription + featured + } + } + locales: allLocale(filter: { language: { eq: $language } }) { + edges { + node { + ns + data + language + } + } + } + file( + sourceInstanceName: { eq: "textblocks" } + relativeDirectory: { eq: "home/about" } + name: { eq: $language } + ) { + id + childMdx { + body + } + name + } + } +`; + +const AboutPage = (props) => { + const {t} = useTranslation(); + + React.useEffect(() => { + if (typeof window === "undefined") return; + + anime({ + targets: [ + "." + styles.profileCard + " > span", + "." + styles.profileCard + " a", + ], + opacity: [0, 1], + translateX: [100, 0], + duration: 250, + delay: anime.stagger(20), + easing: "easeInOutCirc", + }); + anime({ + targets: ["." + styles.profileImageDummy], + translateX: [0, -3], + translateY: [0, 3], + duration: 250, + easing: "easeInOutCirc", + }); + anime({ + targets: ["." + styles.profileImage], + translateX: [0, 4], + translateY: [0, -4], + duration: 250, + easing: "easeInOutCirc", + }); + }, []); + let file = props.data.file; + + return ( + + +
+
+
+ {file.childMdx.body} +
+
+

+ mySkills +

+
+ {props.data.allSkillsJson.nodes.map((skill) => { + return skill.href ? ( + + {skill.name} + + ) : ( + + {skill.name} + + ); + })} +
+
+
+
+
+
+

+ featuredProjects +

+
+ {props.data.allProjectsJson.nodes.map((project) => { + return ( + +
+
+ +
+
+ + {project.name} + + + {project.shortDescription} + +
+
+ + ); + })} +
+ + seeMore{" "} + + +
+
+ +
+ + donationCatchphrase + + +
+ +
+ ); +}; + +AboutPage.propTypes = { + data: PropTypes.object.isRequired, +}; + +export default AboutPage; diff --git a/src/pages/index.js b/src/pages/index.js index 3624d0f..e0501c8 100644 --- a/src/pages/index.js +++ b/src/pages/index.js @@ -3,12 +3,10 @@ import Layout from "../layouts/default"; import PropTypes from "prop-types"; import * as styles from "./index.module.scss"; -import * as projectStyles from "./projects.module.scss"; import { Trans, Link } from "gatsby-plugin-react-i18next"; import { graphql } from "gatsby"; -import { MDXRenderer } from "gatsby-plugin-mdx"; -import { StaticImage, GatsbyImage } from "gatsby-plugin-image"; +import { StaticImage } from "gatsby-plugin-image"; import anime from "animejs"; @@ -28,30 +26,6 @@ export const query = graphql` contactMastodonHref } } - allSkillsJson(sort: { fields: type, order: ASC }) { - nodes { - name - type - href - } - } - allProjectsJson( - filter: { lang: { eq: $language }, featured: { gte: 0 } } - sort: { fields: featured, order: ASC } - ) { - nodes { - lang - urlname - name - image { - childImageSharp { - gatsbyImageData(placeholder: BLURRED, layout: FULL_WIDTH) - } - } - shortDescription - featured - } - } locales: allLocale(filter: { language: { eq: $language } }) { edges { node { @@ -61,17 +35,6 @@ export const query = graphql` } } } - file( - sourceInstanceName: { eq: "textblocks" } - relativeDirectory: { eq: "home/about" } - name: { eq: $language } - ) { - id - childMdx { - body - } - name - } } `; @@ -109,7 +72,6 @@ const IndexPage = (props) => { }, []); let meta = props.data.site.siteMetadata; - let file = props.data.file; return ( { - -
-
-
- {file.childMdx.body} -
-
-

- mySkills -

-
- {props.data.allSkillsJson.nodes.map((skill) => { - return skill.href ? ( - - {skill.name} - - ) : ( - - {skill.name} - - ); - })} +
+
+ +
+ {t("explore")}{" "} + {t("myProjects")}
-
-
+ + + +
+ {t("discover")}{" "} + {t("mySocials")} +
+ + + +
+ {t("learn")}{" "} + {t("moreAboutMe")} +
+ + +
{ -
-
-

- featuredProjects -

-
- {props.data.allProjectsJson.nodes.map((project) => { - return ( - -
-
- -
-
- - {project.name} - - - {project.shortDescription} - -
-
- - ); - })} -
- - seeMore{" "} - - -
-
- -
- - donationCatchphrase - - -
-
); }; diff --git a/src/pages/index.module.scss b/src/pages/index.module.scss index affa961..78db74c 100644 --- a/src/pages/index.module.scss +++ b/src/pages/index.module.scss @@ -3,15 +3,21 @@ .heroSection { width: 100%; - height: 600px; + flex-grow: 1; overflow: hidden; + display: flex; + flex-direction: column; + min-height: 800px; + //scroll-snap-align: start; + padding-top: 100px; + position: relative; .heroSectionBg, .heroSectionBgOver { position: absolute; width: 100%; max-width: unset; - height: 600px; + height: 100%; padding: 0; @media (pointer: coarse), (pointer: none) { @@ -19,9 +25,16 @@ } } + .spacer { + flex-grow: 1; + padding: 0; + margin: 0; + } + .heroSectionBg { /*background: radial-gradient(ellipse at top left, #1f0ba659, transparent), radial-gradient(ellipse at bottom right, #4a086829, transparent);*/ + margin-top: -100px; background: linear-gradient(45deg, #000850 0%, #000320 100%), radial-gradient(100% 225% at 100% 0%, #ff6928 0%, #000000 100%), @@ -38,23 +51,70 @@ #0f0a3c 100% ); background-blend-mode: screen, overlay, hard-light, normal; + } .heroSectionBgOver { - background: linear-gradient(to bottom, transparent 80%, $background); - transition: background-image 0.25s; + bottom: 0; + height: 150px; + /*background-color: $background; + transition: background-color 0.25s, box-shadow 0.25s;*/ + + @media(max-width: 950px) { + display: none; + } + @media (prefers-color-scheme: light) { - background: linear-gradient( - to bottom, - transparent 90%, - $lightBackground - ); + background-color: $lightBackground; } } - @media (pointer: coarse), (pointer: none) { - height: 700px; + .landingCta { + position: relative; + display: flex; + justify-content: space-around; + + @media(max-width: 1000px) { + flex-direction: column; + bottom: 0; + } + + a { + @include cardGeneric; + display: flex; + padding: $layoutPadding; + background-color: $background; + margin: $layoutPadding; + color: $textColor; + font-size: 1.6em; + text-decoration: none; + border-radius: 10px; + align-items: center; + + @media(max-width: 1000px) { + margin: 10px; + font-size: 1.2em; + } + + > svg { + margin-left: $layoutPadding; + flex-shrink: 0; + } + + > div { + display: flex; + flex-direction: column; + flex-grow: 1; + flex-shrink: 0; + + .ctaAccent { + color: $accentColor; + font-weight: 700; + margin-right: 10px; + } + } + } } .profile { @@ -62,9 +122,7 @@ left: 50%; width: calc(90% - 40px); max-width: 600px; - max-height: 400px; transform: translate(-50%, 0%); - top: 100px; .hello { font-weight: 100; @@ -157,7 +215,7 @@ clip-path: polygon(14% 4%, 95% 1%, 88% 96%, 2% 89%); } - @media (max-width: 590px) { + @media (max-width: 690px) { .profileImage, .profileImageDummy { display: none; @@ -212,7 +270,7 @@ .aboutSection { > article { display: flex; - align-items: center; + align-items: flex-start; > div { width: calc(50% - 40px); diff --git a/yarn.lock b/yarn.lock index c0e3a1c..8884a09 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6590,6 +6590,11 @@ gzip-size@5.1.1: duplexer "^0.1.1" pify "^4.0.1" +hamburger-react@^2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/hamburger-react/-/hamburger-react-2.4.1.tgz#44fac99c30720fe8ed098b2a33e919b14b3e007e" + integrity sha512-oqG9CrTVi8wM/dyQQh3JJOOfEiol9ChLOqwtjx+hFyRu0nYfe2ymNmzi2wtfQTDyExUdqETdyACZV9KZ9wpApA== + hard-rejection@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/hard-rejection/-/hard-rejection-2.1.0.tgz#1c6eda5c1685c63942766d79bb40ae773cecd883"