Run prettier on code

This commit is contained in:
Kevin Kandlbinder 2021-04-12 13:02:38 +00:00 committed by GitHub
parent d542206091
commit b8057f0e25
51 changed files with 28270 additions and 26529 deletions

View file

@ -1,17 +1,18 @@
// eslint-disable-next-line no-undef
module.exports = {
"siteName": "KevinK.dev",
"siteAuthor": "@Unkn0wnKevin",
"siteURL": "https://kevink.dev",
"payPalMail": "kevin@1in9.net",
"siteKeywords": "Kevin Kandlbinder, Kevin, Kandlbinder, Web, Web Developer, Developer, JavaScript, PHP, Java, Photos, Fotos",
"iconPath": "src/images/fullbglogo@10x.png",
"languages": ["en", "de"],
"contactEmail": "kevin@kevink.dev",
"contactPhone": "+4941068068004",
"mapsLink": "https://goo.gl/maps/KVq9z1PVaVP2",
"contactTwitter": "Unkn0wnKevin",
"contactGitHub": "Unkn0wnCat",
"contactMastodon": "@kevin@1in1.net",
"contactMastodonHref": "https://mastodon.1in1.net/@kevin"
};
// eslint-disable-next-line no-undef
module.exports = {
siteName: "KevinK.dev",
siteAuthor: "@Unkn0wnKevin",
siteURL: "https://kevink.dev",
payPalMail: "kevin@1in9.net",
siteKeywords:
"Kevin Kandlbinder, Kevin, Kandlbinder, Web, Web Developer, Developer, JavaScript, PHP, Java, Photos, Fotos",
iconPath: "src/images/fullbglogo@10x.png",
languages: ["en", "de"],
contactEmail: "kevin@kevink.dev",
contactPhone: "+4941068068004",
mapsLink: "https://goo.gl/maps/KVq9z1PVaVP2",
contactTwitter: "Unkn0wnKevin",
contactGitHub: "Unkn0wnCat",
contactMastodon: "@kevin@1in1.net",
contactMastodonHref: "https://mastodon.1in1.net/@kevin",
};

View file

@ -1,6 +1,6 @@
{
"profession": "Full-Stack-Developer",
"name": "Feuerhamster",
"url": "https://hamsterlabs.de",
"imageURL": "https://cdn.kevink.dev/assets/friends/feuerhamster.png"
}
{
"profession": "Full-Stack-Developer",
"name": "Feuerhamster",
"url": "https://hamsterlabs.de",
"imageURL": "https://cdn.kevink.dev/assets/friends/feuerhamster.png"
}

View file

@ -1,6 +1,6 @@
{
"profession": "",
"name": "Jannik Kiel",
"url": "https://unsplash.com/@jannikkiel",
"imageURL": "https://source.unsplash.com/user/jannikkiel/300x300"
}
{
"profession": "",
"name": "Jannik Kiel",
"url": "https://unsplash.com/@jannikkiel",
"imageURL": "https://source.unsplash.com/user/jannikkiel/300x300"
}

View file

@ -1,6 +1,6 @@
{
"profession": "Systemadministrator",
"name": "Timo Strüker",
"url": "https://strueker.dev",
"imageURL": "https://cdn.kevink.dev/assets/friends/timo.jpg"
}
{
"profession": "Systemadministrator",
"name": "Timo Strüker",
"url": "https://strueker.dev",
"imageURL": "https://cdn.kevink.dev/assets/friends/timo.jpg"
}

View file

@ -1,12 +1,12 @@
{
"urlname": "foobar",
"lang": "ignoreme",
"name": "foobar",
"shortDescription": "foobar",
"links": {
"website": "https://foo.bar",
"github": "https://foo.bar"
},
"image": "../images/test.jpg",
"featured": 0
}
{
"urlname": "foobar",
"lang": "ignoreme",
"name": "foobar",
"shortDescription": "foobar",
"links": {
"website": "https://foo.bar",
"github": "https://foo.bar"
},
"image": "../images/test.jpg",
"featured": 0
}

View file

@ -1,11 +1,11 @@
{
"urlname": "else",
"lang": "de",
"name": "Schülerzeitung \"ELSE\"",
"shortDescription": "Eine News-Seite für die Schülerzeitung meiner Schule.",
"links": {
"website": "https://schuelerzeitung-elsensee.de"
},
"image": "../images/ELSE.jpg",
"featured": 2
}
{
"urlname": "else",
"lang": "de",
"name": "Schülerzeitung \"ELSE\"",
"shortDescription": "Eine News-Seite für die Schülerzeitung meiner Schule.",
"links": {
"website": "https://schuelerzeitung-elsensee.de"
},
"image": "../images/ELSE.jpg",
"featured": 2
}

View file

@ -1,11 +1,11 @@
{
"urlname": "else",
"lang": "en",
"name": "Student Newspaper \"ELSE\"",
"shortDescription": "A news-site for the my schools school paper.",
"links": {
"website": "https://schuelerzeitung-elsensee.de"
},
"image": "../images/ELSE.jpg",
"featured": 2
}
{
"urlname": "else",
"lang": "en",
"name": "Student Newspaper \"ELSE\"",
"shortDescription": "A news-site for the my schools school paper.",
"links": {
"website": "https://schuelerzeitung-elsensee.de"
},
"image": "../images/ELSE.jpg",
"featured": 2
}

View file

@ -1,13 +1,13 @@
{
"urlname": "kevink-dev",
"lang": "de",
"name": "KevinK.dev",
"shortDescription": "Diese Seite und der Code dahinter.",
"longDescription": "Schon so lange ich im Internet unterwegs bin war ich fasziniert von der Idee eine eigene Website zu haben. Deshalb habe ich mich an diese Seite gesetzt um mich selbst und meine Projekte zu repräsentieren. Wenn du interessiert an dem Code hinter der Seite bist, schau doch gerne auf GitHub vorbei!",
"links": {
"website": "https://kevink.dev",
"github": "https://github.com/Unkn0wnCat/KevinK.dev.js"
},
"image": "../images/KevinK.dev.jpg",
"featured": 0
}
{
"urlname": "kevink-dev",
"lang": "de",
"name": "KevinK.dev",
"shortDescription": "Diese Seite und der Code dahinter.",
"longDescription": "Schon so lange ich im Internet unterwegs bin war ich fasziniert von der Idee eine eigene Website zu haben. Deshalb habe ich mich an diese Seite gesetzt um mich selbst und meine Projekte zu repräsentieren. Wenn du interessiert an dem Code hinter der Seite bist, schau doch gerne auf GitHub vorbei!",
"links": {
"website": "https://kevink.dev",
"github": "https://github.com/Unkn0wnCat/KevinK.dev.js"
},
"image": "../images/KevinK.dev.jpg",
"featured": 0
}

View file

@ -1,13 +1,13 @@
{
"urlname": "kevink-dev",
"lang": "en",
"name": "KevinK.dev",
"shortDescription": "This site and the code behind the scenes.",
"longDescription": "For as long as I've been poking around the internet I've always been facinated by the idea to have my own website. This is why I've created this site to showcase myself and my projects. If you are interested in the code behind the scenes feel free to look at it on GitHub!",
"links": {
"website": "https://kevink.dev",
"github": "https://github.com/Unkn0wnCat/KevinK.dev.js"
},
"image": "../images/KevinK.dev.jpg",
"featured": 0
}
{
"urlname": "kevink-dev",
"lang": "en",
"name": "KevinK.dev",
"shortDescription": "This site and the code behind the scenes.",
"longDescription": "For as long as I've been poking around the internet I've always been facinated by the idea to have my own website. This is why I've created this site to showcase myself and my projects. If you are interested in the code behind the scenes feel free to look at it on GitHub!",
"links": {
"website": "https://kevink.dev",
"github": "https://github.com/Unkn0wnCat/KevinK.dev.js"
},
"image": "../images/KevinK.dev.jpg",
"featured": 0
}

View file

@ -1,12 +1,12 @@
{
"urlname": "kreig",
"lang": "de",
"name": "KREIG.de",
"shortDescription": " Eine einfache aber schöne Gaming-Seite. ",
"longDescription": "Videospiele sind ein wesentlicher Teil unserer heutigen Gesellschaft. Ob Kompetitiv oder einfach nur zum Spaß: Fast jeder hat irgendeine Erfahrnug mit Videospielen. Ich bin da keine Ausnahme und für meine Gaming-Gruppe habe ich diese Seite erstellt, bei der ich modernes Design mit dem Gefühl von klassischen Gaming-Websites vereint habe.",
"links": {
"website": "https://kreig.de"
},
"image": "../images/KREIG.de.jpg",
"featured": 1
}
{
"urlname": "kreig",
"lang": "de",
"name": "KREIG.de",
"shortDescription": " Eine einfache aber schöne Gaming-Seite. ",
"longDescription": "Videospiele sind ein wesentlicher Teil unserer heutigen Gesellschaft. Ob Kompetitiv oder einfach nur zum Spaß: Fast jeder hat irgendeine Erfahrnug mit Videospielen. Ich bin da keine Ausnahme und für meine Gaming-Gruppe habe ich diese Seite erstellt, bei der ich modernes Design mit dem Gefühl von klassischen Gaming-Websites vereint habe.",
"links": {
"website": "https://kreig.de"
},
"image": "../images/KREIG.de.jpg",
"featured": 1
}

View file

@ -1,12 +1,12 @@
{
"urlname": "kreig",
"lang": "en",
"name": "KREIG.de",
"shortDescription": " A simple but nice gaming website. ",
"longDescription": "Video games are a big part of today's society. Competitive or just for fun: Almost everyone has some contact with video games. I am no different to that and for my gaming clan I've created this site, which combines a modern design with the feeling of classical gaming sites on the early web.",
"links": {
"website": "https://kreig.de"
},
"image": "../images/KREIG.de.jpg",
"featured": 1
}
{
"urlname": "kreig",
"lang": "en",
"name": "KREIG.de",
"shortDescription": " A simple but nice gaming website. ",
"longDescription": "Video games are a big part of today's society. Competitive or just for fun: Almost everyone has some contact with video games. I am no different to that and for my gaming clan I've created this site, which combines a modern design with the feeling of classical gaming sites on the early web.",
"links": {
"website": "https://kreig.de"
},
"image": "../images/KREIG.de.jpg",
"featured": 1
}

View file

@ -1,6 +1,6 @@
{
"platformName": "Blog",
"platformHandle": "@kevin@blog.1in9.net",
"url": "https://blog.1in9.net/~/Kevin",
"image": "https://source.unsplash.com/xG8IQMqMITM/300x300"
}
{
"platformName": "Blog",
"platformHandle": "@kevin@blog.1in9.net",
"url": "https://blog.1in9.net/~/Kevin",
"image": "https://source.unsplash.com/xG8IQMqMITM/300x300"
}

View file

@ -1,6 +1,6 @@
{
"platformName": "GitHub",
"platformHandle": "@Unkn0wnCat",
"url": "https://github.com/Unkn0wnCat",
"image": "https://source.unsplash.com/842ofHC6MaI/300x300"
}
{
"platformName": "GitHub",
"platformHandle": "@Unkn0wnCat",
"url": "https://github.com/Unkn0wnCat",
"image": "https://source.unsplash.com/842ofHC6MaI/300x300"
}

View file

@ -1,6 +1,6 @@
{
"platformName": "Mastodon",
"platformHandle": "@kevin@1in1.net",
"url": "https://mastodon.1in1.net/@kevin",
"image": "https://source.unsplash.com/8bghKxNU1j0/300x300"
}
{
"platformName": "Mastodon",
"platformHandle": "@kevin@1in1.net",
"url": "https://mastodon.1in1.net/@kevin",
"image": "https://source.unsplash.com/8bghKxNU1j0/300x300"
}

View file

@ -1,6 +1,6 @@
{
"platformName": "Matrix",
"platformHandle": "@kevin:1in1.net",
"url": "https://matrix.to/#/@kevin:1in1.net",
"image": "https://source.unsplash.com/Zq6HerrBPEs/300x300"
}
{
"platformName": "Matrix",
"platformHandle": "@kevin:1in1.net",
"url": "https://matrix.to/#/@kevin:1in1.net",
"image": "https://source.unsplash.com/Zq6HerrBPEs/300x300"
}

View file

