mirror of
https://github.com/Unkn0wnCat/KevinK.dev.js.git
synced 2025-06-26 14:27:31 +02:00
Run prettier on code
This commit is contained in:
parent
d542206091
commit
b8057f0e25
51 changed files with 28270 additions and 26529 deletions
161
src/_mixins.scss
161
src/_mixins.scss
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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}>×</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}>
|
||||
×
|
||||
</a>
|
||||
)
|
||||
</h2>
|
||||
<ul>
|
||||
{languages.map((lng) => (
|
||||
<li key={lng}>
|
||||
<Link to={originalPath} language={lng}>
|
||||
<Trans>{lng}</Trans>
|
||||
</Link>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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't exist, so you may as well <Link to="/">go home</Link>.
|
||||
Whoops... That page doesn't exist, so you may as well{" "}
|
||||
<Link to="/">go home</Link>.
|
||||
</p>
|
||||
</article>
|
||||
</section>
|
||||
</Layout>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export default NotFoundPage
|
||||
export default NotFoundPage;
|
||||
|
|
|
@ -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) + "¤cy_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) +
|
||||
"¤cy_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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
@ -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>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue