From d37bafb37966ffa87270221cb8817d7fb361dd49 Mon Sep 17 00:00:00 2001 From: Matthias Kretschmann Date: Thu, 10 May 2018 16:06:17 +0200 Subject: [PATCH] theme switcher --- .eslintrc | 1 + src/components/molecules/Availability.scss | 13 ++- src/components/molecules/Social.scss | 2 - src/components/molecules/ThemeSwitch.jsx | 60 ++++++++++++++ src/components/molecules/ThemeSwitch.scss | 95 ++++++++++++++++++++++ src/components/organisms/Footer.scss | 12 ++- src/components/organisms/Header.jsx | 2 + src/components/organisms/Header.scss | 35 ++++++-- src/images/day.svg | 3 + src/images/night.svg | 3 + src/layouts/index.scss | 38 +++++---- src/styles/_variables.scss | 13 +++ src/templates/Project.scss | 1 - 13 files changed, 248 insertions(+), 30 deletions(-) create mode 100644 src/components/molecules/ThemeSwitch.jsx create mode 100644 src/components/molecules/ThemeSwitch.scss create mode 100644 src/images/day.svg create mode 100644 src/images/night.svg 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; }