@ -1,6 +1,6 @@
{
"platformName": "Unkn0wnCat.net",
"platformHandle": "Gaming",
"url": "https://unkn0wncat.net",
"image": "https://source.unsplash.com/nCU4yq5xDEQ/300x300"
}
{
"platformName": "Unkn0wnCat.net",
"platformHandle": "Gaming",
"url": "https://unkn0wncat.net",
"image": "https://source.unsplash.com/nCU4yq5xDEQ/300x300"
}

View file

@ -1,6 +1,6 @@
{
"platformName": "Twitter",
"platformHandle": "@Unkn0wnKevin",
"url": "https://twitter.com/@Unkn0wnKevin",
"image": "https://source.unsplash.com/RnW1taVZqm8/300x300"
}
{
"platformName": "Twitter",
"platformHandle": "@Unkn0wnKevin",
"url": "https://twitter.com/@Unkn0wnKevin",
"image": "https://source.unsplash.com/RnW1taVZqm8/300x300"
}

View file

@ -1,6 +1,6 @@
{
"platformName": "Unsplash",
"platformHandle": "@Unkn0wnCat",
"url": "https://unsplash.com/@unkn0wncat",
"image": "https://source.unsplash.com/user/unkn0wncat/300x300"
}
{
"platformName": "Unsplash",
"platformHandle": "@Unkn0wnCat",
"url": "https://unsplash.com/@unkn0wncat",
"image": "https://source.unsplash.com/user/unkn0wncat/300x300"
}

View file

@ -1,92 +1,92 @@
/* eslint-disable no-undef */
const extConfig = require("./config")
module.exports = {
siteMetadata: {
title: extConfig.siteName,
author: extConfig.siteAuthor,
siteUrl: extConfig.siteURL,
keywords: extConfig.siteKeywords,
payPalMail: extConfig.payPalMail,
contactEmail: extConfig.contactEmail,
contactPhone: extConfig.contactPhone,
mapsLink: extConfig.mapsLink,
contactTwitter: extConfig.contactTwitter,
contactGitHub: extConfig.contactGitHub,
contactMastodon: extConfig.contactMastodon,
contactMastodonHref: extConfig.contactMastodonHref
},
assetPrefix: "/assets",
plugins: [
`gatsby-plugin-eslint`,
{
resolve: "gatsby-plugin-asset-path"
},
`gatsby-plugin-sharp`,
`gatsby-transformer-sharp`,
`gatsby-transformer-json`,
{
resolve: `gatsby-source-filesystem`,
options: {
path: `./content/`,
},
},
{
resolve: `gatsby-source-filesystem`,
options: {
path: `${__dirname}/locales`,
name: `locale`
},
},
`gatsby-plugin-sass`,
{
resolve: `gatsby-plugin-manifest`,
options: {
name: extConfig.siteName,
short_name: extConfig.siteName,
start_url: `/`,
background_color: `#000710`,
theme_color: `#000710`,
display: `minimal-ui`,
icon: extConfig.iconPath, // This path is relative to the root of the site.
cache_busting_mode: 'none',
},
},
`gatsby-plugin-robots-txt`,
{
resolve: `gatsby-plugin-offline`,
options: {
precachePages: ["/", "/en", "/en/projects", "/de", "/de/projects"],
workboxConfig: {
globPatterns: ['**/*']
}
},
},
`gatsby-plugin-sitemap`,
`gatsby-plugin-react-helmet`,
{
resolve: `gatsby-plugin-react-i18next`,
options: {
localeJsonSourceName: `locale`,
languages: extConfig.languages,
defaultLanguage: `en`,
generateDefaultLanguagePage: true,
siteUrl: extConfig.siteURL,
i18nextOptions: {
interpolation: {
escapeValue: false // not needed for react as it escapes by default
},
keySeparator: false,
nsSeparator: false
},
pages: [
{
matchPath: '/:lang/projects/:urlname',
getLanguageFromPath: true,
excludeLanguages: extConfig.languages
}
]
}
}
]
}
/* eslint-disable no-undef */
const extConfig = require("./config");
module.exports = {
siteMetadata: {
title: extConfig.siteName,
author: extConfig.siteAuthor,
siteUrl: extConfig.siteURL,
keywords: extConfig.siteKeywords,
payPalMail: extConfig.payPalMail,
contactEmail: extConfig.contactEmail,
contactPhone: extConfig.contactPhone,
mapsLink: extConfig.mapsLink,
contactTwitter: extConfig.contactTwitter,
contactGitHub: extConfig.contactGitHub,
contactMastodon: extConfig.contactMastodon,
contactMastodonHref: extConfig.contactMastodonHref,
},
assetPrefix: "/assets",
plugins: [
`gatsby-plugin-eslint`,
{
resolve: "gatsby-plugin-asset-path",
},
`gatsby-plugin-sharp`,
`gatsby-transformer-sharp`,
`gatsby-transformer-json`,
{
resolve: `gatsby-source-filesystem`,
options: {
path: `./content/`,
},
},
{
resolve: `gatsby-source-filesystem`,
options: {
path: `${__dirname}/locales`,
name: `locale`,
},
},
`gatsby-plugin-sass`,
{
resolve: `gatsby-plugin-manifest`,
options: {
name: extConfig.siteName,
short_name: extConfig.siteName,
start_url: `/`,
background_color: `#000710`,
theme_color: `#000710`,
display: `minimal-ui`,
icon: extConfig.iconPath, // This path is relative to the root of the site.
cache_busting_mode: "none",
},
},
`gatsby-plugin-robots-txt`,
{
resolve: `gatsby-plugin-offline`,
options: {
precachePages: ["/", "/en", "/en/projects", "/de", "/de/projects"],
workboxConfig: {
globPatterns: ["**/*"],
},
},
},
`gatsby-plugin-sitemap`,
`gatsby-plugin-react-helmet`,
{
resolve: `gatsby-plugin-react-i18next`,
options: {
localeJsonSourceName: `locale`,
languages: extConfig.languages,
defaultLanguage: `en`,
generateDefaultLanguagePage: true,
siteUrl: extConfig.siteURL,
i18nextOptions: {
interpolation: {
escapeValue: false, // not needed for react as it escapes by default
},
keySeparator: false,
nsSeparator: false,
},
pages: [
{
matchPath: "/:lang/projects/:urlname",
getLanguageFromPath: true,
excludeLanguages: extConfig.languages,
},
],
},
},
],
};

View file

@ -1,141 +1,175 @@
/* eslint-disable no-undef */
const path = require(`path`);
const fs = require("fs")
exports.createPages = async ({ actions, graphql, reporter }) => {
const { createPage } = actions
const projectTemplate = path.resolve(`src/templates/project.js`)
const result = await graphql(`
query AllPagesQuery {
allProjectsJson {
nodes {
lang
urlname
}
}
}
`)
if (result.errors) {
reporter.panicOnBuild(`Error while running GraphQL query.`)
return
}
result.data.allProjectsJson.nodes.forEach((node) => {
// eslint-disable-next-line no-undef
console.log("Creating Page: ", `/${node.lang}/projects/${node.urlname}`);
if (node.lang !== "ignoreme") createPage({
path: `/${node.lang}/projects/${node.urlname}`,
component: projectTemplate,
context: {
lang: node.lang,
urlname: node.urlname
}
})
});
}
const config = require("./config.js");
exports.onPostBuild = async ({graphql, reporter}) => {
console.log("Building static api...");
const apiPrefix = "./public/api";
if (!fs.existsSync(apiPrefix)) fs.mkdirSync(apiPrefix)
fs.writeFileSync(`${apiPrefix}.json`, JSON.stringify({
success: true,
endpoints: {
projects: [
{
name: "Projects Overview",
description: "Returns overview of all available projects",
path: "/api/projects.json"
},
{
name: "Projects Overview for Language",
description: "Returns overview of all available projects in a specified language",
path: "/api/projects/:lang.json"
},
{
name: "Get specific Project",
description: "Returns specific project in specified language",
path: "/api/projects/:lang/:slug.json"
}
]
}
}));
const projectsPrefix = apiPrefix+"/projects";
if (!fs.existsSync(projectsPrefix)) fs.mkdirSync(projectsPrefix)
await graphql(`
query {
allProjectsJson {
nodes {
longDescription
urlname
shortDescription
name
links {
github
website
}
lang
image {
publicURL
}
featured
}
}
}
`).then(res => {
if (res.errors) {
reporter.panicOnBuild(`Error while running GraphQL query.`)
return
}
let projects = res.data.allProjectsJson.nodes.filter((project => { return project.lang !== "ignoreme" }));
fs.writeFileSync(`${projectsPrefix}.json`, JSON.stringify({
success: true,
projects: projects.map((project) => {return {slug: project.urlname, lang: project.lang, api: `/api/projects/${project.lang}/${project.urlname}.json`};})
}));
config.languages.forEach((lang) => {
if (!fs.existsSync(`${projectsPrefix}/${lang}`)) fs.mkdirSync(`${projectsPrefix}/${lang}`)
fs.writeFileSync(`${projectsPrefix}/${lang}.json`, JSON.stringify({
success: true,
projects: projects.filter((project) => {return project.lang == lang;}).map((project) => {return {slug: project.urlname, lang: project.lang, api: `/api/projects/${project.lang}/${project.urlname}.json`};})
}));
});
projects.forEach((project) => {
fs.writeFileSync(`${projectsPrefix}/${project.lang}/${project.urlname}.json`, JSON.stringify({
success: true,
project: {
slug: project.urlname,
lang: project.lang,
name: project.name,
shortDescription: project.shortDescription,
longDescription: project.longDescription,
links: project.links !== null ? {
github: project.links.github,
website: project.links.website
} : null,
image: project.image.publicURL,
featured: project.featured,
frontend: `/${project.lang}/projects/${project.urlname}`
}
}));
});
})
}
/* eslint-disable no-undef */
const path = require(`path`);
const fs = require("fs");
exports.createPages = async ({ actions, graphql, reporter }) => {
const { createPage } = actions;
const projectTemplate = path.resolve(`src/templates/project.js`);
const result = await graphql(`
query AllPagesQuery {
allProjectsJson {
nodes {
lang
urlname
}
}
}
`);
if (result.errors) {
reporter.panicOnBuild(`Error while running GraphQL query.`);
return;
}
result.data.allProjectsJson.nodes.forEach((node) => {
// eslint-disable-next-line no-undef
console.log("Creating Page: ", `/${node.lang}/projects/${node.urlname}`);
if (node.lang !== "ignoreme")
createPage({
path: `/${node.lang}/projects/${node.urlname}`,
component: projectTemplate,
context: {
lang: node.lang,
urlname: node.urlname,
},
});
});
};
const config = require("./config.js");
exports.onPostBuild = async ({ graphql, reporter }) => {
console.log("Building static api...");
const apiPrefix = "./public/api";
if (!fs.existsSync(apiPrefix)) fs.mkdirSync(apiPrefix);
fs.writeFileSync(
`${apiPrefix}.json`,
JSON.stringify({
success: true,
endpoints: {
projects: [
{
name: "Projects Overview",
description: "Returns overview of all available projects",
path: "/api/projects.json",
},
{
name: "Projects Overview for Language",
description:
"Returns overview of all available projects in a specified language",
path: "/api/projects/:lang.json",
},
{
name: "Get specific Project",
description: "Returns specific project in specified language",
path: "/api/projects/:lang/:slug.json",
},
],
},
})
);
const projectsPrefix = apiPrefix + "/projects";
if (!fs.existsSync(projectsPrefix)) fs.mkdirSync(projectsPrefix);
await graphql(`
query {
allProjectsJson {
nodes {
longDescription
urlname
shortDescription
name
links {
github
website
}
lang
image {
publicURL
}
featured
}
}
}
`).then((res) => {
if (res.errors) {
reporter.panicOnBuild(`Error while running GraphQL query.`);
return;
}
let projects = res.data.allProjectsJson.nodes.filter((project) => {
return project.lang !== "ignoreme";
});
fs.writeFileSync(
`${projectsPrefix}.json`,
JSON.stringify({
success: true,
projects: projects.map((project) => {
return {
slug: project.urlname,
lang: project.lang,
api: `/api/projects/${project.lang}/${project.urlname}.json`,
};
}),
})
);
config.languages.forEach((lang) => {
if (!fs.existsSync(`${projectsPrefix}/${lang}`))
fs.mkdirSync(`${projectsPrefix}/${lang}`);
fs.writeFileSync(
`${projectsPrefix}/${lang}.json`,
JSON.stringify({
success: true,
projects: projects
.filter((project) => {
return project.lang == lang;
})
.map((project) => {
return {
slug: project.urlname,
lang: project.lang,
api: `/api/projects/${project.lang}/${project.urlname}.json`,
};
}),
})
);
});
projects.forEach((project) => {
fs.writeFileSync(
`${projectsPrefix}/${project.lang}/${project.urlname}.json`,
JSON.stringify({
success: true,
project: {
slug: project.urlname,
lang: project.lang,
name: project.name,
shortDescription: project.shortDescription,
longDescription: project.longDescription,
links:
project.links !== null
? {
github: project.links.github,
website: project.links.website,
}
: null,
image: project.image.publicURL,
featured: project.featured,
frontend: `/${project.lang}/projects/${project.urlname}`,
},
})
);
});
});
};

