diff --git a/.eslintrc b/.eslintrc
index edfbe87..5d50e9a 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -31,6 +31,7 @@
}
]
},
+ "parser": "babel-eslint",
"parserOptions": {
"sourceType": "module",
"ecmaFeatures": {
diff --git a/src/components/molecules/Availability.scss b/src/components/molecules/Availability.scss
index 99034dc..d219248 100644
--- a/src/components/molecules/Availability.scss
+++ b/src/components/molecules/Availability.scss
@@ -3,20 +3,29 @@
.availability {
position: absolute;
bottom: 0;
- background: rgba($brand-light, .8);
border-radius: .25rem;
- color: $brand-grey-light;
+ color: $text-color-light;
z-index: 2;
padding: $spacer / 2;
display: block;
transition: opacity .2s ease-out;
+ .dark & {
+ color: $text-color-light--dark;
+ }
+
p { margin-bottom: 0; }
&.available {
+ background: rgba($brand-light, .8);
color: $brand-main;
position: fixed;
bottom: $spacer;
+
+ .dark & {
+ background: rgba($body-background-color--dark, .8);
+ color: $brand-light;
+ }
}
a {
diff --git a/src/components/molecules/Social.scss b/src/components/molecules/Social.scss
index 6b71134..6badc0b 100644
--- a/src/components/molecules/Social.scss
+++ b/src/components/molecules/Social.scss
@@ -39,8 +39,6 @@
&:hover,
&:focus {
- background: $brand-light;
-
.icon {
fill: $brand-cyan;
}
diff --git a/src/components/molecules/ThemeSwitch.jsx b/src/components/molecules/ThemeSwitch.jsx
new file mode 100644
index 0000000..18c2229
--- /dev/null
+++ b/src/components/molecules/ThemeSwitch.jsx
@@ -0,0 +1,60 @@
+import React, { Component } from 'react'
+import { ReactComponent as Day } from '../../images/day.svg'
+import { ReactComponent as Night } from '../../images/night.svg'
+import './ThemeSwitch.scss'
+
+class ThemeSwitch extends Component {
+ constructor(props) {
+ super(props)
+
+ this.state = {
+ dark: false
+ }
+ }
+
+ componentDidMount() {
+ this.toggleTheme()
+ }
+
+ componentDidUpdate() {
+ this.toggleTheme()
+ }
+
+ isDark = () => this.state.dark === true
+
+ toggleState = () => {
+ this.setState({ dark: !this.isDark() })
+ }
+
+ toggleTheme = () => {
+ document.body.classList.toggle('dark', this.state.dark)
+ }
+
+ render() {
+ return (
+
+ )
+ }
+}
+
+export default ThemeSwitch
diff --git a/src/components/molecules/ThemeSwitch.scss b/src/components/molecules/ThemeSwitch.scss
new file mode 100644
index 0000000..d8ac4a3
--- /dev/null
+++ b/src/components/molecules/ThemeSwitch.scss
@@ -0,0 +1,95 @@
+@import 'variables';
+
+.themeswitch {
+ position: absolute;
+ top: $spacer / 2;
+ right: $spacer;
+ z-index: 10;
+ opacity: .6;
+
+ .dark & {
+ opacity: .8;
+ }
+
+ .icon {
+ width: .8rem;
+ height: .8rem;
+ fill: $brand-grey-light;
+
+ &:last-child {
+ margin-top: -.1rem;
+ width: .7rem;
+ height: .7rem;
+ }
+
+ &.active {
+ fill: $brand-grey;
+ }
+
+ .dark & {
+ fill: $brand-grey;
+
+ &.active {
+ fill: $brand-grey-light;
+ }
+ }
+ }
+}
+
+.checkbox__faux-container {
+ display: flex;
+ align-items: center;
+}
+
+.checkbox__faux {
+ display: block;
+ position: relative;
+ width: 1.15rem;
+ height: .61rem;
+ border: .05rem solid $brand-grey-light;
+ border-radius: 15rem;
+ margin-left: $spacer / 3;
+ margin-right: $spacer / 3;
+
+ &::after {
+ content: '';
+ position: absolute;
+ top: .025rem;
+ left: .05rem;
+ width: .5rem;
+ height: .5rem;
+ background-color: $brand-grey;
+ border-radius: 15rem;
+ transition: transform .2s $easing;
+ transform: translate3d(0, 0, 0);
+ }
+}
+
+.checkbox {
+ position: relative;
+ cursor: pointer;
+
+ [type="checkbox"],
+ .checkbox__label {
+ width: 1px;
+ height: 1px;
+ border: 0;
+ clip: rect(0 0 0 0);
+ margin: -1px;
+ overflow: hidden;
+ padding: 0;
+ position: absolute;
+ }
+
+ [type="checkbox"] {
+ &:checked {
+ + .checkbox__faux-container {
+ .checkbox__faux {
+ &::after {
+ transform: translate3d(100%, 0, 0);
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/components/organisms/Footer.scss b/src/components/organisms/Footer.scss
index 631ad39..88c2347 100644
--- a/src/components/organisms/Footer.scss
+++ b/src/components/organisms/Footer.scss
@@ -3,7 +3,7 @@
.footer {
padding: $spacer * 2;
text-align: center;
- color: $brand-grey-light;
+ color: $text-color-light;
&,
small {
@@ -14,6 +14,10 @@
margin-top: 0;
margin-bottom: $spacer;
}
+
+ .dark & {
+ color: $text-color-light--dark;
+ }
}
.footer__actions {
@@ -25,7 +29,11 @@
padding: 0 $spacer / 4;
font-size: $font-size-small;
margin-left: $spacer;
- color: $brand-grey-light;
+ color: $text-color-light;
+
+ .dark & {
+ color: $text-color-light--dark;
+ }
&:first-child {
margin-left: 0;
diff --git a/src/components/organisms/Header.jsx b/src/components/organisms/Header.jsx
index 5161bf6..f8b1754 100644
--- a/src/components/organisms/Header.jsx
+++ b/src/components/organisms/Header.jsx
@@ -4,6 +4,7 @@ import PropTypes from 'prop-types'
import { FadeIn } from '../atoms/Animations'
import Social from '../molecules/Social'
import Availability from '../molecules/Availability'
+import ThemeSwitch from '../molecules/ThemeSwitch'
import { ReactComponent as Logo } from '../../images/logo.svg'
import './Header.scss'
@@ -17,6 +18,7 @@ class Header extends Component {
return (
+
diff --git a/src/components/organisms/Header.scss b/src/components/organisms/Header.scss
index 176b16d..d2af287 100644
--- a/src/components/organisms/Header.scss
+++ b/src/components/organisms/Header.scss
@@ -39,6 +39,10 @@
font-size: $font-size-large;
color: $brand-grey;
+ .dark & {
+ color: $brand-grey-light;
+ }
+
span {
opacity: .4;
}
@@ -54,13 +58,7 @@
height: auto;
@media (min-width: 30rem) {
- margin-top: $spacer;
- margin-bottom: 0;
- }
-
- .header__title,
- .header__description {
- color: $brand-grey-light;
+ padding-top: $spacer * 2;
}
.header__title {
@@ -72,6 +70,15 @@
font-size: $font-size-base;
}
+ .header__title,
+ .header__description {
+ color: $brand-grey-light;
+
+ .dark & {
+ color: $brand-grey;
+ }
+ }
+
.header__logo {
width: 1rem;
height: 1rem;
@@ -81,6 +88,8 @@
.header__name {
pointer-events: all;
+ display: inline-block;
+ width: auto;
&:hover,
&:focus {
@@ -95,11 +104,19 @@
}
.header__title {
- color: $brand-main;
+ color: $color-headings;
+
+ .dark & {
+ color: $color-headings--dark;
+ }
}
.header__description {
- color: $brand-grey;
+ color: $text-color;
+
+ .dark & {
+ color: $text-color--dark;
+ }
}
}
}
diff --git a/src/images/day.svg b/src/images/day.svg
new file mode 100644
index 0000000..b48ffbb
--- /dev/null
+++ b/src/images/day.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/images/night.svg b/src/images/night.svg
new file mode 100644
index 0000000..c2ee7c9
--- /dev/null
+++ b/src/images/night.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/layouts/index.scss b/src/layouts/index.scss
index 46d27c9..2e75c50 100644
--- a/src/layouts/index.scss
+++ b/src/layouts/index.scss
@@ -19,7 +19,7 @@ html {
}
body {
- background: $brand-light;
+ background: $body-background-color;
font-family: $font-family-base;
font-weight: $font-weight-base;
font-size: $font-size-base;
@@ -29,6 +29,12 @@ body {
font-feature-settings: 'liga', 'kern';
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
+ transition: background .2s ease-out;
+
+ &.dark {
+ background: $body-background-color--dark;
+ color: $text-color--dark;
+ }
}
p,
@@ -40,19 +46,6 @@ ol {
// Headings
/////////////////////////////////////
-h1,
-h2,
-h3,
-h4,
-h5,
-h6 {
- font-family: $font-family-headings;
- line-height: $line-height-headings;
- color: $color-headings;
- font-weight: $font-weight-headings;
- margin: 0 0 $spacer;
-}
-
h1 {
font-size: $font-size-h1;
}
@@ -77,6 +70,23 @@ h6 {
font-size: $font-size-h6;
}
+h1,
+h2,
+h3,
+h4,
+h5,
+h6 {
+ font-family: $font-family-headings;
+ line-height: $line-height-headings;
+ color: $color-headings;
+ font-weight: $font-weight-headings;
+ margin: 0 0 $spacer;
+
+ .dark & {
+ color: $color-headings--dark;
+ }
+}
+
// Links
/////////////////////////////////////
diff --git a/src/styles/_variables.scss b/src/styles/_variables.scss
index 3f374b4..f860842 100644
--- a/src/styles/_variables.scss
+++ b/src/styles/_variables.scss
@@ -1,5 +1,6 @@
$typekit: 'dtg3zui';
$projectImageMaxWidth: 1200px;
+$easing: cubic-bezier(.75, 0, .08, 1);
// Colors
/////////////////////////////////////
@@ -13,12 +14,22 @@ $brand-grey-light: lighten($brand-grey, 15%);
$brand-grey-dimmed: lighten($brand-grey, 50%);
+// Backgrounds
+/////////////////////////////////////
+
+$body-background-color: $brand-light;
+$body-background-color--dark: darken($brand-grey, 30%);
+
+
// Text Colors
/////////////////////////////////////
$text-color: $brand-grey;
$text-color-light: $brand-grey-light;
+$text-color--dark: $brand-grey-light;
+$text-color-light--dark: $brand-grey;
+
// Typography
/////////////////////////////////////
@@ -48,7 +59,9 @@ $font-family-monospace : Menlo, Monaco, Consolas, 'Courier New', monospace;
$font-family-headings : 'brandon-grotesque', 'Avenir Next', 'Helvetica Neue',Helvetica,Arial,sans-serif;
$font-weight-headings : 400;
$line-height-headings : 1.1;
+
$color-headings: $brand-main;
+$color-headings--dark: lighten($color-headings, 10%);
// Components spacing
/////////////////////////////////////
diff --git a/src/templates/Project.scss b/src/templates/Project.scss
index 87cd054..a284ae4 100644
--- a/src/templates/Project.scss
+++ b/src/templates/Project.scss
@@ -20,7 +20,6 @@
.project__description {
font-size: $font-size-base;
- color: $brand-grey;
margin-bottom: $spacer * 3;
}