mirror of
https://github.com/kremalicious/portfolio.git
synced 2024-12-31 09:07:38 +01:00
theme switcher
This commit is contained in:
parent
f9960a1d40
commit
d37bafb379
@ -31,6 +31,7 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"parser": "babel-eslint",
|
||||
"parserOptions": {
|
||||
"sourceType": "module",
|
||||
"ecmaFeatures": {
|
||||
|
@ -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 {
|
||||
|
@ -39,8 +39,6 @@
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
background: $brand-light;
|
||||
|
||||
.icon {
|
||||
fill: $brand-cyan;
|
||||
}
|
||||
|
60
src/components/molecules/ThemeSwitch.jsx
Normal file
60
src/components/molecules/ThemeSwitch.jsx
Normal 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
|
95
src/components/molecules/ThemeSwitch.scss
Normal file
95
src/components/molecules/ThemeSwitch.scss
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
@ -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" />
|
||||
|
@ -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
3
src/images/day.svg
Normal 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
3
src/images/night.svg
Normal 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 |
@ -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
|
||||
/////////////////////////////////////
|
||||
|
||||
|
@ -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
|
||||
/////////////////////////////////////
|
||||
|
@ -20,7 +20,6 @@
|
||||
|
||||
.project__description {
|
||||
font-size: $font-size-base;
|
||||
color: $brand-grey;
|
||||
margin-bottom: $spacer * 3;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user