View file

@ -35,4 +35,4 @@
"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"
}
}

View file

@ -1,38 +1,38 @@
{
"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",
"homeAboutMe": "About me",
"homeAboutMeHello": "Hello!",
"homeAboutMeText": "I am Kevin Kandlbinder, a developer and hobby photographer from northern germany. I've learned operating computers very early in my life with my father giving me his old Windows 2000 tower. Some years later I've had my first contact with web development a few years later when I bought a book about HTML, PHP, JavaScript and CSS from a sale at my local library. From this point onwards web development has been a job and a hobby equally.",
"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</1>!",
"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}}</1> if you have anything you want to talk about!",
"featuredProjects": "Featured Projects",
"seeMore": "See more",
"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"
}
"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",
"homeAboutMe": "About me",
"homeAboutMeHello": "Hello!",
"homeAboutMeText": "I am Kevin Kandlbinder, a developer and hobby photographer from northern germany. I've learned operating computers very early in my life with my father giving me his old Windows 2000 tower. Some years later I've had my first contact with web development a few years later when I bought a book about HTML, PHP, JavaScript and CSS from a sale at my local library. From this point onwards web development has been a job and a hobby equally.",
"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</1>!",
"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}}</1> if you have anything you want to talk about!",
"featuredProjects": "Featured Projects",
"seeMore": "See more",
"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"
}

49838
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,64 +1,64 @@
{
"name": "kevink.dev",
"version": "1.1.0",
"private": true,
"description": "KevinK.dev",
"author": "Kevin Kandlbinder",
"keywords": [
"gatsby"
],
"scripts": {
"develop": "gatsby develop",
"start": "gatsby develop",
"build": "gatsby build --prefix-paths",
"build:fab": "npm run build && npm run fab:build",
"fab:build": "fab build",
"fab:serve": "fab serve fab.zip",
"serve": "gatsby serve",
"clean": "gatsby clean"
},
"license": "Apache-2.0",
"dependencies": {
"@babel/cli": "7.13.14",
"@babel/plugin-transform-typescript": "7.13.0",
"animejs": "3.2.1",
"babel-plugin-i18next-extract": "0.8.3",
"gatsby": "3.2.1",
"gatsby-cli": "3.2.0",
"gatsby-plugin-asset-path": "3.0.3",
"gatsby-plugin-manifest": "3.2.0",
"gatsby-plugin-offline": "4.2.0",
"gatsby-plugin-react-helmet": "4.2.0",
"gatsby-plugin-react-i18next": "1.1.1",
"gatsby-plugin-robots-txt": "1.5.5",
"gatsby-plugin-sass": "4.2.0",
"gatsby-plugin-sharp": "3.2.1",
"gatsby-plugin-sitemap": "3.2.0",
"gatsby-source-filesystem": "3.2.0",
"gatsby-transformer-json": "3.2.0",
"gatsby-transformer-sharp": "3.2.0",
"i18next": "20.2.1",
"locale": "0.1.0",
"node-sass": "4.14.1",
"prop-types": "15.7.2",
"react": "17.0.2",
"react-dom": "17.0.2",
"react-github-btn": "1.2.0",
"react-helmet": "6.1.0",
"react-i18next": "11.8.12"
},
"devDependencies": {
"@fab/actions": "1.0.0-rc.3-beta.1",
"@fab/cli": "1.0.0-rc.3-beta.1",
"@fab/input-static": "1.0.0-rc.3-beta.1",
"@fab/plugin-render-html": "1.0.0-rc.3-beta.1",
"@fab/plugin-rewire-assets": "1.0.0-rc.3-beta.1",
"@fab/server": "1.0.0-rc.3-beta.1",
"babel-eslint": "10.1.0",
"eslint": "7.24.0",
"eslint-loader": "4.0.2",
"eslint-plugin-import": "2.22.1",
"eslint-plugin-react": "7.23.2",
"gatsby-plugin-eslint": "2.0.8"
}
"name": "kevink.dev",
"version": "1.1.0",
"private": true,
"description": "KevinK.dev",
"author": "Kevin Kandlbinder",
"keywords": [
"gatsby"
],
"scripts": {
"develop": "gatsby develop",
"start": "gatsby develop",
"build": "gatsby build --prefix-paths",
"build:fab": "npm run build && npm run fab:build",
"fab:build": "fab build",
"fab:serve": "fab serve fab.zip",
"serve": "gatsby serve",
"clean": "gatsby clean"
},
"license": "Apache-2.0",
"dependencies": {
"@babel/cli": "7.13.14",
"@babel/plugin-transform-typescript": "7.13.0",
"animejs": "3.2.1",
"babel-plugin-i18next-extract": "0.8.3",
"gatsby": "3.2.1",
"gatsby-cli": "3.2.0",
"gatsby-plugin-asset-path": "3.0.3",
"gatsby-plugin-manifest": "3.2.0",
"gatsby-plugin-offline": "4.2.0",
"gatsby-plugin-react-helmet": "4.2.0",
"gatsby-plugin-react-i18next": "1.1.1",
"gatsby-plugin-robots-txt": "1.5.5",
"gatsby-plugin-sass": "4.2.0",
"gatsby-plugin-sharp": "3.2.1",
"gatsby-plugin-sitemap": "3.2.0",
"gatsby-source-filesystem": "3.2.0",
"gatsby-transformer-json": "3.2.0",
"gatsby-transformer-sharp": "3.2.0",
"i18next": "20.2.1",
"locale": "0.1.0",
"node-sass": "4.14.1",
"prop-types": "15.7.2",
"react": "17.0.2",
"react-dom": "17.0.2",
"react-github-btn": "1.2.0",
"react-helmet": "6.1.0",
"react-i18next": "11.8.12"
},
"devDependencies": {
"@fab/actions": "1.0.0-rc.3-beta.1",
"@fab/cli": "1.0.0-rc.3-beta.1",
"@fab/input-static": "1.0.0-rc.3-beta.1",
"@fab/plugin-render-html": "1.0.0-rc.3-beta.1",
"@fab/plugin-rewire-assets": "1.0.0-rc.3-beta.1",
"@fab/server": "1.0.0-rc.3-beta.1",
"babel-eslint": "10.1.0",
"eslint": "7.24.0",
"eslint-loader": "4.0.2",
"eslint-plugin-import": "2.22.1",
"eslint-plugin-react": "7.23.2",
"gatsby-plugin-eslint": "2.0.8"
}
}

View file

@ -1,12 +1,6 @@
{
"extends": [
"config:base"
],
"assignees": [
"Unkn0wnCat"
],
"automerge": true,
"baseBranches": [
"main"
]
}
{
"extends": ["config:base"],
"assignees": ["Unkn0wnCat"],
"automerge": true,
"baseBranches": ["main"]
}

View file

@ -1,81 +1,80 @@
@import "./variables";
@mixin flexList {
display: flex;
flex-wrap: wrap;
justify-content: center;
}
@mixin cardGeneric {
border-radius: 5px;
overflow: hidden;
box-shadow: -1px 11px 33px -10px rgba(127, 127, 127, 0.3);
transition: transform .25s, box-shadow .25s;
color: $textColor;
text-decoration: none;
margin: 20px;
background: $background;
&:hover,
&:active,
&:focus {
transform: scale(1.05);
box-shadow: -1px 11px 33px -10px rgba(127, 127, 127, 0.2), -1px 11px 33px -10px rgba($accentColor, .75);
}
}
@mixin buttonBasic {
display: block;
padding: 10px;
text-align: center;
background: $accentColor;
color: white;
text-decoration: none;
box-shadow: 0 0 33px -10px rgba($accentColor, .5);
transition: box-shadow .25s;
&:hover,
&:active,
&:hover {
box-shadow: 0 0 33px -10px rgba($accentColor, .9);
}
}
@mixin button {
@include buttonBasic;
border-radius: 5px;
}
@mixin homeBanner {
background: lighten($background, 1);
cursor: pointer;
display: block;
text-decoration: none;
color: inherit;
img {
height: 50px;
}
>div {
display: flex;
height: 100%;
padding: 20px !important;
line-height: 50px;
font-size: 1.7em;
color: white;
>span {
margin-left: auto;
margin-right: auto;
}
>i {
display: inline-flex;
flex-direction: column;
justify-content: center;
}
}
}
@import "./variables";
@mixin flexList {
display: flex;
flex-wrap: wrap;
justify-content: center;
}
@mixin cardGeneric {
border-radius: 5px;
overflow: hidden;
box-shadow: -1px 11px 33px -10px rgba(127, 127, 127, 0.3);
transition: transform 0.25s, box-shadow 0.25s;
color: $textColor;
text-decoration: none;
margin: 20px;
background: $background;
&:hover,
&:active,
&:focus {
transform: scale(1.05);
box-shadow: -1px 11px 33px -10px rgba(127, 127, 127, 0.2),
-1px 11px 33px -10px rgba($accentColor, 0.75);
}
}
@mixin buttonBasic {
display: block;
padding: 10px;
text-align: center;
background: $accentColor;
color: white;
text-decoration: none;
box-shadow: 0 0 33px -10px rgba($accentColor, 0.5);
transition: box-shadow 0.25s;
&:hover,
&:active,
&:hover {
box-shadow: 0 0 33px -10px rgba($accentColor, 0.9);
}
}
@mixin button {
@include buttonBasic;
border-radius: 5px;
}
@mixin homeBanner {
background: lighten($background, 1);
cursor: pointer;
display: block;
text-decoration: none;
color: inherit;
img {
height: 50px;
}
> div {
display: flex;
height: 100%;
padding: 20px !important;
line-height: 50px;
font-size: 1.7em;
color: white;
> span {
margin-left: auto;
margin-right: auto;
}
> i {
display: inline-flex;
flex-direction: column;
justify-content: center;
}
}
}

View file

@ -1,8 +1,7 @@
$layoutWidth: 1200px;
$accentColor: #e5502b;
$background: #070707;
$textColor: white;
$layoutPadding: 20px;
$mainFont: 'Anonymous Pro',
monospace;
$layoutWidth: 1200px;
$accentColor: #e5502b;
$background: #070707;
$textColor: white;
$layoutPadding: 20px;
$mainFont: "Anonymous Pro", monospace;

View file

@ -1,25 +1,31 @@
import React from "react"
import { Link, Trans, useI18next } from 'gatsby-plugin-react-i18next';
import React from "react";
import { Link, Trans, useI18next } from "gatsby-plugin-react-i18next";
import * as styles from "./languageSwitcher.module.scss";
export default function LanguageSwitcher() {
const { languages, originalPath } = useI18next();
const { languages, originalPath } = useI18next();
return (
<div className={styles.languageModal} id="languageChooser">
<div className={styles.languageModalInner}>
<h2>Languages (<a href="#top" className={styles.modalCloseLink}>&times;</a>)</h2>
<ul>
{languages.map((lng) => (
<li key={lng}>
<Link to={originalPath} language={lng}>
<Trans>{lng}</Trans>
</Link>
</li>
))}
</ul>
</div>
</div>
);
}
return (
<div className={styles.languageModal} id="languageChooser">
<div className={styles.languageModalInner}>
<h2>
Languages (
<a href="#top" className={styles.modalCloseLink}>
&times;
</a>
)
</h2>
<ul>
{languages.map((lng) => (
<li key={lng}>
<Link to={originalPath} language={lng}>
<Trans>{lng}</Trans>
</Link>
</li>
))}
</ul>
</div>
</div>
);
}

View file

