mirror of
https://github.com/kremalicious/portfolio.git
synced 2024-12-23 01:29:41 +01:00
update to Gatsby v3
This commit is contained in:
parent
c59ef8e4b6
commit
8da788e4d2
7669
package-lock.json
generated
7669
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
54
package.json
54
package.json
@ -20,25 +20,25 @@
|
|||||||
"new": "babel-node ./scripts/new.js"
|
"new": "babel-node ./scripts/new.js"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@giphy/js-fetch-api": "^2.2.2",
|
"@giphy/js-fetch-api": "^2.4.0",
|
||||||
"axios": "^0.21.1",
|
"axios": "^0.21.1",
|
||||||
"file-saver": "^2.0.5",
|
"file-saver": "^2.0.5",
|
||||||
"gatsby": "^2.32.4",
|
"gatsby": "^3.0.4",
|
||||||
"gatsby-image": "^2.11.0",
|
"gatsby-image": "^3.0.0",
|
||||||
"gatsby-plugin-manifest": "^2.12.0",
|
"gatsby-plugin-manifest": "^3.0.0",
|
||||||
"gatsby-plugin-matomo": "^0.9.0",
|
"gatsby-plugin-matomo": "^0.9.0",
|
||||||
"gatsby-plugin-offline": "^3.10.1",
|
"gatsby-plugin-offline": "^4.0.0",
|
||||||
"gatsby-plugin-postcss": "^3.6.0",
|
"gatsby-plugin-postcss": "^4.0.0",
|
||||||
"gatsby-plugin-react-helmet": "^3.9.0",
|
"gatsby-plugin-react-helmet": "^4.0.0",
|
||||||
"gatsby-plugin-sharp": "^2.13.4",
|
"gatsby-plugin-sharp": "^3.0.1",
|
||||||
"gatsby-plugin-sitemap": "^2.11.0",
|
"gatsby-plugin-sitemap": "^3.0.0",
|
||||||
"gatsby-plugin-svgr": "^2.1.0",
|
"gatsby-plugin-svgr": "^3.0.0-beta.0",
|
||||||
"gatsby-plugin-use-dark-mode": "^1.2.0",
|
"gatsby-plugin-use-dark-mode": "^1.3.0",
|
||||||
"gatsby-plugin-webpack-size": "^1.0.0",
|
"gatsby-plugin-webpack-size": "^2.0.1",
|
||||||
"gatsby-source-filesystem": "^2.10.0",
|
"gatsby-source-filesystem": "^3.0.0",
|
||||||
"gatsby-transformer-json": "^2.10.0",
|
"gatsby-transformer-json": "^3.0.0",
|
||||||
"gatsby-transformer-sharp": "^2.11.0",
|
"gatsby-transformer-sharp": "^3.0.0",
|
||||||
"gatsby-transformer-yaml": "^2.10.0",
|
"gatsby-transformer-yaml": "^3.0.0",
|
||||||
"intersection-observer": "^0.12.0",
|
"intersection-observer": "^0.12.0",
|
||||||
"react": "^17.0.1",
|
"react": "^17.0.1",
|
||||||
"react-dom": "^17.0.1",
|
"react-dom": "^17.0.1",
|
||||||
@ -55,25 +55,25 @@
|
|||||||
"vcf": "^2.1.0"
|
"vcf": "^2.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.13.1",
|
"@babel/core": "^7.13.10",
|
||||||
"@babel/eslint-parser": "^7.13.4",
|
"@babel/eslint-parser": "^7.13.10",
|
||||||
"@babel/node": "^7.13.0",
|
"@babel/node": "^7.13.10",
|
||||||
"@babel/preset-env": "^7.12.17",
|
"@babel/preset-env": "^7.13.10",
|
||||||
"@loadable/component": "^5.14.1",
|
"@loadable/component": "^5.14.1",
|
||||||
"@svgr/webpack": "^5.5.0",
|
"@svgr/webpack": "^5.5.0",
|
||||||
"@testing-library/jest-dom": "^5.11.9",
|
"@testing-library/jest-dom": "^5.11.9",
|
||||||
"@testing-library/react": "^11.2.5",
|
"@testing-library/react": "^11.2.5",
|
||||||
"@welldone-software/why-did-you-render": "^6.0.5",
|
"@welldone-software/why-did-you-render": "^6.1.0",
|
||||||
"babel-preset-gatsby": "^0.12.1",
|
"babel-preset-gatsby": "^0.12.2",
|
||||||
"chalk": "^4.1.0",
|
"chalk": "^4.1.0",
|
||||||
"eslint": "^7.20.0",
|
"eslint": "^7.21.0",
|
||||||
"eslint-config-prettier": "^8.0.0",
|
"eslint-config-prettier": "^8.1.0",
|
||||||
"eslint-plugin-graphql": "^4.0.0",
|
"eslint-plugin-graphql": "^4.0.0",
|
||||||
"eslint-plugin-prettier": "^3.3.1",
|
"eslint-plugin-prettier": "^3.3.1",
|
||||||
"eslint-plugin-react": "^7.22.0",
|
"eslint-plugin-react": "^7.22.0",
|
||||||
"eslint-plugin-react-hooks": "^4.2.0",
|
"eslint-plugin-react-hooks": "^4.2.0",
|
||||||
"eslint-plugin-testing-library": "^3.10.1",
|
"eslint-plugin-testing-library": "^3.10.1",
|
||||||
"gatsby-plugin-webpack-bundle-analyser-v2": "^1.1.20",
|
"gatsby-plugin-webpack-bundle-analyser-v2": "^1.1.21",
|
||||||
"identity-obj-proxy": "^3.0.0",
|
"identity-obj-proxy": "^3.0.0",
|
||||||
"jest": "^26.6.3",
|
"jest": "^26.6.3",
|
||||||
"jest-canvas-mock": "^2.3.1",
|
"jest-canvas-mock": "^2.3.1",
|
||||||
@ -83,9 +83,9 @@
|
|||||||
"prepend": "^1.0.2",
|
"prepend": "^1.0.2",
|
||||||
"prettier": "^2.2.1",
|
"prettier": "^2.2.1",
|
||||||
"slugify": "^1.4.7",
|
"slugify": "^1.4.7",
|
||||||
"stylelint": "^13.11.0",
|
"stylelint": "^13.12.0",
|
||||||
"stylelint-config-prettier": "^8.0.2",
|
"stylelint-config-prettier": "^8.0.2",
|
||||||
"stylelint-prettier": "^1.1.2"
|
"stylelint-prettier": "^1.2.0"
|
||||||
},
|
},
|
||||||
"browserslist": [
|
"browserslist": [
|
||||||
">0.2%",
|
">0.2%",
|
||||||
|
@ -7,7 +7,7 @@ import HostnameCheck from './atoms/HostnameCheck'
|
|||||||
import ThemeSwitch from './molecules/ThemeSwitch'
|
import ThemeSwitch from './molecules/ThemeSwitch'
|
||||||
import Header from './organisms/Header'
|
import Header from './organisms/Header'
|
||||||
import Footer from './organisms/Footer'
|
import Footer from './organisms/Footer'
|
||||||
import styles from './Layout.module.css'
|
import { screen } from './Layout.module.css'
|
||||||
import { useMeta } from '../hooks/use-meta'
|
import { useMeta } from '../hooks/use-meta'
|
||||||
|
|
||||||
// https://github.com/welldone-software/why-did-you-render
|
// https://github.com/welldone-software/why-did-you-render
|
||||||
@ -49,7 +49,7 @@ export default function Layout({ children, location }) {
|
|||||||
delayChildren={timeout}
|
delayChildren={timeout}
|
||||||
>
|
>
|
||||||
<Header minimal={!isHomepage} hide={isResume} />
|
<Header minimal={!isHomepage} hide={isResume} />
|
||||||
<main className={styles.screen}>{children}</main>
|
<main className={screen}>{children}</main>
|
||||||
</RoutesContainer>
|
</RoutesContainer>
|
||||||
</PoseGroup>
|
</PoseGroup>
|
||||||
|
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import styles from './Button.module.css'
|
import { button } from './Button.module.css'
|
||||||
|
|
||||||
const Button = (props) => (
|
const Button = (props) => (
|
||||||
<a className={styles.button} {...props}>
|
<a className={button} {...props}>
|
||||||
{props.children}
|
{props.children}
|
||||||
</a>
|
</a>
|
||||||
)
|
)
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import styles from './FullWidth.module.css'
|
import { fullWidth } from './FullWidth.module.css'
|
||||||
|
|
||||||
const FullWidth = ({ children }) => (
|
const FullWidth = ({ children }) => <div className={fullWidth}>{children}</div>
|
||||||
<div className={styles.fullWidth}>{children}</div>
|
|
||||||
)
|
|
||||||
|
|
||||||
FullWidth.propTypes = {
|
FullWidth.propTypes = {
|
||||||
children: PropTypes.node
|
children: PropTypes.node
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React, { PureComponent } from 'react'
|
import React, { PureComponent } from 'react'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import { Helmet } from 'react-helmet'
|
import { Helmet } from 'react-helmet'
|
||||||
import styles from './HostnameCheck.module.css'
|
import { hostnameInfo } from './HostnameCheck.module.css'
|
||||||
|
|
||||||
export default class HostnameCheck extends PureComponent {
|
export default class HostnameCheck extends PureComponent {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
@ -33,7 +33,7 @@ export default class HostnameCheck extends PureComponent {
|
|||||||
<Helmet>
|
<Helmet>
|
||||||
<meta name="robots" content="noindex,nofollow" />
|
<meta name="robots" content="noindex,nofollow" />
|
||||||
</Helmet>
|
</Helmet>
|
||||||
<aside className={styles.hostnameInfo}>
|
<aside className={hostnameInfo}>
|
||||||
<p>{`Hi there 👋. Please note that only the code and documentation of this
|
<p>{`Hi there 👋. Please note that only the code and documentation of this
|
||||||
site are open source. But my logo and the combination of typography,
|
site are open source. But my logo and the combination of typography,
|
||||||
colors, and layout making up my brand identity are not. Don't just
|
colors, and layout making up my brand identity are not. Don't just
|
||||||
|
@ -25,7 +25,7 @@ import {
|
|||||||
Info,
|
Info,
|
||||||
Dribbble
|
Dribbble
|
||||||
} from 'react-feather'
|
} from 'react-feather'
|
||||||
import styles from './Icon.module.css'
|
import { icon } from './Icon.module.css'
|
||||||
|
|
||||||
const Icon = memo(({ name, ...props }) => {
|
const Icon = memo(({ name, ...props }) => {
|
||||||
const components = {
|
const components = {
|
||||||
@ -62,7 +62,7 @@ const Icon = memo(({ name, ...props }) => {
|
|||||||
// const IconComp = Feather[name]
|
// const IconComp = Feather[name]
|
||||||
if (!IconMapped) return null
|
if (!IconMapped) return null
|
||||||
|
|
||||||
return <IconMapped className={styles.icon} {...props} />
|
return <IconMapped className={icon} {...props} />
|
||||||
})
|
})
|
||||||
|
|
||||||
Icon.displayName = 'Icon'
|
Icon.displayName = 'Icon'
|
||||||
|
@ -2,7 +2,7 @@ import React, { PureComponent } from 'react'
|
|||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import { graphql } from 'gatsby'
|
import { graphql } from 'gatsby'
|
||||||
import Img from 'gatsby-image'
|
import Img from 'gatsby-image'
|
||||||
import styles from './ProjectImage.module.css'
|
import { projectImage as styleProjectImage } from './ProjectImage.module.css'
|
||||||
|
|
||||||
export default class ProjectImage extends PureComponent {
|
export default class ProjectImage extends PureComponent {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
@ -13,7 +13,7 @@ export default class ProjectImage extends PureComponent {
|
|||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<Img
|
<Img
|
||||||
className={styles.projectImage}
|
className={styleProjectImage}
|
||||||
backgroundColor="transparent"
|
backgroundColor="transparent"
|
||||||
fluid={this.props.fluid}
|
fluid={this.props.fluid}
|
||||||
alt={this.props.alt}
|
alt={this.props.alt}
|
||||||
|
@ -3,7 +3,10 @@ import PropTypes from 'prop-types'
|
|||||||
import posed from 'react-pose'
|
import posed from 'react-pose'
|
||||||
import { fadeIn } from '../atoms/Transitions'
|
import { fadeIn } from '../atoms/Transitions'
|
||||||
import { useMeta } from '../../hooks/use-meta'
|
import { useMeta } from '../../hooks/use-meta'
|
||||||
import styles from './Availability.module.css'
|
import {
|
||||||
|
availability as styleAvailability,
|
||||||
|
available as styleAvailable
|
||||||
|
} from './Availability.module.css'
|
||||||
|
|
||||||
const Animation = posed.aside(fadeIn)
|
const Animation = posed.aside(fadeIn)
|
||||||
|
|
||||||
@ -11,8 +14,8 @@ const Availability = ({ hide }) => {
|
|||||||
const { availability } = useMeta()
|
const { availability } = useMeta()
|
||||||
const { status, available, unavailable } = availability
|
const { status, available, unavailable } = availability
|
||||||
const className = status
|
const className = status
|
||||||
? `${styles.availability} ${styles.available}`
|
? `${styleAvailability} ${styleAvailable}`
|
||||||
: `${styles.availability}`
|
: `${styleAvailability}`
|
||||||
const html = status ? available : unavailable
|
const html = status ? available : unavailable
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -4,7 +4,13 @@ import { Link } from 'gatsby'
|
|||||||
import posed from 'react-pose'
|
import posed from 'react-pose'
|
||||||
import { moveInBottom } from '../atoms/Transitions'
|
import { moveInBottom } from '../atoms/Transitions'
|
||||||
import { ReactComponent as Logo } from '../../images/logo.svg'
|
import { ReactComponent as Logo } from '../../images/logo.svg'
|
||||||
import styles from './LogoUnit.module.css'
|
import {
|
||||||
|
minimal as styleMinimal,
|
||||||
|
logounit,
|
||||||
|
logo,
|
||||||
|
title,
|
||||||
|
description
|
||||||
|
} from './LogoUnit.module.css'
|
||||||
import { useResume } from '../../hooks/use-resume'
|
import { useResume } from '../../hooks/use-resume'
|
||||||
|
|
||||||
LogoUnit.propTypes = {
|
LogoUnit.propTypes = {
|
||||||
@ -18,12 +24,10 @@ function LogoUnit({ minimal }) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Animation>
|
<Animation>
|
||||||
<Link className={minimal ? styles.minimal : styles.logounit} to={'/'}>
|
<Link className={minimal ? styleMinimal : logounit} to={'/'}>
|
||||||
<Logo className={styles.logo} />
|
<Logo className={logo} />
|
||||||
<h1 className={`p-name ${styles.title}`}>
|
<h1 className={`p-name ${title}`}>{basics.name.toLowerCase()}</h1>
|
||||||
{basics.name.toLowerCase()}
|
<p className={`p-job-title ${description}`}>
|
||||||
</h1>
|
|
||||||
<p className={`p-job-title ${styles.description}`}>
|
|
||||||
{basics.label.toLowerCase()}
|
{basics.label.toLowerCase()}
|
||||||
</p>
|
</p>
|
||||||
</Link>
|
</Link>
|
||||||
|
@ -4,10 +4,15 @@ import posed from 'react-pose'
|
|||||||
import { moveInTop } from '../atoms/Transitions'
|
import { moveInTop } from '../atoms/Transitions'
|
||||||
import Icon from '../atoms/Icon'
|
import Icon from '../atoms/Icon'
|
||||||
import { useResume } from '../../hooks/use-resume'
|
import { useResume } from '../../hooks/use-resume'
|
||||||
import styles from './Networks.module.css'
|
import {
|
||||||
|
link,
|
||||||
|
title,
|
||||||
|
small as styleSmall,
|
||||||
|
networks
|
||||||
|
} from './Networks.module.css'
|
||||||
|
|
||||||
const linkClasses = (key) =>
|
const linkClasses = (key) =>
|
||||||
key === 'Mail' ? `u-email ${styles.link}` : `u-url ${styles.link}`
|
key === 'Mail' ? `u-email ${link}` : `u-url ${link}`
|
||||||
|
|
||||||
const NetworkLink = ({ name, url }) => (
|
const NetworkLink = ({ name, url }) => (
|
||||||
<a
|
<a
|
||||||
@ -16,7 +21,7 @@ const NetworkLink = ({ name, url }) => (
|
|||||||
data-testid={`network-${name.toLowerCase()}`}
|
data-testid={`network-${name.toLowerCase()}`}
|
||||||
>
|
>
|
||||||
<Icon name={name} />
|
<Icon name={name} />
|
||||||
<span className={styles.title}>{name}</span>
|
<span className={title}>{name}</span>
|
||||||
</a>
|
</a>
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -32,7 +37,7 @@ function Networks({ small, hide }) {
|
|||||||
const Animation = posed.aside(moveInTop)
|
const Animation = posed.aside(moveInTop)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Animation className={small ? styles.small : styles.networks}>
|
<Animation className={small ? styleSmall : networks}>
|
||||||
<NetworkLink name="Mail" url={`mailto:${basics.email}`} />
|
<NetworkLink name="Mail" url={`mailto:${basics.email}`} />
|
||||||
|
|
||||||
{basics.profiles.map((profile) => (
|
{basics.profiles.map((profile) => (
|
||||||
|
@ -2,7 +2,7 @@ import React from 'react'
|
|||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import Button from '../atoms/Button'
|
import Button from '../atoms/Button'
|
||||||
import Icon from '../atoms/Icon'
|
import Icon from '../atoms/Icon'
|
||||||
import styles from './ProjectLinks.module.css'
|
import { projectLinks, title } from './ProjectLinks.module.css'
|
||||||
|
|
||||||
ProjectLinks.propTypes = {
|
ProjectLinks.propTypes = {
|
||||||
links: PropTypes.array
|
links: PropTypes.array
|
||||||
@ -10,8 +10,8 @@ ProjectLinks.propTypes = {
|
|||||||
|
|
||||||
export default function ProjectLinks({ links }) {
|
export default function ProjectLinks({ links }) {
|
||||||
return (
|
return (
|
||||||
<div className={styles.projectLinks}>
|
<div className={projectLinks}>
|
||||||
<h3 className={styles.title}>
|
<h3 className={title}>
|
||||||
Links <span>Learn more on the interwebz.</span>
|
Links <span>Learn more on the interwebz.</span>
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ import PropTypes from 'prop-types'
|
|||||||
import { Link, graphql, StaticQuery } from 'gatsby'
|
import { Link, graphql, StaticQuery } from 'gatsby'
|
||||||
import shortid from 'shortid'
|
import shortid from 'shortid'
|
||||||
import ProjectImage from '../atoms/ProjectImage'
|
import ProjectImage from '../atoms/ProjectImage'
|
||||||
import styles from './ProjectNav.module.css'
|
import { item, link, title, projectNav } from './ProjectNav.module.css'
|
||||||
|
|
||||||
const query = graphql`
|
const query = graphql`
|
||||||
query {
|
query {
|
||||||
@ -26,14 +26,10 @@ const query = graphql`
|
|||||||
`
|
`
|
||||||
|
|
||||||
const Project = ({ node, refCurrentItem }) => (
|
const Project = ({ node, refCurrentItem }) => (
|
||||||
<div className={styles.item} ref={refCurrentItem}>
|
<div className={item} ref={refCurrentItem}>
|
||||||
<Link className={styles.link} to={node.slug}>
|
<Link className={link} to={node.slug}>
|
||||||
<ProjectImage
|
<ProjectImage fluid={node.img.childImageSharp.fluid} alt={node.title} />
|
||||||
className={styles.image}
|
<h1 className={title}>{node.title}</h1>
|
||||||
fluid={node.img.childImageSharp.fluid}
|
|
||||||
alt={node.title}
|
|
||||||
/>
|
|
||||||
<h1 className={styles.title}>{node.title}</h1>
|
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
@ -88,7 +84,7 @@ export default class ProjectNav extends PureComponent {
|
|||||||
const projects = data.allProjectsYaml.edges
|
const projects = data.allProjectsYaml.edges
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<nav className={styles.projectNav} ref={this.scrollContainer}>
|
<nav className={projectNav} ref={this.scrollContainer}>
|
||||||
{projects.map(({ node }) => {
|
{projects.map(({ node }) => {
|
||||||
const isCurrent = node.slug === currentSlug
|
const isCurrent = node.slug === currentSlug
|
||||||
|
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import styles from './ProjectTechstack.module.css'
|
import { projectTechstack, title } from './ProjectTechstack.module.css'
|
||||||
|
|
||||||
const ProjectTechstack = ({ techstack }) => (
|
const ProjectTechstack = ({ techstack }) => (
|
||||||
<div className={styles.projectTechstack}>
|
<div className={projectTechstack}>
|
||||||
<h3 className={styles.title}>
|
<h3 className={title}>
|
||||||
Tools & Technologies <span>The tech stack I was involved with.</span>
|
Tools & Technologies <span>The tech stack I was involved with.</span>
|
||||||
</h3>
|
</h3>
|
||||||
<ul>
|
<ul>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import Icon from '../atoms/Icon'
|
import Icon from '../atoms/Icon'
|
||||||
import styles from './Repository.module.css'
|
import { repo as styleRepo, repoTitle, meta } from './Repository.module.css'
|
||||||
|
|
||||||
export default function Repository({ repo }) {
|
export default function Repository({ repo }) {
|
||||||
const {
|
const {
|
||||||
@ -23,12 +23,12 @@ export default function Repository({ repo }) {
|
|||||||
: homepage
|
: homepage
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.repo}>
|
<div className={styleRepo}>
|
||||||
<h1 className={styles.repoTitle}>
|
<h1 className={repoTitle}>
|
||||||
<a href={repoLink}>{isExternal ? full_name : name}</a>
|
<a href={repoLink}>{isExternal ? full_name : name}</a>
|
||||||
</h1>
|
</h1>
|
||||||
<p>{description}</p>
|
<p>{description}</p>
|
||||||
<p className={styles.meta}>
|
<p className={meta}>
|
||||||
{name === 'portfolio' || name === 'blog'
|
{name === 'portfolio' || name === 'blog'
|
||||||
? null
|
? null
|
||||||
: !isExternal &&
|
: !isExternal &&
|
||||||
|
@ -3,12 +3,18 @@ import PropTypes from 'prop-types'
|
|||||||
import { Helmet } from 'react-helmet'
|
import { Helmet } from 'react-helmet'
|
||||||
import useDarkMode from 'use-dark-mode'
|
import useDarkMode from 'use-dark-mode'
|
||||||
import Icon from '../atoms/Icon'
|
import Icon from '../atoms/Icon'
|
||||||
import styles from './ThemeSwitch.module.css'
|
import {
|
||||||
|
checkboxContainer,
|
||||||
|
checkboxFake,
|
||||||
|
themeSwitch,
|
||||||
|
checkbox,
|
||||||
|
label
|
||||||
|
} from './ThemeSwitch.module.css'
|
||||||
|
|
||||||
const ThemeToggle = memo(({ dark }) => (
|
const ThemeToggle = memo(({ dark }) => (
|
||||||
<span id="toggle" className={styles.checkboxContainer} aria-live="assertive">
|
<span id="toggle" className={checkboxContainer} aria-live="assertive">
|
||||||
<Icon name="Sun" className={!dark ? null : 'active'} />
|
<Icon name="Sun" className={!dark ? null : 'active'} />
|
||||||
<span className={styles.checkboxFake} />
|
<span className={checkboxFake} />
|
||||||
<Icon name="Moon" className={dark ? 'active' : null} />
|
<Icon name="Moon" className={dark ? 'active' : null} />
|
||||||
</span>
|
</span>
|
||||||
))
|
))
|
||||||
@ -69,9 +75,9 @@ function ThemeSwitch() {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<HeadItems themeColor={themeColor} bodyClass={bodyClass} />
|
<HeadItems themeColor={themeColor} bodyClass={bodyClass} />
|
||||||
<aside className={styles.themeSwitch}>
|
<aside className={themeSwitch}>
|
||||||
<label className={styles.checkbox}>
|
<label className={checkbox}>
|
||||||
<span className={styles.label}>Toggle Night Mode</span>
|
<span className={label}>Toggle Night Mode</span>
|
||||||
<ThemeToggleInput dark={value} toggleDark={toggle} />
|
<ThemeToggleInput dark={value} toggleDark={toggle} />
|
||||||
<ThemeToggle dark={value} />
|
<ThemeToggle dark={value} />
|
||||||
</label>
|
</label>
|
||||||
|
@ -3,24 +3,24 @@ import PropTypes from 'prop-types'
|
|||||||
import loadable from '@loadable/component'
|
import loadable from '@loadable/component'
|
||||||
import LogoUnit from '../molecules/LogoUnit'
|
import LogoUnit from '../molecules/LogoUnit'
|
||||||
import Networks from '../molecules/Networks'
|
import Networks from '../molecules/Networks'
|
||||||
import styles from './Footer.module.css'
|
import { footer, actions, copyright } from './Footer.module.css'
|
||||||
import { useMeta } from '../../hooks/use-meta'
|
import { useMeta } from '../../hooks/use-meta'
|
||||||
|
|
||||||
const LazyVcard = loadable(() => import('../atoms/Vcard'))
|
const LazyVcard = loadable(() => import('../atoms/Vcard'))
|
||||||
|
|
||||||
const FooterMarkup = ({ meta, year }) => (
|
const FooterMarkup = ({ meta, year }) => (
|
||||||
<footer className={`h-card ${styles.footer}`}>
|
<footer className={`h-card ${footer}`}>
|
||||||
<LogoUnit minimal />
|
<LogoUnit minimal />
|
||||||
<Networks small />
|
<Networks small />
|
||||||
|
|
||||||
<p className={styles.actions}>
|
<p className={actions}>
|
||||||
<LazyVcard />
|
<LazyVcard />
|
||||||
<a className="u-key" href={meta.gpg}>
|
<a className="u-key" href={meta.gpg}>
|
||||||
PGP/GPG key
|
PGP/GPG key
|
||||||
</a>
|
</a>
|
||||||
<a href={meta.bugs}>Found a bug?</a>
|
<a href={meta.bugs}>Found a bug?</a>
|
||||||
</p>
|
</p>
|
||||||
<p className={styles.copyright}>
|
<p className={copyright}>
|
||||||
<small>
|
<small>
|
||||||
© {year}{' '}
|
© {year}{' '}
|
||||||
<a className="u-url" href={meta.url}>
|
<a className="u-url" href={meta.url}>
|
||||||
|
@ -4,7 +4,7 @@ import Networks from '../molecules/Networks'
|
|||||||
import Availability from '../molecules/Availability'
|
import Availability from '../molecules/Availability'
|
||||||
|
|
||||||
import LogoUnit from '../molecules/LogoUnit'
|
import LogoUnit from '../molecules/LogoUnit'
|
||||||
import styles from './Header.module.css'
|
import { header, minimal as styleMinimal } from './Header.module.css'
|
||||||
import { useMeta } from '../../hooks/use-meta'
|
import { useMeta } from '../../hooks/use-meta'
|
||||||
|
|
||||||
Header.propTypes = {
|
Header.propTypes = {
|
||||||
@ -16,7 +16,7 @@ export default function Header({ minimal, hide }) {
|
|||||||
const { availability } = useMeta()
|
const { availability } = useMeta()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<header className={minimal ? styles.minimal : styles.header}>
|
<header className={minimal ? styleMinimal : header}>
|
||||||
{!hide && (
|
{!hide && (
|
||||||
<>
|
<>
|
||||||
<LogoUnit minimal={minimal} />
|
<LogoUnit minimal={minimal} />
|
||||||
|
@ -2,7 +2,11 @@ import React, { memo } from 'react'
|
|||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
|
|
||||||
import Repository from '../molecules/Repository'
|
import Repository from '../molecules/Repository'
|
||||||
import styles from './Repositories.module.css'
|
import {
|
||||||
|
section,
|
||||||
|
sectionTitle,
|
||||||
|
repos as styleRepos
|
||||||
|
} from './Repositories.module.css'
|
||||||
|
|
||||||
Repositories.propTypes = {
|
Repositories.propTypes = {
|
||||||
repos: PropTypes.array
|
repos: PropTypes.array
|
||||||
@ -12,9 +16,9 @@ function Repositories({ repos }) {
|
|||||||
if (!repos) return null
|
if (!repos) return null
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className={styles.section}>
|
<section className={section}>
|
||||||
<h1 className={styles.sectionTitle}>Open Source Projects</h1>
|
<h1 className={sectionTitle}>Open Source Projects</h1>
|
||||||
<div className={styles.repos}>
|
<div className={styleRepos}>
|
||||||
{repos.map((repo) => (
|
{repos.map((repo) => (
|
||||||
<Repository key={repo.name} repo={repo} />
|
<Repository key={repo.name} repo={repo} />
|
||||||
))}
|
))}
|
||||||
|
@ -2,7 +2,7 @@ import React from 'react'
|
|||||||
import shortid from 'shortid'
|
import shortid from 'shortid'
|
||||||
import { useResume } from '../../../hooks/use-resume'
|
import { useResume } from '../../../hooks/use-resume'
|
||||||
import Icon from '../../atoms/Icon'
|
import Icon from '../../atoms/Icon'
|
||||||
import styles from './Header.module.css'
|
import { title, description, contact, languagesList } from './Header.module.css'
|
||||||
|
|
||||||
export default function Header() {
|
export default function Header() {
|
||||||
const { basics, languages } = useResume()
|
const { basics, languages } = useResume()
|
||||||
@ -12,12 +12,12 @@ export default function Header() {
|
|||||||
<>
|
<>
|
||||||
<header>
|
<header>
|
||||||
<p>Résumé</p>
|
<p>Résumé</p>
|
||||||
<h1 className={styles.title}>{name}</h1>
|
<h1 className={title}>{name}</h1>
|
||||||
<h2 className={styles.label}>{label}</h2>
|
<h2 className={description}>{label}</h2>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<ul className={styles.contact}>
|
<ul className={contact}>
|
||||||
<li>
|
<li>
|
||||||
<a href={website}>
|
<a href={website}>
|
||||||
<Icon name="Compass" />
|
<Icon name="Compass" />
|
||||||
@ -32,7 +32,7 @@ export default function Header() {
|
|||||||
<Icon name="MapPin" />
|
<Icon name="MapPin" />
|
||||||
{location.city}, {location.countryCode}
|
{location.city}, {location.countryCode}
|
||||||
</li>
|
</li>
|
||||||
<li className={styles.languages}>
|
<li className={languagesList}>
|
||||||
<Icon name="Globe" />
|
<Icon name="Globe" />
|
||||||
{languages.map((item) => (
|
{languages.map((item) => (
|
||||||
<p key={shortid.generate()}>
|
<p key={shortid.generate()}>
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.label {
|
.description {
|
||||||
font-size: var(--font-size-h3);
|
font-size: var(--font-size-h3);
|
||||||
color: var(--text-color);
|
color: var(--text-color);
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
@ -37,20 +37,20 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.languages svg {
|
.languagesList svg {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.languages p {
|
.languagesList p {
|
||||||
margin-left: calc(var(--spacer) / 1.1);
|
margin-left: calc(var(--spacer) / 1.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.languages p:first-of-type {
|
.languagesList p:first-of-type {
|
||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.languages span {
|
.languagesList span {
|
||||||
font-size: var(--font-size-small);
|
font-size: var(--font-size-small);
|
||||||
margin-left: calc(var(--spacer) / 4);
|
margin-left: calc(var(--spacer) / 4);
|
||||||
color: var(--text-color-light);
|
color: var(--text-color-light);
|
||||||
|
@ -5,7 +5,12 @@ import remark2react from 'remark-react'
|
|||||||
import parse from 'remark-parse'
|
import parse from 'remark-parse'
|
||||||
import html from 'remark-html'
|
import html from 'remark-html'
|
||||||
import breaks from 'remark-breaks'
|
import breaks from 'remark-breaks'
|
||||||
import styles from './ResumeItem.module.css'
|
import {
|
||||||
|
resumeItem,
|
||||||
|
time,
|
||||||
|
styleTitle,
|
||||||
|
styleSubTitle
|
||||||
|
} from './ResumeItem.module.css'
|
||||||
|
|
||||||
const markdownOutput = (text) =>
|
const markdownOutput = (text) =>
|
||||||
remark()
|
remark()
|
||||||
@ -32,13 +37,13 @@ export default function ResumeItem({ content }) {
|
|||||||
const isSameYear = dateStart === dateEnd
|
const isSameYear = dateStart === dateEnd
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.resumeItem}>
|
<div className={resumeItem}>
|
||||||
<span className={styles.time}>
|
<span className={time}>
|
||||||
{dateStart}
|
{dateStart}
|
||||||
{dateEnd ? !isSameYear && `–${dateEnd}` : '–present'}{' '}
|
{dateEnd ? !isSameYear && `–${dateEnd}` : '–present'}{' '}
|
||||||
</span>
|
</span>
|
||||||
<h4 className={styles.title}>{title}</h4>
|
<h4 className={styleTitle}>{title}</h4>
|
||||||
<h5 className={styles.subTitle}>{subTitle}</h5>
|
<h5 className={styleSubTitle}>{subTitle}</h5>
|
||||||
{text && markdownOutput(text)}
|
{text && markdownOutput(text)}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
@ -26,12 +26,12 @@
|
|||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.title {
|
.styleTitle {
|
||||||
margin-bottom: calc(var(--spacer) / 3);
|
margin-bottom: calc(var(--spacer) / 3);
|
||||||
font-size: var(--font-size-h4);
|
font-size: var(--font-size-h4);
|
||||||
}
|
}
|
||||||
|
|
||||||
.subTitle {
|
.styleSubTitle {
|
||||||
color: var(--text-color-light);
|
color: var(--text-color-light);
|
||||||
font-size: var(--font-size-h5);
|
font-size: var(--font-size-h5);
|
||||||
}
|
}
|
||||||
|
@ -3,12 +3,12 @@ import PropTypes from 'prop-types'
|
|||||||
import shortid from 'shortid'
|
import shortid from 'shortid'
|
||||||
import Icon from '../../atoms/Icon'
|
import Icon from '../../atoms/Icon'
|
||||||
import ResumeItem, { ResumeItemContentProps } from './ResumeItem'
|
import ResumeItem, { ResumeItemContentProps } from './ResumeItem'
|
||||||
import styles from './ResumeSection.module.css'
|
import { subTitle } from './ResumeSection.module.css'
|
||||||
|
|
||||||
export default function ResumeSection({ section }) {
|
export default function ResumeSection({ section }) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<h3 className={styles.subTitle}>
|
<h3 className={subTitle}>
|
||||||
<Icon name={section.icon} />
|
<Icon name={section.icon} />
|
||||||
{section.name}
|
{section.name}
|
||||||
</h3>
|
</h3>
|
||||||
|
@ -3,7 +3,7 @@ import { Link } from 'gatsby'
|
|||||||
import { GiphyFetch } from '@giphy/js-fetch-api'
|
import { GiphyFetch } from '@giphy/js-fetch-api'
|
||||||
import SEO from '../components/atoms/SEO'
|
import SEO from '../components/atoms/SEO'
|
||||||
import Button from '../components/atoms/Button'
|
import Button from '../components/atoms/Button'
|
||||||
import styles from './404.module.css'
|
import { content } from './404.module.css'
|
||||||
|
|
||||||
// Famous last words:
|
// Famous last words:
|
||||||
// "It's just the 404 page so why not expose the dev API key"
|
// "It's just the 404 page so why not expose the dev API key"
|
||||||
@ -41,7 +41,7 @@ export default function NotFound() {
|
|||||||
<>
|
<>
|
||||||
<SEO />
|
<SEO />
|
||||||
|
|
||||||
<article className={styles.content}>
|
<article className={content}>
|
||||||
<h1>Shenanigans, page not found.</h1>
|
<h1>Shenanigans, page not found.</h1>
|
||||||
<p>
|
<p>
|
||||||
You might want to check the url, or{' '}
|
You might want to check the url, or{' '}
|
||||||
|
@ -4,7 +4,12 @@ import { Link, graphql } from 'gatsby'
|
|||||||
import shortid from 'shortid'
|
import shortid from 'shortid'
|
||||||
import SEO from '../components/atoms/SEO'
|
import SEO from '../components/atoms/SEO'
|
||||||
import ProjectImage from '../components/atoms/ProjectImage'
|
import ProjectImage from '../components/atoms/ProjectImage'
|
||||||
import styles from './index.module.css'
|
import {
|
||||||
|
project as styleProject,
|
||||||
|
projects as styleProjects,
|
||||||
|
title as styleTitle,
|
||||||
|
imageCount as styleImageCount
|
||||||
|
} from './index.module.css'
|
||||||
import Repositories from '../components/organisms/Repositories'
|
import Repositories from '../components/organisms/Repositories'
|
||||||
import Icon from '../components/atoms/Icon'
|
import Icon from '../components/atoms/Icon'
|
||||||
|
|
||||||
@ -33,14 +38,14 @@ function Project({ node, images }) {
|
|||||||
const imageCount = getImageCount(images, slug)
|
const imageCount = getImageCount(images, slug)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<article className={styles.project} key={slug}>
|
<article className={styleProject} key={slug}>
|
||||||
<Link to={slug}>
|
<Link to={slug}>
|
||||||
<h1 className={styles.title}>{title}</h1>
|
<h1 className={styleTitle}>{title}</h1>
|
||||||
<ProjectImage fluid={img.childImageSharp.fluid} alt={title} />
|
<ProjectImage fluid={img.childImageSharp.fluid} alt={title} />
|
||||||
|
|
||||||
{imageCount > 1 && (
|
{imageCount > 1 && (
|
||||||
<small
|
<small
|
||||||
className={styles.imageCount}
|
className={styleImageCount}
|
||||||
title={`${imageCount} project images`}
|
title={`${imageCount} project images`}
|
||||||
>
|
>
|
||||||
<Icon name="Image" /> {imageCount}
|
<Icon name="Image" /> {imageCount}
|
||||||
@ -64,7 +69,7 @@ function Home({ data, pageContext }) {
|
|||||||
<>
|
<>
|
||||||
<SEO />
|
<SEO />
|
||||||
|
|
||||||
<div className={styles.projects}>
|
<div className={styleProjects}>
|
||||||
{projects.map(({ node }) => (
|
{projects.map(({ node }) => (
|
||||||
<Project key={shortid.generate()} node={node} images={images} />
|
<Project key={shortid.generate()} node={node} images={images} />
|
||||||
))}
|
))}
|
||||||
|
@ -2,7 +2,7 @@ import React from 'react'
|
|||||||
import shortid from 'shortid'
|
import shortid from 'shortid'
|
||||||
import SEO from '../components/atoms/SEO'
|
import SEO from '../components/atoms/SEO'
|
||||||
import { useResume } from '../hooks/use-resume'
|
import { useResume } from '../hooks/use-resume'
|
||||||
import styles from './resume.module.css'
|
import { resume } from './resume.module.css'
|
||||||
import Header from '../components/pages/Resume/Header'
|
import Header from '../components/pages/Resume/Header'
|
||||||
import ResumeSection from '../components/pages/Resume/ResumeSection'
|
import ResumeSection from '../components/pages/Resume/ResumeSection'
|
||||||
|
|
||||||
@ -18,7 +18,7 @@ export default function Resume() {
|
|||||||
<>
|
<>
|
||||||
<SEO />
|
<SEO />
|
||||||
|
|
||||||
<div className={styles.resume}>
|
<div className={resume}>
|
||||||
<Header />
|
<Header />
|
||||||
|
|
||||||
{items.map((item) => (
|
{items.map((item) => (
|
||||||
|
@ -7,7 +7,12 @@ import ProjectTechstack from '../components/molecules/ProjectTechstack'
|
|||||||
import ProjectLinks from '../components/molecules/ProjectLinks'
|
import ProjectLinks from '../components/molecules/ProjectLinks'
|
||||||
import ProjectNav from '../components/molecules/ProjectNav'
|
import ProjectNav from '../components/molecules/ProjectNav'
|
||||||
import SEO from '../components/atoms/SEO'
|
import SEO from '../components/atoms/SEO'
|
||||||
import styles from './{ProjectsYaml.slug}.module.css'
|
import {
|
||||||
|
meta,
|
||||||
|
imageWrap,
|
||||||
|
headerTitle,
|
||||||
|
description
|
||||||
|
} from './{ProjectsYaml.slug}.module.css'
|
||||||
|
|
||||||
class ProjectMeta extends PureComponent {
|
class ProjectMeta extends PureComponent {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
@ -19,7 +24,7 @@ class ProjectMeta extends PureComponent {
|
|||||||
const { links, techstack } = this.props
|
const { links, techstack } = this.props
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<footer className={styles.meta}>
|
<footer className={meta}>
|
||||||
{!!links && <ProjectLinks links={links} />}
|
{!!links && <ProjectLinks links={links} />}
|
||||||
{!!techstack && <ProjectTechstack techstack={techstack} />}
|
{!!techstack && <ProjectTechstack techstack={techstack} />}
|
||||||
</footer>
|
</footer>
|
||||||
@ -37,7 +42,7 @@ class ProjectImages extends PureComponent {
|
|||||||
return (
|
return (
|
||||||
<FullWidth>
|
<FullWidth>
|
||||||
{this.props.projectImages.map(({ node }) => (
|
{this.props.projectImages.map(({ node }) => (
|
||||||
<div className={styles.imageWrap} key={node.id}>
|
<div className={imageWrap} key={node.id}>
|
||||||
<ProjectImage fluid={node.fluid} alt={this.props.title} />
|
<ProjectImage fluid={node.fluid} alt={this.props.title} />
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
@ -65,10 +70,10 @@ export default class Project extends PureComponent {
|
|||||||
|
|
||||||
<article>
|
<article>
|
||||||
<header>
|
<header>
|
||||||
<h1 className={styles.title}>{title}</h1>
|
<h1 className={headerTitle}>{title}</h1>
|
||||||
</header>
|
</header>
|
||||||
<div
|
<div
|
||||||
className={styles.description}
|
className={description}
|
||||||
dangerouslySetInnerHTML={{ __html: descriptionHtml }}
|
dangerouslySetInnerHTML={{ __html: descriptionHtml }}
|
||||||
/>
|
/>
|
||||||
<ProjectImages projectImages={projectImages} title={title} />
|
<ProjectImages projectImages={projectImages} title={title} />
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
margin-bottom: calc(var(--spacer) * 3);
|
margin-bottom: calc(var(--spacer) * 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
.title {
|
.headerTitle {
|
||||||
font-size: var(--font-size-h2);
|
font-size: var(--font-size-h2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -11,7 +11,7 @@
|
|||||||
margin-bottom: calc(var(--spacer) * 6);
|
margin-bottom: calc(var(--spacer) * 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
.title {
|
.headerTitle {
|
||||||
font-size: var(--font-size-h1);
|
font-size: var(--font-size-h1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user