theme switcher

This commit is contained in:
Matthias Kretschmann 2018-05-10 16:06:17 +02:00
parent f9960a1d40
commit d37bafb379
Signed by: m
GPG Key ID: 606EEEF3C479A91F
13 changed files with 248 additions and 30 deletions

View File

@ -31,6 +31,7 @@
}
]
},
"parser": "babel-eslint",
"parserOptions": {
"sourceType": "module",
"ecmaFeatures": {

View File

@ -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 {

View File

@ -39,8 +39,6 @@
&:hover,
&:focus {
background: $brand-light;
.icon {
fill: $brand-cyan;
}

View File

@ -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 (
<aside className="themeswitch">
<label className="checkbox">
<span className="checkbox__label">Toggle Night Mode</span>
<input
onClick={this.toggleState}
type="checkbox"
name="toggle"
value="toggle"
aria-describedby="toggle"
/>
<span
id="toggle"
className="checkbox__faux-container"
aria-live="assertive"
>
<Day className={this.state.dark ? 'icon' : 'icon active'} />
<span className="checkbox__faux" />
<Night className={this.state.dark ? 'icon active' : 'icon'} />
</span>
</label>
</aside>
)
}
}
export default ThemeSwitch

View File

@ -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);
}
}
}
}
}
}

View File

@ -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;

View File

@ -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 (
<header className={classes}>
<ThemeSwitch />
<FadeIn>
<Link className="header__name" to={'/'}>
<Logo className="header__logo" />

View File

@ -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;
}
}
}
}

3
src/images/day.svg Normal file
View File

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="21" height="21" viewBox="0 0 21 21">
<path d="M1001,1344.5 C1001,1347.53669 998.535313,1350 995.5,1350 C992.459875,1350 990,1347.53669 990,1344.5 C990,1341.46331 992.459875,1339 995.5,1339 C998.535313,1339 1001,1341.46331 1001,1344.5 Z M995.5,1336.484 C994.633125,1336.484 993.81625,1336.69175 993.035,1337 L993,1337 L995.5,1334 L998,1337 L997.96125,1337 C997.181875,1336.691 996.365,1336.484 995.5,1336.484 Z M995.5,1352.516 C996.365,1352.516 997.181875,1352.30825 997.96125,1352 L998,1352 L995.5,1355 L993,1352 L993.035,1352 C993.81625,1352.309 994.633125,1352.516 995.5,1352.516 Z M1003.516,1344.5 C1003.516,1343.63562 1003.3045,1342.81562 1003,1342.03625 L1003,1342 L1006,1344.5 L1003,1347 L1003,1346.96375 C1003.30525,1346.18438 1003.516,1345.36438 1003.516,1344.5 Z M987.484,1344.5 C987.484,1345.36438 987.69025,1346.18438 988,1346.96375 L988,1347 L985,1344.5 L988,1342 L988,1342.03625 C987.6895,1342.81562 987.484,1343.63562 987.484,1344.5 Z M1001.34229,1350.34229 C1002.03819,1349.65134 1002.55304,1348.85785 1002.96959,1348.0297 L1003,1348 L1003,1352 L999,1352 L999.028289,1351.97242 C999.856436,1351.55233 1000.65205,1351.03819 1001.34229,1350.34229 Z M989.657001,1338.65771 C988.961103,1339.34866 988.447666,1340.14215 988.028289,1340.9703 L988,1341 L988,1337 L992,1337 L991.966761,1337.02758 C991.137907,1337.44767 990.348656,1337.96181 989.657001,1338.65771 Z M989.657709,1350.343 C990.349364,1351.0389 991.138614,1351.55304 991.966761,1351.97242 L992,1352 L988,1352 L988,1348 L988.028289,1348.0297 C988.448373,1348.85856 988.96181,1349.65205 989.657709,1350.343 Z M1001.34229,1338.657 C1000.65205,1337.9611 999.856436,1337.44696 999.028289,1337.02758 L999,1337 L1003,1337 L1003,1341 L1002.96959,1340.9703 C1002.55304,1340.14144 1002.03819,1339.34795 1001.34229,1338.657 Z" transform="translate(-985 -1334)"/>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

3
src/images/night.svg Normal file
View File

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="17" viewBox="0 0 18 17">
<path d="M1057.35991,1345.6935 C1052.91908,1345.6935 1049.32216,1342.19489 1049.32216,1337.88132 C1049.32216,1336.46068 1049.74141,1335.14652 1050.42369,1334 C1046.72047,1335.03741 1044,1338.31568 1044,1342.24655 C1044,1347.00713 1047.97006,1350.86789 1052.86864,1350.86789 C1056.91247,1350.86789 1060.28811,1348.22007 1061.35547,1344.62446 C1060.17313,1345.28549 1058.82157,1345.6935 1057.35991,1345.6935 Z" transform="translate(-1044 -1334)"/>
</svg>

After

Width:  |  Height:  |  Size: 539 B

View File

@ -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
/////////////////////////////////////

View File

@ -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
/////////////////////////////////////

View File

@ -20,7 +20,6 @@
.project__description {
font-size: $font-size-base;
color: $brand-grey;
margin-bottom: $spacer * 3;
}