@ -7,11 +7,11 @@
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, .7);
background: rgba(0, 0, 0, 0.7);
z-index: 1000;
opacity: 0;
pointer-events: none;
transition: opacity .25s;
transition: opacity 0.25s;
&:target {
opacity: 1;
@ -33,10 +33,9 @@
color: white;
text-decoration-style: dotted;
}
}
.modalCloseLink {
text-decoration: none;
}
}
}

View file

@ -1,26 +1,26 @@
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 React, { useEffect, useState } from "react";
import PropTypes from "prop-types";
import { Trans, Link } from "gatsby-plugin-react-i18next";
import { graphql, StaticQuery } from "gatsby";
import * as styles from './navigation.module.scss'
import * as styles from "./navigation.module.scss";
const Navigation = ({ isHome }) => {
let [atTop, setAtTop] = useState(false);
const updateTransparency = () => {
if(typeof window === "undefined") return;
if (typeof window === "undefined") return;
// eslint-disable-next-line no-undef
if (window.scrollY < 15) {
if(!atTop) setAtTop(true);
if (!atTop) setAtTop(true);
} else {
if(atTop) setAtTop(false);
if (atTop) setAtTop(false);
}
}
};
useEffect(() => {
if(typeof window === "undefined") return;
if (typeof window === "undefined") return;
// eslint-disable-next-line no-undef
window.addEventListener("scroll", updateTransparency);
@ -30,7 +30,7 @@ const Navigation = ({ isHome }) => {
updateTransparency();
// eslint-disable-next-line no-undef
let int = window.setInterval(updateTransparency, 10000)
let int = window.setInterval(updateTransparency, 10000);
return () => {
// eslint-disable-next-line no-undef
@ -40,33 +40,52 @@ const Navigation = ({ isHome }) => {
// eslint-disable-next-line no-undef
window.clearInterval(int);
}
};
});
return (
<div className={styles.topBar + (isHome ? " "+styles.homeBar : "") + (atTop ? " "+styles.homeBarTransparent : "")}>
<nav className={styles.topBarInner}>
<StaticQuery query={graphql`
query {
site {
siteMetadata {
title
}
}
}
`} render={data => (
<Link to="/" activeClassName={styles.active}>{data.site.siteMetadata.title}</Link>
)} />
<div className="flexSpacer"></div>
<Link id="navBtnProjects" to="/projects" activeClassName={styles.active}><Trans>projects</Trans></Link>
<Link id="navBtnSocial" to="/social" activeClassName={styles.active}><Trans>social</Trans></Link>
</nav>
</div>
<div
className={
styles.topBar +
(isHome ? " " + styles.homeBar : "") +
(atTop ? " " + styles.homeBarTransparent : "")
}
>
<nav className={styles.topBarInner}>
<StaticQuery
query={graphql`
query {
site {
siteMetadata {
title
}
}
}
`}
render={(data) => (
<Link to="/" activeClassName={styles.active}>
{data.site.siteMetadata.title}
</Link>
)}
/>
<div className="flexSpacer"></div>
<Link
id="navBtnProjects"
to="/projects"
activeClassName={styles.active}
>
<Trans>projects</Trans>
</Link>
<Link id="navBtnSocial" to="/social" activeClassName={styles.active}>
<Trans>social</Trans>
</Link>
</nav>
</div>
);
}
};
Navigation.propTypes = {
isHome: PropTypes.bool.isRequired
}
isHome: PropTypes.bool.isRequired,
};
export default Navigation;
export default Navigation;

View file

@ -7,13 +7,13 @@
left: 0;
display: flex;
width: 100%;
background: rgba($background, .95);
background: rgba($background, 0.95);
backdrop-filter: blur(5px);
z-index: 999;
transition: background .25s;
transition: background 0.25s;
@supports(backdrop-filter: blur(5px)) {
background: rgba($background, .9);
@supports (backdrop-filter: blur(5px)) {
background: rgba($background, 0.9);
}
.topBarInner {
@ -38,7 +38,7 @@
border-top: 2px solid transparent;
&:hover {
border-color: rgba(255, 255, 255, .25);
border-color: rgba(255, 255, 255, 0.25);
}
&.active {
@ -53,9 +53,7 @@
backdrop-filter: blur(0);
}
.flexSpacer {
flex-grow: 1;
text-align: center;
}
}

View file

@ -1,86 +1,92 @@
import React from "react"
import PropTypes from "prop-types"
import { Helmet } from "gatsby-plugin-react-i18next"
import { useStaticQuery, graphql } from "gatsby"
import { useTranslation } from 'gatsby-plugin-react-i18next';
function SEO({ description, meta, title }) {
const { t } = useTranslation();
const { site } = useStaticQuery(
graphql`
query {
site {
siteMetadata {
title
author
keywords
}
}
}
`
)
const metaDescription = description || t("siteDescription");
return (
<Helmet
title={title}
titleTemplate={`%s | ${site.siteMetadata.title}`}
meta={[
{
name: `description`,
content: metaDescription,
},
{
property: `og:title`,
content: title,
},
{
property: `og:description`,
content: metaDescription,
},
{
property: `og:type`,
content: `website`,
},
{
name: `twitter:card`,
content: `summary`,
},
{
name: `twitter:creator`,
content: site.siteMetadata.author,
},
{
name: `twitter:title`,
content: title,
},
{
name: `twitter:description`,
content: metaDescription,
},
{
name: "keywords",
content: site.siteMetadata.keywords
}
].concat(meta)}
>
<script src="https://kit.fontawesome.com/1377f925e0.js" crossOrigin="anonymous"></script>
<link rel="preconnect" href="https://fonts.gstatic.com" />
<link href="https://fonts.googleapis.com/css2?family=Anonymous+Pro:wght@400;700&family=Roboto&display=swap" rel="stylesheet" />
</Helmet>
)
}
SEO.defaultProps = {
meta: [],
description: ``,
}
SEO.propTypes = {
description: PropTypes.string,
meta: PropTypes.arrayOf(PropTypes.object),
title: PropTypes.string.isRequired,
}
export default SEO
import React from "react";
import PropTypes from "prop-types";
import { Helmet } from "gatsby-plugin-react-i18next";
import { useStaticQuery, graphql } from "gatsby";
import { useTranslation } from "gatsby-plugin-react-i18next";
function SEO({ description, meta, title }) {
const { t } = useTranslation();
const { site } = useStaticQuery(
graphql`
query {
site {
siteMetadata {
title
author
keywords
}
}
}
`
);
const metaDescription = description || t("siteDescription");
return (
<Helmet
title={title}
titleTemplate={`%s | ${site.siteMetadata.title}`}
meta={[
{
name: `description`,
content: metaDescription,
},
{
property: `og:title`,
content: title,
},
{
property: `og:description`,
content: metaDescription,
},
{
property: `og:type`,
content: `website`,
},
{
name: `twitter:card`,
content: `summary`,
},
{
name: `twitter:creator`,
content: site.siteMetadata.author,
},
{
name: `twitter:title`,
content: title,
},
{
name: `twitter:description`,
content: metaDescription,
},
{
name: "keywords",
content: site.siteMetadata.keywords,
},
].concat(meta)}
>
<script
src="https://kit.fontawesome.com/1377f925e0.js"
crossOrigin="anonymous"
></script>
<link rel="preconnect" href="https://fonts.gstatic.com" />
<link
href="https://fonts.googleapis.com/css2?family=Anonymous+Pro:wght@400;700&family=Roboto&display=swap"
rel="stylesheet"
/>
</Helmet>
);
}
SEO.defaultProps = {
meta: [],
description: ``,
};
SEO.propTypes = {
description: PropTypes.string,
meta: PropTypes.arrayOf(PropTypes.object),
title: PropTypes.string.isRequired,
};
export default SEO;

View file

@ -1,43 +1,62 @@
import React from "react"
import PropTypes from "prop-types"
import Navigation from "../components/navigation"
import React from "react";
import PropTypes from "prop-types";
import Navigation from "../components/navigation";
import SEO from "../components/seo";
import "./default.scss";
import { Link, Trans } from 'gatsby-plugin-react-i18next';
import { Link, Trans } from "gatsby-plugin-react-i18next";
import LanguageSwitcher from "../components/languageSwitcher";
class Layout extends React.Component {
render() {
return (
<>
<SEO description={this.props.description} lang={this.props.lang} meta={this.props.meta} title={this.props.title} />
<Navigation isHome={this.props.transparentTopbar} />
<div id="content" role="main">
{this.props.children}
</div>
<footer role="contentinfo">CC-BY 4.0 Kevin Kandlbinder, <Link to="/legal/about" className="spf-link"><Trans i18nKey="imprint">Imprint</Trans></Link> | <Link to="/legal/datasec" className="spf-link"><Trans i18nKey="datasec">Data Protection</Trans></Link> | <Link to="/legal/disclaimer" className="spf-link"><Trans i18nKey="disclaimer">Disclaimer</Trans></Link> | <a href="#languageChooser">Language</a></footer>
<LanguageSwitcher />
</>
);
}
render() {
return (
<>
<SEO
description={this.props.description}
lang={this.props.lang}
meta={this.props.meta}
title={this.props.title}
/>
<Navigation isHome={this.props.transparentTopbar} />
<div id="content" role="main">
{this.props.children}
</div>
<footer role="contentinfo">
CC-BY 4.0 Kevin Kandlbinder,{" "}
<Link to="/legal/about" className="spf-link">
<Trans i18nKey="imprint">Imprint</Trans>
</Link>{" "}
|{" "}
<Link to="/legal/datasec" className="spf-link">
<Trans i18nKey="datasec">Data Protection</Trans>
</Link>{" "}
|{" "}
<Link to="/legal/disclaimer" className="spf-link">
<Trans i18nKey="disclaimer">Disclaimer</Trans>
</Link>{" "}
| <a href="#languageChooser">Language</a>
</footer>
<LanguageSwitcher />
</>
);
}
}
Layout.defaultProps = {
module: `none`,
meta: [],
description: ``,
transparentTopbar: false
}
module: `none`,
meta: [],
description: ``,
transparentTopbar: false,
};
Layout.propTypes = {
description: PropTypes.string,
lang: PropTypes.string,
meta: PropTypes.arrayOf(PropTypes.object),
title: PropTypes.string.isRequired,
transparentTopbar: PropTypes.bool,
children: PropTypes.any.isRequired
}
description: PropTypes.string,
lang: PropTypes.string,
meta: PropTypes.arrayOf(PropTypes.object),
title: PropTypes.string.isRequired,
transparentTopbar: PropTypes.bool,
children: PropTypes.any.isRequired,
};
export default Layout;
export default Layout;

View file

