1
0
mirror of https://github.com/kremalicious/portfolio.git synced 2025-02-14 21:10:41 +01:00

Merge pull request from kremalicious/feature/code

New open source section
This commit is contained in:
Matthias Kretschmann 2019-05-27 00:20:46 +02:00 committed by GitHub
commit 41c151971c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
37 changed files with 486 additions and 75 deletions

@ -1,7 +1,6 @@
dist: xenial
language: node_js
node_js:
- '11'
node_js: node
cache:
directories:

@ -17,6 +17,7 @@
- [🎉 Features](#-features)
- [⛵️ Lighthouse score](#-lighthouse-score)
- [💍 One data file to rule all pages](#-one-data-file-to-rule-all-pages)
- [🐱 GitHub repositories](#-github-repositories)
- [💅 Theme switcher](#-theme-switcher)
- [🏆 SEO component](#-seo-component)
- [📇 Client-side vCard creation](#-client-side-vcard-creation)
@ -52,6 +53,18 @@ Gatsby automatically creates pages from each item in that file utilizing the [`P
- [`content/projects.yml`](content/projects.yml)
- [`src/templates/Project.jsx`](src/templates/Project.jsx)
### 🐱 GitHub repositories
The open source section at the bottom of the front page shows selected GitHub repositories, sourced from GitHub.
On build time, all my public repositories are fetched from GitHub, then filtered against the ones defined in `content/repos.yml`, sorted by the last push date, and provided via the page context of the front page.
If you want to know how, have a look at the respective components:
- [`gatsby-node.js`](gatsby-node.js)
- [`content/repos.yml`](content/repos.yml)
- [`src/components/molecules/Repository.jsx`](src/components/molecules/Repository.jsx)
### 💅 Theme switcher
Includes a theme switcher which allows user to toggle between a light and a dark theme. Switching between them also happens automatically based on user's local sunset and sunrise times. Uses Cloudflare's geo location HTTP header functionality.

@ -1,4 +1,4 @@
title: Matthias Kretschmann
- title: Matthias Kretschmann
tagline: Designer & Developer
description: Portfolio of web & ui designer/developer hybrid Matthias Kretschmann.
url: https://matthiaskretschmann.com

11
content/repos.yml Normal file

@ -0,0 +1,11 @@
- user: kremalicious
repos:
- portfolio
- blog
- blowfish
- gatsby-plugin-matomo
- gatsby-redirect-from
- hyper-mac-pro
- appstorebadges
- kbdfun
- wp-icons-template

@ -2,7 +2,7 @@ const path = require('path')
const fs = require('fs')
const yaml = require('js-yaml')
const meta = yaml.load(fs.readFileSync('./content/meta.yml', 'utf8'))
const { title, description, url, matomoSite, matomoUrl } = meta
const { title, description, url, matomoSite, matomoUrl } = meta[0]
module.exports = {
siteMetadata: {

@ -1,7 +1,15 @@
/* eslint-disable no-console */
const path = require('path')
const remark = require('remark')
const markdown = require('remark-parse')
const html = require('remark-html')
const axios = require('axios')
const fs = require('fs')
const yaml = require('js-yaml')
const reposYaml = yaml.load(fs.readFileSync('./content/repos.yml', 'utf8'))
const { performance } = require('perf_hooks')
const chalk = require('chalk')
function truncate(n, useWordBoundary) {
if (this.length <= n) {
@ -15,6 +23,59 @@ function truncate(n, useWordBoundary) {
)
}
//
// Get GitHub repos
//
async function getGithubRepos(data) {
const allRepos = await axios.get(
`https://api.github.com/users/${data.user}/repos?per_page=100`
)
const repos = allRepos.data
// filter by what's defined in content/repos.yml
.filter(({ name }) => data.repos.includes(name))
// sort by pushed to, newest first
.sort((a, b) => b.pushed_at.localeCompare(a.pushed_at))
return repos
}
//
// Get GitHub repos once and store for later build stages
//
let repos
exports.onPreBootstrap = async () => {
const t0 = performance.now()
try {
repos = await getGithubRepos(reposYaml[0])
const t1 = performance.now()
const ms = t1 - t0
const s = ((ms / 1000) % 60).toFixed(3)
console.log(
chalk.green('success ') + `getGithubRepos: ${repos.length} repos - ${s} s`
)
} catch (error) {
throw Error(error.message)
}
}
//
// Add repos to front page's context
//
exports.onCreatePage = async ({ page, actions }) => {
const { createPage } = actions
if (page.path === '/')
createPage({
...page,
context: {
...page.context,
repos
}
})
}
exports.onCreateNode = ({ node, actions }) => {
const { createNodeField } = actions

@ -1,5 +1,5 @@
{
"contentYaml": {
"metaYaml": {
"title": "Matthias Kretschmann",
"tagline": "Designer & Developer",
"description": "Portfolio of web &amp; ui designer/developer hybrid Matthias Kretschmann.",

@ -0,0 +1,102 @@
[
{
"id": 133283555,
"node_id": "MDEwOlJlcG9zaXRvcnkxMzMyODM1NTU=",
"name": "portfolio",
"full_name": "kremalicious/portfolio",
"private": false,
"owner": {
"login": "kremalicious",
"id": 90316,
"node_id": "MDQ6VXNlcjkwMzE2",
"avatar_url": "https://avatars1.githubusercontent.com/u/90316?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/kremalicious",
"html_url": "https://github.com/kremalicious",
"followers_url": "https://api.github.com/users/kremalicious/followers",
"following_url": "https://api.github.com/users/kremalicious/following{/other_user}",
"gists_url": "https://api.github.com/users/kremalicious/gists{/gist_id}",
"starred_url": "https://api.github.com/users/kremalicious/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/kremalicious/subscriptions",
"organizations_url": "https://api.github.com/users/kremalicious/orgs",
"repos_url": "https://api.github.com/users/kremalicious/repos",
"events_url": "https://api.github.com/users/kremalicious/events{/privacy}",
"received_events_url": "https://api.github.com/users/kremalicious/received_events",
"type": "User",
"site_admin": false
},
"html_url": "https://github.com/kremalicious/portfolio",
"description": "👔 Portfolio thingy, built with Gatsby",
"fork": false,
"url": "https://api.github.com/repos/kremalicious/portfolio",
"forks_url": "https://api.github.com/repos/kremalicious/portfolio/forks",
"keys_url": "https://api.github.com/repos/kremalicious/portfolio/keys{/key_id}",
"collaborators_url": "https://api.github.com/repos/kremalicious/portfolio/collaborators{/collaborator}",
"teams_url": "https://api.github.com/repos/kremalicious/portfolio/teams",
"hooks_url": "https://api.github.com/repos/kremalicious/portfolio/hooks",
"issue_events_url": "https://api.github.com/repos/kremalicious/portfolio/issues/events{/number}",
"events_url": "https://api.github.com/repos/kremalicious/portfolio/events",
"assignees_url": "https://api.github.com/repos/kremalicious/portfolio/assignees{/user}",
"branches_url": "https://api.github.com/repos/kremalicious/portfolio/branches{/branch}",
"tags_url": "https://api.github.com/repos/kremalicious/portfolio/tags",
"blobs_url": "https://api.github.com/repos/kremalicious/portfolio/git/blobs{/sha}",
"git_tags_url": "https://api.github.com/repos/kremalicious/portfolio/git/tags{/sha}",
"git_refs_url": "https://api.github.com/repos/kremalicious/portfolio/git/refs{/sha}",
"trees_url": "https://api.github.com/repos/kremalicious/portfolio/git/trees{/sha}",
"statuses_url": "https://api.github.com/repos/kremalicious/portfolio/statuses/{sha}",
"languages_url": "https://api.github.com/repos/kremalicious/portfolio/languages",
"stargazers_url": "https://api.github.com/repos/kremalicious/portfolio/stargazers",
"contributors_url": "https://api.github.com/repos/kremalicious/portfolio/contributors",
"subscribers_url": "https://api.github.com/repos/kremalicious/portfolio/subscribers",
"subscription_url": "https://api.github.com/repos/kremalicious/portfolio/subscription",
"commits_url": "https://api.github.com/repos/kremalicious/portfolio/commits{/sha}",
"git_commits_url": "https://api.github.com/repos/kremalicious/portfolio/git/commits{/sha}",
"comments_url": "https://api.github.com/repos/kremalicious/portfolio/comments{/number}",
"issue_comment_url": "https://api.github.com/repos/kremalicious/portfolio/issues/comments{/number}",
"contents_url": "https://api.github.com/repos/kremalicious/portfolio/contents/{+path}",
"compare_url": "https://api.github.com/repos/kremalicious/portfolio/compare/{base}...{head}",
"merges_url": "https://api.github.com/repos/kremalicious/portfolio/merges",
"archive_url": "https://api.github.com/repos/kremalicious/portfolio/{archive_format}{/ref}",
"downloads_url": "https://api.github.com/repos/kremalicious/portfolio/downloads",
"issues_url": "https://api.github.com/repos/kremalicious/portfolio/issues{/number}",
"pulls_url": "https://api.github.com/repos/kremalicious/portfolio/pulls{/number}",
"milestones_url": "https://api.github.com/repos/kremalicious/portfolio/milestones{/number}",
"notifications_url": "https://api.github.com/repos/kremalicious/portfolio/notifications{?since,all,participating}",
"labels_url": "https://api.github.com/repos/kremalicious/portfolio/labels{/name}",
"releases_url": "https://api.github.com/repos/kremalicious/portfolio/releases{/id}",
"deployments_url": "https://api.github.com/repos/kremalicious/portfolio/deployments",
"created_at": "2018-05-13T23:53:31Z",
"updated_at": "2019-05-26T19:34:49Z",
"pushed_at": "2019-05-26T19:35:10Z",
"git_url": "git://github.com/kremalicious/portfolio.git",
"ssh_url": "git@github.com:kremalicious/portfolio.git",
"clone_url": "https://github.com/kremalicious/portfolio.git",
"svn_url": "https://github.com/kremalicious/portfolio",
"homepage": "https://matthiaskretschmann.com",
"size": 135135,
"stargazers_count": 55,
"watchers_count": 55,
"language": "JavaScript",
"has_issues": true,
"has_projects": false,
"has_downloads": true,
"has_wiki": false,
"has_pages": false,
"forks_count": 5,
"mirror_url": null,
"archived": false,
"disabled": false,
"open_issues_count": 1,
"license": {
"key": "mit",
"name": "MIT License",
"spdx_id": "MIT",
"url": "https://api.github.com/licenses/mit",
"node_id": "MDc6TGljZW5zZTEz"
},
"forks": 5,
"open_issues": 1,
"watchers": 55,
"default_branch": "master"
}
]

@ -23,6 +23,7 @@
"new": "babel-node ./scripts/new.js"
},
"dependencies": {
"axios": "^0.18.0",
"classnames": "^2.2.6",
"file-saver": "^2.0.1",
"gatsby": "^2.7.1",
@ -63,6 +64,7 @@
"babel-eslint": "^10.0.1",
"babel-jest": "^24.7.1",
"babel-preset-gatsby": "^0.1.11",
"chalk": "^2.4.2",
"eslint": "^5.16.0",
"eslint-config-prettier": "^4.2.0",
"eslint-loader": "^2.1.2",

@ -16,7 +16,7 @@ import styles from './Layout.module.scss'
const query = graphql`
query {
contentYaml {
metaYaml {
allowedHosts
}
}
@ -41,7 +41,7 @@ export default class Layout extends PureComponent {
<StaticQuery
query={query}
render={data => {
const { allowedHosts } = data.contentYaml
const { allowedHosts } = data.metaYaml
return (
<>

@ -5,7 +5,7 @@
width: 100%;
color: $brand-cyan;
text-align: center;
border-radius: .25rem;
border-radius: $border-radius;
padding: $spacer / 4 $spacer / 2;
transition-property: all;
background: rgba(#fff, .15);

@ -10,6 +10,7 @@ import { ReactComponent as Dribbble } from '../../images/dribbble.svg'
import { ReactComponent as Email } from '../../images/email.svg'
import { ReactComponent as Blog } from '../../images/blog.svg'
import { ReactComponent as Twitter } from '../../images/twitter.svg'
import { ReactComponent as Star } from '../../images/star.svg'
const LinkIcon = ({ title, type, ...props }) => {
let typeOrTitle = type ? type : title
@ -39,6 +40,8 @@ const LinkIcon = ({ title, type, ...props }) => {
return <Blog {...props} />
case 'Twitter':
return <Twitter {...props} />
case 'star':
return <Star {...props} />
default:
return null
}

@ -5,7 +5,7 @@ import { StaticQuery, graphql } from 'gatsby'
const query = graphql`
query {
contentYaml {
metaYaml {
title
tagline
description
@ -75,7 +75,7 @@ export default class SEO extends PureComponent {
query={query}
render={data => {
const { project } = this.props
const meta = data.contentYaml
const meta = data.metaYaml
const title = (project && project.title) || null
const description =
(project && project.fields.excerpt) || meta.description

@ -19,7 +19,7 @@ const TypekitScript = typekitID => (
const query = graphql`
query {
contentYaml {
metaYaml {
typekitID
}
}
@ -29,7 +29,7 @@ const Typekit = () => (
<StaticQuery
query={query}
render={data => {
const { typekitID } = data.contentYaml
const { typekitID } = data.metaYaml
return (
typekitID && (

@ -5,7 +5,7 @@ import vCard from 'vcf'
const query = graphql`
query {
contentYaml {
metaYaml {
title
tagline
description
@ -37,7 +37,7 @@ export default class Vcard extends PureComponent {
<StaticQuery
query={query}
render={data => {
const meta = data.contentYaml
const meta = data.metaYaml
const handleAddressbookClick = e => {
e.preventDefault()

@ -24,14 +24,14 @@ describe('Vcard', () => {
})
it('combined vCard download process finishes', async () => {
await init(data.contentYaml)
await init(data.metaYaml)
expect(global.URL.createObjectURL).toHaveBeenCalledTimes(1)
})
it('vCard can be constructed', async () => {
const vcard = await constructVcard(
'data:image/jpeg;base64,00',
data.contentYaml
data.metaYaml
)
expect(vcard).toBeDefined()
})

@ -1,7 +1,7 @@
@import 'variables';
.availability {
border-radius: .25rem;
border-radius: $border-radius;
color: $text-color-light;
z-index: 2;
padding: $spacer / 2;

@ -14,7 +14,7 @@ describe('Availability', () => {
it('renders correctly when status: true', () => {
useStaticQuery.mockImplementationOnce(() => {
return {
contentYaml: {
metaYaml: {
availability: {
status: true,
available: 'I am available.',
@ -32,7 +32,7 @@ describe('Availability', () => {
it('renders correctly when status: false', () => {
useStaticQuery.mockImplementationOnce(() => {
return {
contentYaml: {
metaYaml: {
availability: {
status: false,
available: 'I am available.',

@ -9,7 +9,7 @@ import styles from './LogoUnit.module.scss'
const query = graphql`
query {
contentYaml {
metaYaml {
title
tagline
}
@ -35,7 +35,7 @@ export default class LogoUnit extends PureComponent {
<StaticQuery
query={query}
render={data => {
const { title, tagline } = data.contentYaml
const { title, tagline } = data.metaYaml
return (
<div className={this.wrapClasses}>

@ -10,7 +10,7 @@ beforeEach(() => {
describe('LogoUnit', () => {
it('renders correctly from data file values', () => {
const { title, tagline } = data.contentYaml
const { title, tagline } = data.metaYaml
const { container, getByTestId } = render(<LogoUnit />)
expect(container.firstChild).toBeInTheDocument()

@ -10,7 +10,7 @@ beforeEach(() => {
describe('Networks', () => {
it('renders correctly from data file values', () => {
const { social } = data.contentYaml
const { social } = data.metaYaml
const { container, getByTestId } = render(<Networks />)
expect(container.firstChild).toBeInTheDocument()

@ -9,7 +9,7 @@
@media (min-width: $projectImageMaxWidth) {
max-width: $projectImageMaxWidth;
border-radius: .25rem;
border-radius: $border-radius;
overflow: hidden;
}

@ -15,7 +15,7 @@
padding: $spacer / 4;
text-align: center;
background: rgba(#fff, .15);
border-radius: .25rem;
border-radius: $border-radius;
border: .05rem solid transparent;
color: $brand-grey-light;
font-size: $font-size-small;

@ -0,0 +1,45 @@
import React from 'react'
import PropTypes from 'prop-types'
import LinkIcon from '../atoms/LinkIcon'
import styles from './Repository.module.scss'
const Repository = ({ repo }) => {
const { name, description, html_url, homepage, stargazers_count } = repo
// for blog & portfolio and if there's no homepage, use github url
// else use homepage field
const repoLink =
name === 'blog' || name === 'portfolio' || !homepage ? html_url : homepage
return (
<div className={styles.repo}>
<h1 className={styles.repoTitle}>
<a href={repoLink}>{name}</a>
</h1>
<p>{description}</p>
<p className={styles.meta}>
{name === 'portfolio' || name === 'blog'
? null
: homepage && (
<a href={homepage}>
<LinkIcon title="website" /> Learn more
</a>
)}
<a href={html_url}>
<LinkIcon title="github" /> GitHub
</a>
<a href={`${html_url}/stargazers`}>
<LinkIcon title="star" /> {stargazers_count}
</a>
</p>
</div>
)
}
Repository.propTypes = {
repo: PropTypes.object.isRequired
}
export default Repository

@ -0,0 +1,59 @@
@import 'variables';
.repo {
padding: $spacer;
border-radius: $border-radius;
background: rgba(#fff, .15);
box-shadow: 0 3px 5px rgba($brand-main, .1),
0 5px 16px rgba($brand-main, .1);
display: flex;
flex-wrap: wrap;
align-items: flex-start;
:global(.dark) & {
background: darken($body-background-color--dark, 1%);
box-shadow: 0 3px 5px rgba(darken($brand-main, 20%), .1),
0 5px 16px rgba(darken($brand-main, 20%), .1);
}
> * {
width: 100%;
}
p {
font-size: $font-size-small;
}
p:last-child {
margin: 0;
}
}
.repoTitle {
font-size: $font-size-h4;
margin-bottom: $spacer / 2;
}
.meta {
font-size: $font-size-small;
align-self: flex-end;
display: flex;
justify-content: space-between;
a {
display: inline-block;
color: $brand-grey-light;
font-variant-numeric: lining-nums;
&:hover,
&:focus {
color: $brand-cyan;
}
}
svg {
fill: currentColor;
width: $font-size-mini;
height: $font-size-mini;
}
}

@ -0,0 +1,40 @@
import React from 'react'
import { render } from 'react-testing-library'
import Repository from './Repository'
import repos from '../../../jest/__fixtures__/repos.json'
describe('Repository', () => {
it('renders correctly', () => {
const { container } = render(<Repository repo={repos[0]} />)
expect(container.firstChild).toBeInTheDocument()
})
it('uses html_url as main link for portfolio & blog', () => {
const repo1 = {
name: 'portfolio',
html_url: 'html_url'
}
const { container } = render(<Repository repo={repo1} />)
expect(container.querySelector('h1 > a').getAttribute('href')).toBe(
repo1.html_url
)
})
it('renders homepage link when provided', () => {
const repo = {
name: 'Hello',
homepage: 'hello'
}
const { container } = render(<Repository repo={repo} />)
expect(container.querySelectorAll('p:last-child a').length).toBe(3)
})
it('renders no link without homepage', () => {
const repo = { name: 'Hello' }
const { container } = render(<Repository repo={repo} />)
expect(container.querySelectorAll('p:last-child a').length).toBe(2)
})
})

@ -14,7 +14,7 @@ const query = graphql`
bugs
}
contentYaml {
metaYaml {
title
url
gpg
@ -68,7 +68,7 @@ export default class Footer extends PureComponent {
query={query}
render={data => {
const pkg = data.portfolioJson
const meta = data.contentYaml
const meta = data.metaYaml
return <FooterMarkup year={this.state.year} pkg={pkg} meta={meta} />
}}

@ -10,7 +10,7 @@ import styles from './Header.module.scss'
const query = graphql`
query {
contentYaml {
metaYaml {
availability {
status
}
@ -30,7 +30,7 @@ export default class Header extends PureComponent {
<StaticQuery
query={query}
render={data => {
const meta = data.contentYaml
const meta = data.metaYaml
let headerClasses = classNames([styles.header], {
[styles.minimal]: minimal

@ -0,0 +1,24 @@
import React, { PureComponent } from 'react'
import PropTypes from 'prop-types'
import Repository from '../molecules/Repository'
import styles from './Repositories.module.scss'
export default class Repositories extends PureComponent {
static propTypes = {
repos: PropTypes.array.isRequired
}
render() {
return (
<section className={styles.section}>
<h1 className={styles.sectionTitle}>Open Source Projects</h1>
<div className={styles.repos}>
{this.props.repos.map(repo => (
<Repository key={repo.name} repo={repo} />
))}
</div>
</section>
)
}
}

@ -0,0 +1,29 @@
@import 'variables';
.section {
max-width: calc(#{$projectImageMaxWidth} - #{$spacer * 2});
margin: $spacer * 3 auto 0 auto;
padding-left: $spacer;
padding-right: $spacer;
}
.sectionTitle {
font-size: $font-size-h3;
margin-bottom: $spacer * 2;
text-align: center;
}
.repos {
display: grid;
grid-template-columns: 1fr;
grid-gap: $spacer * 2;
@media (min-width: $screen-sm) {
grid-template-columns: 1fr 1fr;
grid-gap: $spacer * 2;
}
@media (min-width: $screen-md) {
grid-gap: $spacer * 3;
}
}

@ -0,0 +1,11 @@
import React from 'react'
import { render } from 'react-testing-library'
import Repositories from './Repositories'
import repos from '../../../jest/__fixtures__/repos.json'
describe('Repositories', () => {
it('renders correctly', () => {
const { container } = render(<Repositories repos={repos} />)
expect(container.firstChild).toBeInTheDocument()
})
})

@ -2,7 +2,7 @@ import { useStaticQuery, graphql } from 'gatsby'
const query = graphql`
query Meta {
contentYaml {
metaYaml {
title
tagline
description
@ -31,6 +31,6 @@ const query = graphql`
`
export const useMeta = () => {
const { contentYaml } = useStaticQuery(query)
return contentYaml
const { metaYaml } = useStaticQuery(query)
return metaYaml
}

3
src/images/star.svg Normal file

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<polygon points="22.136 19.625 32 12 20 12 16 0 12 12 0 12 9.875 19.594 6 32 16.016 24.32 26.008 32"/>
</svg>

After

(image error) Size: 196 B

@ -16,8 +16,16 @@ describe('Home', () => {
...projectImageFiles
}
const pageContext = {
repos: [
{
name: 'Hello'
}
]
}
it('renders correctly from data file values', () => {
const { container } = render(<Home data={data} />)
const { container } = render(<Home data={data} pageContext={pageContext} />)
expect(container.firstChild).toBeInTheDocument()
})
})

@ -5,6 +5,7 @@ import SEO from '../components/atoms/SEO'
import ProjectImage from '../components/molecules/ProjectImage'
import { ReactComponent as Images } from '../images/images.svg'
import styles from './index.module.scss'
import Repositories from '../components/organisms/Repositories'
function getImageCount(images, slug) {
let array = []
@ -19,12 +20,12 @@ function getImageCount(images, slug) {
export default class Home extends PureComponent {
static propTypes = {
data: PropTypes.object,
location: PropTypes.object
data: PropTypes.object.isRequired,
pageContext: PropTypes.object.isRequired
}
render() {
const { data } = this.props
const { data, pageContext } = this.props
const projects = data.allProjectsYaml.edges
const images = data.projectImageFiles.edges
@ -56,6 +57,8 @@ export default class Home extends PureComponent {
)
})}
</div>
<Repositories repos={pageContext.repos} />
</>
)
}

@ -5,22 +5,23 @@ import { getLocationTimes } from '../utils/getLocationTimes'
import { getCountry } from '../utils/getCountry'
export default class AppProvider extends PureComponent {
static propTypes = {
children: PropTypes.any.isRequired
}
state = {
dark: false,
toggleDark: () => this.toggleDark(),
geolocation: null
}
static propTypes = {
children: PropTypes.any.isRequired
}
store = typeof localStorage === 'undefined' ? null : localStorage
mounted = false
async componentDidMount() {
this.mounted = true
const geolocation = await getCountry()
this.setState({ geolocation })
this.checkDark()
@ -30,16 +31,12 @@ export default class AppProvider extends PureComponent {
this.mounted = false
}
setDark() {
this.mounted && this.setState({ dark: true })
}
setLight() {
this.mounted && this.setState({ dark: false })
setDark(dark) {
this.mounted && this.setState({ dark })
}
darkLocalStorageMode(darkLocalStorage) {
darkLocalStorage === 'true' ? this.setDark() : this.setLight()
darkLocalStorage === 'true' ? this.setDark(true) : this.setDark(false)
}
//
@ -51,7 +48,7 @@ export default class AppProvider extends PureComponent {
const now = new Date().getHours()
const weWantItDarkTimes = now >= sunset || now <= sunrise
!dark && weWantItDarkTimes ? this.setDark() : this.setLight()
!dark && weWantItDarkTimes ? this.setDark(true) : this.setDark(false)
}
async checkDark() {

@ -67,6 +67,7 @@ $color-headings--dark: $brand-main-light;
/////////////////////////////////////
$spacer: ($font-size-base * $line-height);
$border-radius: .25rem;
// Responsive breakpoints
/////////////////////////////////////