@ -41,16 +41,15 @@ footer {
flex-direction: column;
}
.flexSpacer {
flex-grow: 1;
text-align: center;
}
section>div:not(.profile),
section>article,
.section>div:not(.profile),
.section>article {
section > div:not(.profile),
section > article,
.section > div:not(.profile),
.section > article {
max-width: $layoutWidth;
width: 100%;
padding: 39px 20px;
@ -72,4 +71,3 @@ article {
h1 {
font-size: 2em;
}

View file

@ -1,6 +1,6 @@
import * as React from "react"
import { Link } from "gatsby-plugin-react-i18next"
import Layout from "../layouts/default"
import * as React from "react";
import { Link } from "gatsby-plugin-react-i18next";
import Layout from "../layouts/default";
const NotFoundPage = () => {
return (
@ -9,12 +9,13 @@ const NotFoundPage = () => {
<article>
<h1>Page not found</h1>
<p>
Whoops... That page doesn&apos;t exist, so you may as well <Link to="/">go home</Link>.
Whoops... That page doesn&apos;t exist, so you may as well{" "}
<Link to="/">go home</Link>.
</p>
</article>
</section>
</Layout>
)
}
);
};
export default NotFoundPage
export default NotFoundPage;

View file

@ -1,39 +1,39 @@
import React, { useState } from "react"
import React, { useState } from "react";
import Layout from "../layouts/default";
import { graphql } from "gatsby";
import { Trans, useI18next, I18nextContext } from "gatsby-plugin-react-i18next"
import PropTypes from "prop-types"
import GitHubButton from 'react-github-btn'
import { Trans, useI18next, I18nextContext } from "gatsby-plugin-react-i18next";
import PropTypes from "prop-types";
import GitHubButton from "react-github-btn";
import * as styles from "./donate.module.scss";
export const query = graphql`
query ($language: String!) {
site {
siteMetadata {
title
siteUrl
payPalMail
contactGitHub
query($language: String!) {
site {
siteMetadata {
title
siteUrl
payPalMail
contactGitHub
}
}
}
file(relativePath: {eq: "images/pplogo.png"}) {
file(relativePath: { eq: "images/pplogo.png" }) {
childImageSharp {
resize(width: 240, height: 240, fit: CONTAIN) {
src
}
resize(width: 240, height: 240, fit: CONTAIN) {
src
}
}
}
locales: allLocale(filter: {language: {eq: $language}}) {
edges {
node {
ns
data
language
}
locales: allLocale(filter: { language: { eq: $language } }) {
edges {
node {
ns
data
language
}
}
}
}
}
`;
function DonatePage(props) {
@ -47,23 +47,81 @@ function DonatePage(props) {
<Layout title={t("donate")} description={t("donationCatchphrase")}>
<section>
<article>
<h1><Trans>donate</Trans></h1>
<h1>
<Trans>donate</Trans>
</h1>
<p><Trans>donateDescription</Trans></p>
<p>
<Trans>donateDescription</Trans>
</p>
<p><Trans>donateGitHub</Trans></p>
<p>
<Trans>donateGitHub</Trans>
</p>
<p style={{display: "block", textAlign: "center"}}><GitHubButton href={"https://github.com/sponsors/"+site.siteMetadata.contactGitHub} data-color-scheme="no-preference: light; light: dark; dark: dark;" data-icon="octicon-heart" data-size="large" aria-label="Sponsor @Unkn0wnCat on GitHub"><Trans>sponsorGitHub</Trans></GitHubButton></p>
<p style={{ display: "block", textAlign: "center" }}>
<GitHubButton
href={
"https://github.com/sponsors/" + site.siteMetadata.contactGitHub
}
data-color-scheme="no-preference: light; light: dark; dark: dark;"
data-icon="octicon-heart"
data-size="large"
aria-label="Sponsor @Unkn0wnCat on GitHub"
>
<Trans>sponsorGitHub</Trans>
</GitHubButton>
</p>
<p><Trans>donatePayPal</Trans></p>
<p>
<Trans>donatePayPal</Trans>
</p>
<div className={styles.priceAmount}>
<label htmlFor="priceInput" className={styles.sronly}>Amount</label>
<input type="number" min="1" placeholder="10.00" step="1" value={amount} onChange={(ev) => { setAmount(ev.target.value) }} name="priceInput" id="priceInput" />
<label htmlFor="priceInput" className={styles.sronly}>
Amount
</label>
<input
type="number"
min="1"
placeholder="10.00"
step="1"
value={amount}
onChange={(ev) => {
setAmount(ev.target.value);
}}
name="priceInput"
id="priceInput"
/>
<div></div>
</div>
<a className={styles.donateButton} rel="noopener" id="payPalBtn" href={"https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=" + encodeURIComponent(site.siteMetadata.payPalMail) + "&item_name=" + encodeURIComponent(site.siteMetadata.title) + "&currency_code=EUR&image_url=" + (encodeURIComponent(site.siteMetadata.siteUrl + file.childImageSharp.resize.src)) + "&return=" + (encodeURIComponent(site.siteMetadata.siteUrl + "/" + path + "thank-you/")) + "&rm=0&cancel_return=" + (encodeURIComponent(site.siteMetadata.siteUrl + "/" + path)) + "&amount=" + amount}><span>Donate using PayPal</span><i className="fas fa-fw fa-chevron-right" aria-hidden="true"></i></a>
<a
className={styles.donateButton}
rel="noopener"
id="payPalBtn"
href={
"https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=" +
encodeURIComponent(site.siteMetadata.payPalMail) +
"&item_name=" +
encodeURIComponent(site.siteMetadata.title) +
"&currency_code=EUR&image_url=" +
encodeURIComponent(
site.siteMetadata.siteUrl + file.childImageSharp.resize.src
) +
"&return=" +
encodeURIComponent(
site.siteMetadata.siteUrl + "/" + path + "thank-you/"
) +
"&rm=0&cancel_return=" +
encodeURIComponent(site.siteMetadata.siteUrl + "/" + path) +
"&amount=" +
amount
}
>
<span>Donate using PayPal</span>
<i className="fas fa-fw fa-chevron-right" aria-hidden="true"></i>
</a>
</article>
</section>
</Layout>
@ -71,7 +129,7 @@ function DonatePage(props) {
}
DonatePage.propTypes = {
data: PropTypes.object.isRequired
data: PropTypes.object.isRequired,
};
export default DonatePage;
export default DonatePage;

View file

@ -1,40 +1,40 @@
@import "../variables";
@import "../mixins";
.priceAmount {
display: flex;
width: 150px;
margin: 20px auto;
border: thin solid rgba(0, 0, 0, .25);
border-radius: 5px;
overflow: hidden;
line-height: 40px;
input {
flex-grow: 1;
border: none;
padding-left: 10px;
width: 1px;
border-right: thin solid rgba(0, 0, 0, .25);
}
div {
width: 20px;
text-align: center;
}
}
.donateButton {
@include button;
}
.sronly {
border: 0;
clip: rect(0, 0, 0, 0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
}
@import "../variables";
@import "../mixins";
.priceAmount {
display: flex;
width: 150px;
margin: 20px auto;
border: thin solid rgba(0, 0, 0, 0.25);
border-radius: 5px;
overflow: hidden;
line-height: 40px;
input {
flex-grow: 1;
border: none;
padding-left: 10px;
width: 1px;
border-right: thin solid rgba(0, 0, 0, 0.25);
}
div {
width: 20px;
text-align: center;
}
}
.donateButton {
@include button;
}
.sronly {
border: 0;
clip: rect(0, 0, 0, 0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
}

View file

@ -1,8 +1,8 @@
import React from "react"
import React from "react";
import Layout from "../../layouts/default";
import { Trans, useI18next } from "gatsby-plugin-react-i18next"
import { Trans, useI18next } from "gatsby-plugin-react-i18next";
import { graphql } from "gatsby";
import PropTypes from "prop-types"
import PropTypes from "prop-types";
export const query = graphql`
query GetThankYouPage($language: String!) {
@ -11,7 +11,7 @@ export const query = graphql`
contactEmail
}
}
locales: allLocale(filter: {language: {eq: $language}}) {
locales: allLocale(filter: { language: { eq: $language } }) {
edges {
node {
ns
@ -21,10 +21,10 @@ export const query = graphql`
}
}
}
`
`;
function ThankYouPage(props) {
const { site } = props.data
const { site } = props.data;
let contactEmail = site.siteMetadata.contactEmail;
const { t } = useI18next();
@ -32,9 +32,16 @@ function ThankYouPage(props) {
<Layout title={t("donate")}>
<section>
<article>
<h1><Trans>donateThanks</Trans></h1>
<h1>
<Trans>donateThanks</Trans>
</h1>
<p><Trans contactEmail={contactEmail} i18nKey="donateThanksText">donateThanksText<a href={"mailto:" + contactEmail}>{{ contactEmail }}</a></Trans></p>
<p>
<Trans contactEmail={contactEmail} i18nKey="donateThanksText">
donateThanksText
<a href={"mailto:" + contactEmail}>{{ contactEmail }}</a>
</Trans>
</p>
</article>
</section>
</Layout>
@ -42,7 +49,7 @@ function ThankYouPage(props) {
}
ThankYouPage.propTypes = {
data: PropTypes.object.isRequired
data: PropTypes.object.isRequired,
};
export default ThankYouPage;
export default ThankYouPage;

View file

@ -1,13 +1,13 @@
import React from "react"
import React from "react";
import Layout from "../layouts/default";
import { Trans, useI18next } from "gatsby-plugin-react-i18next"
import { graphql } from 'gatsby'
import PropTypes from "prop-types"
import { Trans, useI18next } from "gatsby-plugin-react-i18next";
import { graphql } from "gatsby";
import PropTypes from "prop-types";
import * as styles from "./friends.module.scss";
export const query = graphql`
query AllFriendsQuery($language: String!) {
query AllFriendsQuery($language: String!) {
allFriendsJson {
nodes {
name
@ -16,7 +16,7 @@ query AllFriendsQuery($language: String!) {
imageURL
}
}
locales: allLocale(filter: {language: {eq: $language}}) {
locales: allLocale(filter: { language: { eq: $language } }) {
edges {
node {
ns
@ -26,55 +26,71 @@ query AllFriendsQuery($language: String!) {
}
}
}
`
`;
const FriendsPage = ({ data }) => {
const { t } = useI18next();
const { t } = useI18next();
function shuffle(a) {
for (let i = a.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[a[i], a[j]] = [a[j], a[i]];
}
return a;
function shuffle(a) {
for (let i = a.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[a[i], a[j]] = [a[j], a[i]];
}
return a;
}
return (
<Layout title={t("friends")} description={t("friendsDescription")}>
<section>
<article>
<h1><Trans>social</Trans></h1>
return (
<Layout title={t("friends")} description={t("friendsDescription")}>
<section>
<article>
<h1>
<Trans>social</Trans>
</h1>
<p><Trans>friendsDescription</Trans></p>
<p>
<Trans>friendsDescription</Trans>
</p>
<div className={styles.friendsList}>
{
shuffle(data.allFriendsJson.nodes).map((friend) => {
return (
<div className={styles.friendProfile} key={friend.url + "#" + friend.name}>
<div className={styles.friendImage} style={{ backgroundImage: "url(" + friend.imageURL + ")" }}>
<span className={styles.friendName}>{friend.name}</span>
<span className={styles.friendTitle}>{friend.profession}</span>
</div>
<div className={styles.friendsList}>
{shuffle(data.allFriendsJson.nodes).map((friend) => {
return (
<div
className={styles.friendProfile}
key={friend.url + "#" + friend.name}
>
<div
className={styles.friendImage}
style={{ backgroundImage: "url(" + friend.imageURL + ")" }}
>
<span className={styles.friendName}>{friend.name}</span>
<span className={styles.friendTitle}>
{friend.profession}
</span>
</div>
<div className={styles.contactLinks}>
<a className={styles.contactLink} href={friend.url} target="_blank" rel="noreferrer"><i className="fas fa-globe-europe" aria-hidden="true"></i> {friend.url}</a>
</div>
</div>
);
})
}
</div>
</article>
</section>
</Layout>
);
}
FriendsPage.propTypes = {
data: PropTypes.object.isRequired
<div className={styles.contactLinks}>
<a
className={styles.contactLink}
href={friend.url}
target="_blank"
rel="noreferrer"
>
<i className="fas fa-globe-europe" aria-hidden="true"></i>{" "}
{friend.url}
</a>
</div>
</div>
);
})}
</div>
</article>
</section>
</Layout>
);
};
export default FriendsPage;
FriendsPage.propTypes = {
data: PropTypes.object.isRequired,
};
export default FriendsPage;

View file

@ -1,62 +1,62 @@
@import "../variables";
@import "../mixins";
.friendsList {
@include flexList;
.friendProfile {
@include cardGeneric;
display: flex;
flex-direction: column;
width: 300px;
flex-shrink: 0;
.friendImage {
width: 100%;
height: 300px;
background-position: center;
background-size: cover;
display: flex;
padding: 10px;
flex-direction: column-reverse;
text-shadow: 0 0 10px black, 0 0 10px black, 0 0 20px black;
.friendName {
font-size: 2em;
margin-top: -5px;
}
.friendTitle {
margin-top: auto;
}
}
.friendBio {
padding: 15px;
flex-grow: 1;
text-align: justify;
display: block;
padding-bottom: 0;
}
.contactLinks {
padding: 15px;
margin: 0;
display: flex;
flex-direction: column;
.contactLink {
transition: text-decoration .5s;
text-decoration: underline dotted rgba(0, 0, 0, 0);
padding: 6px 0 6px 25px;
color: $textColor;
>i {
color: $accentColor;
margin-left: -25px;
margin-right: 5px;
}
}
}
}
}
@import "../variables";
@import "../mixins";
.friendsList {
@include flexList;
.friendProfile {
@include cardGeneric;
display: flex;
flex-direction: column;
width: 300px;
flex-shrink: 0;
.friendImage {
width: 100%;
height: 300px;
background-position: center;
background-size: cover;
display: flex;
padding: 10px;
flex-direction: column-reverse;
text-shadow: 0 0 10px black, 0 0 10px black, 0 0 20px black;
.friendName {
font-size: 2em;
margin-top: -5px;
}
.friendTitle {
margin-top: auto;
}
}
.friendBio {
padding: 15px;
flex-grow: 1;
text-align: justify;
display: block;
padding-bottom: 0;
}
.contactLinks {
padding: 15px;
margin: 0;
display: flex;
flex-direction: column;
.contactLink {
transition: text-decoration 0.5s;
text-decoration: underline dotted rgba(0, 0, 0, 0);
padding: 6px 0 6px 25px;
color: $textColor;
> i {
color: $accentColor;
margin-left: -25px;
margin-right: 5px;
}
}
}
}
}

View file

@ -1,16 +1,15 @@
import * as React from "react"
import Layout from "../layouts/default"
import PropTypes from "prop-types"
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 * as styles from "./index.module.scss";
import * as projectStyles from "./projects.module.scss";
import { Trans, Link } from "gatsby-plugin-react-i18next"
import { Trans, Link } from "gatsby-plugin-react-i18next";
import { graphql } from "gatsby";
import anime from "animejs";
export const query = graphql`
query GetMetaAndProjects($language: String) {
site {
@ -24,7 +23,10 @@ export const query = graphql`
contactMastodonHref
}
}
allProjectsJson(filter: {lang: {eq: $language}, featured: {gte: 0}}, sort: {fields: featured, order: ASC}) {
allProjectsJson(
filter: { lang: { eq: $language }, featured: { gte: 0 } }
sort: { fields: featured, order: ASC }
) {
nodes {
lang
urlname
@ -40,7 +42,7 @@ export const query = graphql`
featured
}
}
locales: allLocale(filter: {language: {eq: $language}}) {
locales: allLocale(filter: { language: { eq: $language } }) {
edges {
node {
ns
@ -55,26 +57,29 @@ export const query = graphql`
class IndexPage extends React.Component {
componentDidMount() {
anime({
targets: ["."+styles.profileCard+" > span", "."+styles.profileCard+" a"],
targets: [
"." + styles.profileCard + " > span",
"." + styles.profileCard + " a",
],
opacity: [0, 1],
translateX: [100, 0],
duration: 250,
delay: anime.stagger(20),
easing: 'easeInOutCirc'
easing: "easeInOutCirc",
});
anime({
targets: ["."+styles.profileImageDummy],
targets: ["." + styles.profileImageDummy],
translateX: [0, -3],
translateY: [0, 3],
duration: 250,
easing: 'easeInOutCirc'
easing: "easeInOutCirc",
});
anime({
targets: ["."+styles.profileImage],
targets: ["." + styles.profileImage],
translateX: [0, 4],
translateY: [0, -4],
duration: 250,
easing: 'easeInOutCirc'
easing: "easeInOutCirc",
});
}
@ -85,45 +90,128 @@ class IndexPage extends React.Component {
<Layout title="Kevin Kandlbinder" transparentTopbar={true}>
<section className={styles.heroSection}>
<div className={styles.profile + " profile"}>
<div data-bg="url(https://cdn.kevink.dev/images/kevin/kevin-kandlbinder-03.jpg)" style={{ backgroundImage: "url(https://cdn.kevink.dev/images/kevin/kevin-kandlbinder-03.jpg)" }} className={styles.profileImage + " lazy"}></div>
<div
data-bg="url(https://cdn.kevink.dev/images/kevin/kevin-kandlbinder-03.jpg)"
style={{
backgroundImage:
"url(https://cdn.kevink.dev/images/kevin/kevin-kandlbinder-03.jpg)",
}}
className={styles.profileImage + " lazy"}
></div>
<div className={styles.profileImageDummy}></div>
<div className={styles.profileCard}>
<span className={styles.hello}><Trans>homeHello</Trans></span>
<span className={styles.hello}>
<Trans>homeHello</Trans>
</span>
<span className={styles.name}>Kevin Kandlbinder</span>
<span className={styles.description}><Trans>homeMe</Trans> <span id="descriptionType"><Trans>homeWebDeveloper</Trans></span>.</span>
<span className={styles.description}>
<Trans>homeMe</Trans>{" "}
<span id="descriptionType">
<Trans>homeWebDeveloper</Trans>
</span>
.
</span>
<div className={styles.contactLinks}>
<a className={styles.contactLink} href={"tel:" + meta.contactPhone} rel="me"><i className="fas fa-fw fa-phone"></i>{meta.contactPhone}</a>
<a className={styles.contactLink} href={"mailto:" + meta.contactEmail} rel="me"><i className="far fa-fw fa-envelope"></i>{meta.contactEmail}</a>
<a className={styles.contactLink} href={meta.mapsLink} rel="noreferrer " target="_blank"><i className="fas fa-fw fa-map-marker-alt"></i><Trans>homeMyLocation</Trans></a>
<a className={styles.contactLink} href={meta.contactMastodonHref} rel="noreferrer me" target="_blank"><i className="fab fa-fw fa-mastodon"></i>{meta.contactMastodon}</a>
<a className={styles.contactLink} href={"https://github.com/" + meta.contactGitHub} rel="noreferrer me" target="_blank"><i className="fab fa-fw fa-github"></i>{meta.contactGitHub}</a>
<a
className={styles.contactLink}
href={"tel:" + meta.contactPhone}
rel="me"
>
<i className="fas fa-fw fa-phone"></i>
{meta.contactPhone}
</a>
<a
className={styles.contactLink}
href={"mailto:" + meta.contactEmail}
rel="me"
>
<i className="far fa-fw fa-envelope"></i>
{meta.contactEmail}
</a>
<a
className={styles.contactLink}
href={meta.mapsLink}
rel="noreferrer "
target="_blank"
>
<i className="fas fa-fw fa-map-marker-alt"></i>
<Trans>homeMyLocation</Trans>
</a>
<a
className={styles.contactLink}
href={meta.contactMastodonHref}
rel="noreferrer me"
target="_blank"
>
<i className="fab fa-fw fa-mastodon"></i>
{meta.contactMastodon}
</a>
<a
className={styles.contactLink}
href={"https://github.com/" + meta.contactGitHub}
rel="noreferrer me"
target="_blank"
>
<i className="fab fa-fw fa-github"></i>
{meta.contactGitHub}
</a>
</div>
</div>
</div>
</section>
<section className="aboutSection">
<article>
<h1><Trans>homeAboutMe</Trans></h1>
<p><Trans>homeAboutMeHello</Trans><br /><Trans>homeAboutMeText</Trans></p>
<h1>
<Trans>homeAboutMe</Trans>
</h1>
<p>
<Trans>homeAboutMeHello</Trans>
<br />
<Trans>homeAboutMeText</Trans>
</p>
</article>
</section>
<a className={styles.creditSection} href="https://unsplash.com/@jannikkiel" target="_blank" rel="noreferrer">
<a
className={styles.creditSection}
href="https://unsplash.com/@jannikkiel"
target="_blank"
rel="noreferrer"
>
<div>
<span><i className="fas fa-fw fa-camera"></i> <Trans>homeImageCredit</Trans></span>
<span>
<i className="fas fa-fw fa-camera"></i>{" "}
<Trans>homeImageCredit</Trans>
</span>
<i className="fas fa-fw fa-chevron-right"></i>
</div>
</a>
<section className="featuredSection">
<article>
<h1><Trans>featuredProjects</Trans></h1>
<h1>
<Trans>featuredProjects</Trans>
</h1>
<div className={projectStyles.projectList}>
{this.props.data.allProjectsJson.nodes.map((project) => {
return (
<Link className={projectStyles.projectCard} key={project.lang + "/" + project.urlname} to={"/projects/" + project.urlname}>
<div className={projectStyles.projectCardImage} style={{ backgroundImage: "url(" + project.image.childImageSharp.resize.src + ")" }}>
<Link
className={projectStyles.projectCard}
key={project.lang + "/" + project.urlname}
to={"/projects/" + project.urlname}
>
<div
className={projectStyles.projectCardImage}
style={{
backgroundImage:
"url(" +
project.image.childImageSharp.resize.src +
")",
}}
>
<div className={projectStyles.projectCardMeta}>
<span className={projectStyles.projectCardTitle}>{project.name}</span>
<span className={projectStyles.projectCardTitle}>
{project.name}
</span>
<span>{project.shortDescription}</span>
</div>
</div>
@ -131,22 +219,27 @@ class IndexPage extends React.Component {
);
})}
</div>
<Link to="/projects" className={styles.seeMoreButton}><Trans>seeMore</Trans> <i className="fas fa-fw fa-chevron-right"></i></Link>
<Link to="/projects" className={styles.seeMoreButton}>
<Trans>seeMore</Trans>{" "}
<i className="fas fa-fw fa-chevron-right"></i>
</Link>
</article>
</section>
<Link className={styles.donationSection} to="/donate">
<div>
<span><Trans>donationCatchphrase</Trans></span>
<span>
<Trans>donationCatchphrase</Trans>
</span>
<i className="fas fa-fw fa-chevron-right"></i>
</div>
</Link>
</Layout>
)
);
}
}
IndexPage.propTypes = {
data: PropTypes.object.isRequired
}
data: PropTypes.object.isRequired,
};
export default IndexPage
export default IndexPage;

View file

@ -7,10 +7,11 @@
min-height: 600px;
padding-top: 100px;
overflow: hidden;
background: linear-gradient(to bottom, transparent 80%, $background), radial-gradient(ellipse at top left, #1f0ba659, transparent), radial-gradient(ellipse at bottom right, #4a086829, transparent);
background: linear-gradient(to bottom, transparent 80%, $background),
radial-gradient(ellipse at top left, #1f0ba659, transparent),
radial-gradient(ellipse at bottom right, #4a086829, transparent);
@media(pointer: coarse),
(pointer: none) {
@media (pointer: coarse), (pointer: none) {
min-height: 700px;
}
@ -24,7 +25,7 @@
.hello {
font-weight: 100;
opacity: .75;
opacity: 0.75;
display: block;
margin-bottom: -5px;
}
@ -47,13 +48,12 @@
}
.contactLink {
transition: text-decoration .5s;
transition: text-decoration 0.5s;
text-decoration: underline dotted rgba(0, 0, 0, 0);
padding: 6px 0 6px 25px;
color: $textColor;
@media(pointer: coarse),
(pointer: none) {
@media (pointer: coarse), (pointer: none) {
padding-top: 15px;
padding-bottom: 15px;
}
@ -61,10 +61,10 @@
.contactLink:hover,
.contactLink:active {
text-decoration: underline dotted rgba(0, 0, 0, .5);
text-decoration: underline dotted rgba(0, 0, 0, 0.5);
}
.contactLink>i {
.contactLink > i {
color: $accentColor;
margin-left: -25px;
margin-right: 5px;
@ -90,7 +90,7 @@
background-color: #1c1c1c;
background-size: cover;
background-position: center;
transition: transform .25s;
transition: transform 0.25s;
}
.profileImage {
@ -101,11 +101,10 @@
.profileImageDummy {
z-index: 10;
background: $accentColor;
opacity: .2;
opacity: 0.2;
}
@media (max-width: 590px) {
.profileImage,
.profileImageDummy {
display: none;
@ -115,11 +114,8 @@
padding: 20px 20px 20px 20px;
transform: translate(20px, 20px);
}
}
}
}
.amazonAlexaSection,
@ -131,13 +127,13 @@
.creditSection {
@include homeBanner;
>div {
> div {
padding: 15px !important;
line-height: 15px;
font-size: 1.2em;
color: white;
>span>i {
> span > i {
line-height: 15px !important;
}
}
@ -149,4 +145,4 @@
margin: 0 auto;
margin-top: 40px;
padding: 10px 20px;
}
}

View file

@ -1,11 +1,11 @@
import React from "react"
import React from "react";
import Layout from "../../layouts/default";
import { Trans, useI18next } from "gatsby-plugin-react-i18next"
import { Trans, useI18next } from "gatsby-plugin-react-i18next";
import { graphql } from "gatsby";
export const query = graphql`
query ($language: String!) {
locales: allLocale(filter: {language: {eq: $language}}) {
query($language: String!) {
locales: allLocale(filter: { language: { eq: $language } }) {
edges {
node {
ns
@ -15,27 +15,42 @@ export const query = graphql`
}
}
}
`
`;
export default function ImprintPage() {
const { t } = useI18next();
return (
<Layout title={t("imprint")}>
<section>
<article>
<h1>
<Trans>imprint</Trans>
</h1>
const { t } = useI18next();
return (
<Layout title={t("imprint")}>
<section>
<article>
<h1><Trans>imprint</Trans></h1>
<p>Angaben gemäß § 5 TMG</p><p>Kevin Kandlbinder<br />
Eichenweg 48<br />
25451 Quickborn <br />
</p><p> <strong>Vertreten durch: </strong><br />
Kevin Kandlbinder<br />
</p><p><strong>Kontakt:</strong> <br />
Telefon: +49 4106 8068004<br />
E-Mail: <a href='mailto:contact@kevink.dev'>contact@kevink.dev</a><br /></p>
</article>
</section>
</Layout>
);
}
<p>Angaben gemäß § 5 TMG</p>
<p>
Kevin Kandlbinder
<br />
Eichenweg 48
<br />
25451 Quickborn <br />
</p>
<p>
{" "}
<strong>Vertreten durch: </strong>
<br />
Kevin Kandlbinder
<br />
</p>
<p>
<strong>Kontakt:</strong> <br />
Telefon: +49 4106 8068004
<br />
E-Mail: <a href="mailto:contact@kevink.dev">contact@kevink.dev</a>
<br />
</p>
</article>
</section>
</Layout>
);
}

File diff suppressed because one or more lines are too long

View file

@ -1,11 +1,11 @@
import React from "react"
import React from "react";
import Layout from "../../layouts/default";
import { Trans, useI18next } from "gatsby-plugin-react-i18next"
import { Trans, useI18next } from "gatsby-plugin-react-i18next";
import { graphql } from "gatsby";
export const query = graphql`
query ($language: String!) {
locales: allLocale(filter: {language: {eq: $language}}) {
query($language: String!) {
locales: allLocale(filter: { language: { eq: $language } }) {
edges {
node {
ns
@ -15,36 +15,80 @@ export const query = graphql`
}
}
}
`
`;
export default function DisclaimerPage() {
const { t } = useI18next();
return (
<Layout title={t("disclaimer")}>
<section>
<article>
<h1>
<Trans>disclaimer</Trans>
</h1>
const { t } = useI18next();
return (
<Layout title={t("disclaimer")}>
<section>
<article>
<h1><Trans>disclaimer</Trans></h1>
<h2>Haftung für Inhalte</h2>
<h2>Haftung für Inhalte</h2>
<p>
Als Diensteanbieter sind wir gemäß § 7 Abs.1 TMG für eigene Inhalte
auf diesen Seiten nach den allgemeinen Gesetzen verantwortlich. Nach
§§ 8 bis 10 TMG sind wir als Diensteanbieter jedoch nicht
verpflichtet, übermittelte oder gespeicherte fremde Informationen zu
überwachen oder nach Umständen zu forschen, die auf eine
rechtswidrige Tätigkeit hinweisen.
</p>
<p>Als Diensteanbieter sind wir gemäß § 7 Abs.1 TMG für eigene Inhalte auf diesen Seiten nach den allgemeinen Gesetzen verantwortlich. Nach §§ 8 bis 10 TMG sind wir als Diensteanbieter jedoch nicht verpflichtet, übermittelte oder gespeicherte fremde Informationen zu überwachen oder nach Umständen zu forschen, die auf eine rechtswidrige Tätigkeit hinweisen.</p>
<p>
Verpflichtungen zur Entfernung oder Sperrung der Nutzung von
Informationen nach den allgemeinen Gesetzen bleiben hiervon
unberührt. Eine diesbezügliche Haftung ist jedoch erst ab dem
Zeitpunkt der Kenntnis einer konkreten Rechtsverletzung möglich. Bei
Bekanntwerden von entsprechenden Rechtsverletzungen werden wir diese
Inhalte umgehend entfernen.
</p>
<p>Verpflichtungen zur Entfernung oder Sperrung der Nutzung von Informationen nach den allgemeinen Gesetzen bleiben hiervon unberührt. Eine diesbezügliche Haftung ist jedoch erst ab dem Zeitpunkt der Kenntnis einer konkreten Rechtsverletzung möglich. Bei Bekanntwerden von entsprechenden Rechtsverletzungen werden wir diese Inhalte umgehend entfernen.</p>
<h2>Haftung für Links</h2>
<h2>Haftung für Links</h2>
<p>
Unser Angebot enthält Links zu externen Websites Dritter, auf deren
Inhalte wir keinen Einfluss haben. Deshalb können wir für diese
fremden Inhalte auch keine Gewähr übernehmen. Für die Inhalte der
verlinkten Seiten ist stets der jeweilige Anbieter oder Betreiber
der Seiten verantwortlich. Die verlinkten Seiten wurden zum
Zeitpunkt der Verlinkung auf mögliche Rechtsverstöße überprüft.
Rechtswidrige Inhalte waren zum Zeitpunkt der Verlinkung nicht
erkennbar.
</p>
<p>Unser Angebot enthält Links zu externen Websites Dritter, auf deren Inhalte wir keinen Einfluss haben. Deshalb können wir für diese fremden Inhalte auch keine Gewähr übernehmen. Für die Inhalte der verlinkten Seiten ist stets der jeweilige Anbieter oder Betreiber der Seiten verantwortlich. Die verlinkten Seiten wurden zum Zeitpunkt der Verlinkung auf mögliche Rechtsverstöße überprüft. Rechtswidrige Inhalte waren zum Zeitpunkt der Verlinkung nicht erkennbar.</p>
<p>
Eine permanente inhaltliche Kontrolle der verlinkten Seiten ist
jedoch ohne konkrete Anhaltspunkte einer Rechtsverletzung nicht
zumutbar. Bei Bekanntwerden von Rechtsverletzungen werden wir
derartige Links umgehend entfernen.
</p>
<p>Eine permanente inhaltliche Kontrolle der verlinkten Seiten ist jedoch ohne konkrete Anhaltspunkte einer Rechtsverletzung nicht zumutbar. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Links umgehend entfernen.</p>
<h2>Urheberrecht</h2>
<h2>Urheberrecht</h2>
<p>
Die durch die Seitenbetreiber erstellten Inhalte und Werke auf
diesen Seiten unterliegen dem deutschen Urheberrecht. Die
Vervielfältigung, Bearbeitung, Verbreitung und jede Art der
Verwertung außerhalb der Grenzen des Urheberrechtes bedürfen der
schriftlichen Zustimmung des jeweiligen Autors bzw. Erstellers.
Downloads und Kopien dieser Seite sind nur für den privaten, nicht
kommerziellen Gebrauch gestattet.
</p>
<p>Die durch die Seitenbetreiber erstellten Inhalte und Werke auf diesen Seiten unterliegen dem deutschen Urheberrecht. Die Vervielfältigung, Bearbeitung, Verbreitung und jede Art der Verwertung außerhalb der Grenzen des Urheberrechtes bedürfen der schriftlichen Zustimmung des jeweiligen Autors bzw. Erstellers. Downloads und Kopien dieser Seite sind nur für den privaten, nicht kommerziellen Gebrauch gestattet.</p>
<p>Soweit die Inhalte auf dieser Seite nicht vom Betreiber erstellt wurden, werden die Urheberrechte Dritter beachtet. Insbesondere werden Inhalte Dritter als solche gekennzeichnet. Sollten Sie trotzdem auf eine Urheberrechtsverletzung aufmerksam werden, bitten wir um einen entsprechenden Hinweis. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Inhalte umgehend entfernen.</p>
</article>
</section>
</Layout>
);
}
<p>
Soweit die Inhalte auf dieser Seite nicht vom Betreiber erstellt
wurden, werden die Urheberrechte Dritter beachtet. Insbesondere
werden Inhalte Dritter als solche gekennzeichnet. Sollten Sie
trotzdem auf eine Urheberrechtsverletzung aufmerksam werden, bitten
wir um einen entsprechenden Hinweis. Bei Bekanntwerden von
Rechtsverletzungen werden wir derartige Inhalte umgehend entfernen.
</p>
</article>
</section>
</Layout>
);
}

View file

@ -1,29 +1,29 @@
import React from "react"
import React from "react";
import Layout from "../layouts/default";
import { Trans, Link, useI18next } from "gatsby-plugin-react-i18next"
import { graphql } from 'gatsby'
import PropTypes from "prop-types"
import { Trans, Link, useI18next } from "gatsby-plugin-react-i18next";
import { graphql } from "gatsby";
import PropTypes from "prop-types";
import * as styles from "./projects.module.scss";
export const query = graphql`
query GetProjects($language: String) {
allProjectsJson(filter: {lang: {eq: $language}}) {
nodes {
lang
urlname
name
image {
childImageSharp {
resize(width: 400, quality: 90) {
src
query GetProjects($language: String) {
allProjectsJson(filter: { lang: { eq: $language } }) {
nodes {
lang
urlname
name
image {
childImageSharp {
resize(width: 400, quality: 90) {
src
}
}
}
shortDescription
}
shortDescription
}
}
locales: allLocale(filter: {language: {eq: $language}}) {
locales: allLocale(filter: { language: { eq: $language } }) {
edges {
node {
ns
@ -32,27 +32,42 @@ query GetProjects($language: String) {
}
}
}
}
`
}
`;
const ProjectsPage = ({ data }) => {
const { t } = useI18next();
return (
<Layout title={t("projects")} description={t("projectsDescription")}>
<section>
<article>
<h1><Trans>projects</Trans></h1>
<h1>
<Trans>projects</Trans>
</h1>
<p><Trans>projectsDescription</Trans></p>
<p>
<Trans>projectsDescription</Trans>
</p>
<div className={styles.projectList}>
{data.allProjectsJson.nodes.map((project) => {
return (
<Link className={styles.projectCard} key={project.lang + project.urlname} to={"/projects/" + project.urlname}>
<div className={styles.projectCardImage} style={{ backgroundImage: "url(" + project.image.childImageSharp.resize.src + ")" }}>
<Link
className={styles.projectCard}
key={project.lang + project.urlname}
to={"/projects/" + project.urlname}
>
<div
className={styles.projectCardImage}
style={{
backgroundImage:
"url(" + project.image.childImageSharp.resize.src + ")",
}}
>
<div className={styles.projectCardMeta}>
<span className={styles.projectCardTitle}>{project.name}</span>
<span className={styles.projectCardTitle}>
{project.name}
</span>
<span>{project.shortDescription}</span>
</div>
</div>
@ -64,10 +79,10 @@ const ProjectsPage = ({ data }) => {
</section>
</Layout>
);
}
};
ProjectsPage.propTypes = {
data: PropTypes.object
}
data: PropTypes.object,
};
export default ProjectsPage;
export default ProjectsPage;

View file

@ -1,89 +1,89 @@
@import "../variables";
@import "../mixins";
.projectList {
@include flexList;
margin: 15px 0;
}
.projectCard {
@include cardGeneric;
display: flex;
flex-direction: column;
flex-grow: 1;
width: 250px;
flex-shrink: 0;
.projectCardActivityIndicator {
position: absolute;
margin: 12px;
padding: 2px 5px;
border-radius: 3px;
&.activityIndicatorGreen {
background: #26de81;
}
&.activityIndicatorYellow {
background: #f7b731;
}
&.activityIndicatorRed {
background: #fc5c65;
}
&.activityIndicatorBlue {
background: #45aaf2;
}
}
.projectCardImage {
width: 100%;
height: 250px;
background-position: center;
background-size: cover;
text-shadow: 0 0 10px black, 0 0 10px black, 0 0 20px black;
}
.projectCardMeta {
padding: 10px;
flex-grow: 1;
display: flex;
flex-direction: column;
padding: 10px;
height: 100%;
background: linear-gradient(to bottom, transparent, black);
}
.projectCardTitle {
display: block;
font-size: 1.5em;
margin-top: auto;
}
.projectCardCTA {
display: block;
}
.projectCardCTA a {
@include buttonBasic;
}
.projectCardCTAContainer {
display: flex;
}
@media(max-width: 900px) {
.projectCardCTAContainer {
flex-direction: column;
}
.projectCardCTA:nth-child(2) {
border-left: none;
}
}
.projectCardCTAContainer>* {
flex-grow: 1;
}
}
@import "../variables";
@import "../mixins";
.projectList {
@include flexList;
margin: 15px 0;
}
.projectCard {
@include cardGeneric;
display: flex;
flex-direction: column;
flex-grow: 1;
width: 250px;
flex-shrink: 0;
.projectCardActivityIndicator {
position: absolute;
margin: 12px;
padding: 2px 5px;
border-radius: 3px;
&.activityIndicatorGreen {
background: #26de81;
}
&.activityIndicatorYellow {
background: #f7b731;
}
&.activityIndicatorRed {
background: #fc5c65;
}
&.activityIndicatorBlue {
background: #45aaf2;
}
}
.projectCardImage {
width: 100%;
height: 250px;
background-position: center;
background-size: cover;
text-shadow: 0 0 10px black, 0 0 10px black, 0 0 20px black;
}
.projectCardMeta {
padding: 10px;
flex-grow: 1;
display: flex;
flex-direction: column;
padding: 10px;
height: 100%;
background: linear-gradient(to bottom, transparent, black);
}
.projectCardTitle {
display: block;
font-size: 1.5em;
margin-top: auto;
}
.projectCardCTA {
display: block;
}
.projectCardCTA a {
@include buttonBasic;
}
.projectCardCTAContainer {
display: flex;
}
@media (max-width: 900px) {
.projectCardCTAContainer {
flex-direction: column;
}
.projectCardCTA:nth-child(2) {
border-left: none;
}
}
.projectCardCTAContainer > * {
flex-grow: 1;
}
}

View file

@ -1,13 +1,13 @@
import React from "react"
import React from "react";
import Layout from "../layouts/default";
import { Trans, Link, useI18next } from "gatsby-plugin-react-i18next"
import { graphql } from 'gatsby'
import PropTypes from "prop-types"
import { Trans, Link, useI18next } from "gatsby-plugin-react-i18next";
import { graphql } from "gatsby";
import PropTypes from "prop-types";
import * as styles from "./social.module.scss";
export const query = graphql`
query AllSocialsQuery($language: String!) {
query AllSocialsQuery($language: String!) {
allSocialsJson {
nodes {
image
@ -16,7 +16,7 @@ query AllSocialsQuery($language: String!) {
url
}
}
locales: allLocale(filter: {language: {eq: $language}}) {
locales: allLocale(filter: { language: { eq: $language } }) {
edges {
node {
ns
@ -25,42 +25,58 @@ query AllSocialsQuery($language: String!) {
}
}
}
}
`
}
`;
const SocialPage = ({ data }) => {
const { t } = useI18next();
return (
<Layout title={t("social")} description={t("socialDescription")}>
<section>
<article>
<h1>
<Trans>social</Trans>
</h1>
const { t } = useI18next();
return (
<Layout title={t("social")} description={t("socialDescription")}>
<section>
<article>
<h1><Trans>social</Trans></h1>
<p>
<Trans i18nKey="socialDescriptionWithLink">
socialDescriptionWith<Link to="/friends">Link</Link>
</Trans>
</p>
<p><Trans i18nKey="socialDescriptionWithLink">socialDescriptionWith<Link to="/friends">Link</Link></Trans></p>
<div className={styles.socialList}>
{
data.allSocialsJson.nodes.map((social) => {
return (
<a className={styles.socialCard} href={social.url} target="_blank" rel="noreferrer me" key={social.url}>
<div className={styles.socialImage} style={{ backgroundImage: "url(" + social.image + ")" }}>
<span className={styles.socialName}>{social.platformName}</span>
<span className={styles.socialUsername}>{social.platformHandle}</span>
</div>
</a>
);
})
}
</div>
</article>
</section>
</Layout>
);
}
SocialPage.propTypes = {
data: PropTypes.object.isRequired
<div className={styles.socialList}>
{data.allSocialsJson.nodes.map((social) => {
return (
<a
className={styles.socialCard}
href={social.url}
target="_blank"
rel="noreferrer me"
key={social.url}
>
<div
className={styles.socialImage}
style={{ backgroundImage: "url(" + social.image + ")" }}
>
<span className={styles.socialName}>
{social.platformName}
</span>
<span className={styles.socialUsername}>
{social.platformHandle}
</span>
</div>
</a>
);
})}
</div>
</article>
</section>
</Layout>
);
};
export default SocialPage;
SocialPage.propTypes = {
data: PropTypes.object.isRequired,
};
export default SocialPage;

View file

@ -1,32 +1,32 @@
@import "../variables";
@import "../mixins";
.socialList {
@include flexList;
.socialCard {
@include cardGeneric;
display: flex;
flex-direction: column;
.socialImage {
width: 300px;
height: 300px;
background-position: center;
background-size: cover;
display: flex;
padding: 10px;
flex-direction: column-reverse;
text-shadow: 0 0 10px black, 0 0 10px black, 0 0 20px black;
.socialName {
font-size: 2em;
margin-top: -5px;
}
.socialUsername {
margin-top: auto;
}
}
}
}
@import "../variables";
@import "../mixins";
.socialList {
@include flexList;
.socialCard {
@include cardGeneric;
display: flex;
flex-direction: column;
.socialImage {
width: 300px;
height: 300px;
background-position: center;
background-size: cover;
display: flex;
padding: 10px;
flex-direction: column-reverse;
text-shadow: 0 0 10px black, 0 0 10px black, 0 0 20px black;
.socialName {
font-size: 2em;
margin-top: -5px;
}
.socialUsername {
margin-top: auto;
}
}
}
}

View file

@ -1,40 +1,42 @@
import React from "react"
import { graphql } from "gatsby"
import { Trans, useTranslation } from 'gatsby-plugin-react-i18next';
import React from "react";
import { graphql } from "gatsby";
import { Trans, useTranslation } from "gatsby-plugin-react-i18next";
import Layout from "../layouts/default";
import PropTypes from "prop-types"
import PropTypes from "prop-types";
import * as styles from "./project.module.scss";
export const query = graphql`
query GetProject($urlname: String!, $lang: String!, $language: String!) {
allProjectsJson(filter: {urlname: {eq: $urlname}, lang: {eq: $lang}}) {
nodes {
lang
urlname
name
links {
github
website
query GetProject($urlname: String!, $lang: String!, $language: String!) {
allProjectsJson(
filter: { urlname: { eq: $urlname }, lang: { eq: $lang } }
) {
nodes {
lang
urlname
name
links {
github
website
}
image {
publicURL
}
longDescription
shortDescription
}
image {
publicURL
}
longDescription
shortDescription
}
}
locales: allLocale(filter: {language: {eq: $language}}) {
edges {
node {
ns
data
language
locales: allLocale(filter: { language: { eq: $language } }) {
edges {
node {
ns
data
language
}
}
}
}
}
`
`;
const ProjectTemplate = ({ data }) => {
const { t } = useTranslation();
@ -42,45 +44,74 @@ const ProjectTemplate = ({ data }) => {
let projectName = project.name;
return (
<Layout description={project.shortDescription} title={t("project") + ": " + projectName} transparentTopbar={true}>
<Layout
description={project.shortDescription}
title={t("project") + ": " + projectName}
transparentTopbar={true}
>
<section className={styles.projectHeader}>
<div style={{ paddingTop: 0 }}>
<div className={styles.headerBackground} style={{ backgroundImage: "url(" + project.image.publicURL + ")" }}></div>
<div
className={styles.headerBackground}
style={{ backgroundImage: "url(" + project.image.publicURL + ")" }}
></div>
<header>
<div className={styles.headerInner}>
<h1><Trans>project</Trans>: {projectName}</h1>
<h1>
<Trans>project</Trans>: {projectName}
</h1>
<span>{project.shortDescription}</span>
</div>
</header>
<div className={styles.headerPlaceholder}></div>
</div>
</section>
{project.longDescription != null ?
{project.longDescription != null ? (
<section className={styles.projectAbout}>
<article>
<h1><Trans projectName={projectName} i18nKey="projectAboutHeader">projectAboutHeader{{ projectName }}</Trans></h1>
<h1>
<Trans projectName={projectName} i18nKey="projectAboutHeader">
projectAboutHeader{{ projectName }}
</Trans>
</h1>
<p>{project.longDescription}</p>
</article>
</section>
: null}
{project.links !== null ?
) : null}
{project.links !== null ? (
<section className={styles.projectLinks}>
<div>
<h1>Links</h1>
<div className={styles.linkList}>
{project.links.github !== null ? <a href={project.links.github} target="_blank" rel="noreferrer"><i className="fab fa-github" aria-hidden="true"></i> <Trans>projectViewGitHub</Trans></a> : null}
{project.links.website !== null ? <a href={project.links.website} target="_blank" rel="noreferrer"><i className="fas fa-external-link-alt" aria-hidden="true"></i> <Trans>projectViewWebsite</Trans></a> : null}
{project.links.github !== null ? (
<a href={project.links.github} target="_blank" rel="noreferrer">
<i className="fab fa-github" aria-hidden="true"></i>{" "}
<Trans>projectViewGitHub</Trans>
</a>
) : null}
{project.links.website !== null ? (
<a
href={project.links.website}
target="_blank"
rel="noreferrer"
>
<i
className="fas fa-external-link-alt"
aria-hidden="true"
></i>{" "}
<Trans>projectViewWebsite</Trans>
</a>
) : null}
</div>
</div>
</section>
: null}
) : null}
</Layout>
);
}
};
ProjectTemplate.propTypes = {
data: PropTypes.object.isRequired
}
data: PropTypes.object.isRequired,
};
export default ProjectTemplate;
export default ProjectTemplate;

View file

@ -1,92 +1,99 @@
@import "../variables";
.projectHeader {
>div {
padding-bottom: 0 !important;
}
.headerBackground {
position: absolute;
left: 0;
width: 100%;
height: 400px;
background-position: center;
background-size: cover;
}
header {
position: absolute;
left: 0;
width: 100%;
height: 400px;
background: linear-gradient(to bottom, rgba($background, .95), rgba($background, .25) 20%, rgba($background, .35) 80%, rgba($background, 1) 100%);
.headerInner {
max-width: $layoutWidth;
width: 100%;
height: 100%;
margin: 0 auto;
display: flex;
flex-direction: column;
text-shadow: 0 0 10px black, 0 0 20px black;
padding: 10px 20px;
* {
margin: 0;
color: white;
font-size: 1.25em;
}
h1 {
font-size: 2.2em;
margin-top: auto;
}
}
}
.headerPlaceholder {
width: 100%;
height: 400px;
}
}
.projectAbout, .projectLinks {
&:nth-of-type(2) {
> div, > article {
padding-top: 20px;
}
}
}
.projectAbout {
background: #060606;
color: white;
}
.projectLinks {
.linkList {
display: flex;
justify-content: center;
flex-wrap: wrap;
}
a {
display: inline-block;
border: thin solid rgb(200, 200, 200);
border-radius: 5px;
padding: 10px 15px;
margin: 5px;
color: $textColor;
text-decoration-skip: none;
text-decoration: underline dotted currentColor;
i.fab,
i.fas,
i.fa,
i.far,
i.fal {
display: inline;
}
}
}
@import "../variables";
.projectHeader {
> div {
padding-bottom: 0 !important;
}
.headerBackground {
position: absolute;
left: 0;
width: 100%;
height: 400px;
background-position: center;
background-size: cover;
}
header {
position: absolute;
left: 0;
width: 100%;
height: 400px;
background: linear-gradient(
to bottom,
rgba($background, 0.95),
rgba($background, 0.25) 20%,
rgba($background, 0.35) 80%,
rgba($background, 1) 100%
);
.headerInner {
max-width: $layoutWidth;
width: 100%;
height: 100%;
margin: 0 auto;
display: flex;
flex-direction: column;
text-shadow: 0 0 10px black, 0 0 20px black;
padding: 10px 20px;
* {
margin: 0;
color: white;
font-size: 1.25em;
}
h1 {
font-size: 2.2em;
margin-top: auto;
}
}
}
.headerPlaceholder {
width: 100%;
height: 400px;
}
}
.projectAbout,
.projectLinks {
&:nth-of-type(2) {
> div,
> article {
padding-top: 20px;
}
}
}
.projectAbout {
background: #060606;
color: white;
}
.projectLinks {
.linkList {
display: flex;
justify-content: center;
flex-wrap: wrap;
}
a {
display: inline-block;
border: thin solid rgb(200, 200, 200);
border-radius: 5px;
padding: 10px 15px;
margin: 5px;
color: $textColor;
text-decoration-skip: none;
text-decoration: underline dotted currentColor;
i.fab,
i.fas,
i.fa,
i.far,
i.fal {
display: inline;
}
}
}