1
0
mirror of https://github.com/kremalicious/portfolio.git synced 2024-12-22 17:23:22 +01:00

Merge pull request #5 from kremalicious/feature/css-modules

move to CSS modules
This commit is contained in:
Matthias Kretschmann 2018-06-11 20:11:01 +02:00 committed by GitHub
commit 6a3b501e18
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 155 additions and 113 deletions

View File

@ -1,9 +1,9 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import './Content.scss' import styles from './Content.module.scss'
const Content = props => ( const Content = props => (
<div className="content" {...props}> <div className={styles.content} {...props}>
{props.children} {props.children}
</div> </div>
) )

View File

@ -1,8 +1,10 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import './FullWidth.scss' import styles from './FullWidth.module.scss'
const FullWidth = ({ children }) => <div className="full-width">{children}</div> const FullWidth = ({ children }) => (
<div className={styles.fullWidth}>{children}</div>
)
FullWidth.propTypes = { FullWidth.propTypes = {
children: PropTypes.node children: PropTypes.node

View File

@ -1,4 +1,4 @@
.full-width { .fullWidth {
width: 100vw; width: 100vw;
position: relative; position: relative;
left: 50%; left: 50%;

View File

@ -1,16 +1,18 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import { ReactComponent as Logo } from '../../images/logo.svg' import { ReactComponent as Logo } from '../../images/logo.svg'
import './LogoUnit.scss' import styles from './LogoUnit.module.scss'
const LogoUnit = ({ meta, minimal }) => { const LogoUnit = ({ meta, minimal }) => {
const classes = minimal ? 'logounit logounit--minimal' : 'logounit' const classes = minimal
? `${styles.logounit} ${styles.minimal}`
: styles.logounit
return ( return (
<div className={classes}> <div className={classes}>
<Logo className="logounit__logo" /> <Logo className={styles.logounit__logo} />
<h1 className="logounit__title">{meta.title.toLowerCase()}</h1> <h1 className={styles.logounit__title}>{meta.title.toLowerCase()}</h1>
<p className="logounit__description"> <p className={styles.logounit__description}>
<span>{'{ '}</span> {meta.tagline.toLowerCase()} <span>{' }'}</span> <span>{'{ '}</span> {meta.tagline.toLowerCase()} <span>{' }'}</span>
</p> </p>
</div> </div>

View File

@ -1,5 +1,9 @@
@import 'variables'; @import 'variables';
.logounit {
display: block;
}
.logounit__logo { .logounit__logo {
display: block; display: block;
width: 1.5rem; width: 1.5rem;
@ -36,7 +40,7 @@
} }
} }
.logounit--minimal { .minimal {
transform: scale(.7); transform: scale(.7);
transform-origin: top center; transform-origin: top center;
transform-box: border-box; transform-box: border-box;

View File

@ -1,7 +1,7 @@
import React, { Fragment, PureComponent } from 'react' import React, { Fragment, PureComponent } from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import { MoveIn } from '../atoms/Animations' import { MoveIn } from '../atoms/Animations'
import './Availability.scss' import styles from './Availability.module.scss'
class Availability extends PureComponent { class Availability extends PureComponent {
constructor(props) { constructor(props) {
@ -64,7 +64,9 @@ class Availability extends PureComponent {
<MoveIn> <MoveIn>
<aside <aside
className={ className={
status ? 'availability available' : 'availability unavailable' status
? `${styles.availability} ${styles.available}`
: `${styles.availability} ${styles.unavailable}`
} }
> >
<p <p

View File

@ -9,8 +9,8 @@ import { ReactComponent as Twitter } from '../../images/twitter.svg'
import { ReactComponent as GitHub } from '../../images/github.svg' import { ReactComponent as GitHub } from '../../images/github.svg'
import { ReactComponent as Dribbble } from '../../images/dribbble.svg' import { ReactComponent as Dribbble } from '../../images/dribbble.svg'
import '../atoms/Icons.scss' import icons from '../atoms/Icons.module.scss'
import './Networks.scss' import styles from './Networks.module.scss'
const NetworkIcon = props => { const NetworkIcon = props => {
switch (props.title) { switch (props.title) {
@ -34,7 +34,7 @@ class Network extends PureComponent {
super(props) super(props)
this.state = { this.state = {
classes: 'networks' classes: styles.networks
} }
} }
@ -48,9 +48,9 @@ class Network extends PureComponent {
toggleClasses = () => { toggleClasses = () => {
if (this.props.minimal) { if (this.props.minimal) {
this.setState({ classes: 'networks networks--minimal' }) this.setState({ classes: `${styles.networks} ${styles.minimal}` })
} else { } else {
this.setState({ classes: 'networks' }) this.setState({ classes: styles.networks })
} }
} }
@ -61,12 +61,12 @@ class Network extends PureComponent {
<aside className={this.state.classes}> <aside className={this.state.classes}>
{Object.keys(this.props.meta.social).map((key, i) => ( {Object.keys(this.props.meta.social).map((key, i) => (
<OutboundLink <OutboundLink
className="networks__link" className={styles.link}
href={this.props.meta.social[key]} href={this.props.meta.social[key]}
key={i} key={i}
> >
<NetworkIcon title={key} className="icon" /> <NetworkIcon title={key} className={icons.icon} />
<span className="networks__title">{key}</span> <span className={styles.title}>{key}</span>
</OutboundLink> </OutboundLink>
))} ))}
</aside> </aside>

View File

@ -10,7 +10,7 @@
max-width: 20rem; max-width: 20rem;
} }
.networks__title { .title {
display: block; display: block;
font-size: $font-size-mini; font-size: $font-size-mini;
color: $brand-grey-light; color: $brand-grey-light;
@ -19,7 +19,7 @@
transition: .2s $easing; transition: .2s $easing;
} }
.networks__link { .link {
margin-left: $spacer / 2; margin-left: $spacer / 2;
margin-right: $spacer / 2; margin-right: $spacer / 2;
text-align: center; text-align: center;
@ -27,35 +27,38 @@
flex: 1 1 (100% / 5); flex: 1 1 (100% / 5);
&, &,
.icon { svg {
transition: .2s $easing; transition: .2s $easing;
} }
.icon { svg {
fill: $brand-grey-light; fill: $brand-grey-light;
} }
&:hover, &:hover,
&:focus { &:focus {
.icon { svg {
fill: $brand-cyan; fill: $brand-cyan;
} }
.networks__title { .title {
opacity: 1; opacity: 1;
transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0);
} }
} }
}
.networks--minimal & { .minimal {
.link {
padding: $spacer / 4; padding: $spacer / 4;
margin-left: $spacer / 4; margin-left: $spacer / 4;
margin-right: $spacer / 4; margin-right: $spacer / 4;
}
.icon { /* stylelint-disable no-descending-specificity */
width: .85rem; svg {
height: .85rem; width: .85rem;
opacity: .8; height: .85rem;
} opacity: .8;
} }
} }

View File

@ -9,8 +9,8 @@ import { ReactComponent as Styleguide } from '../../images/styleguide.svg'
import { ReactComponent as GitHub } from '../../images/github.svg' import { ReactComponent as GitHub } from '../../images/github.svg'
import { ReactComponent as Dribbble } from '../../images/dribbble.svg' import { ReactComponent as Dribbble } from '../../images/dribbble.svg'
import '../atoms/Icons.scss' import icons from '../atoms/Icons.module.scss'
import './ProjectLinks.scss' import styles from './ProjectLinks.module.scss'
const LinkIcon = props => { const LinkIcon = props => {
switch (props.title) { switch (props.title) {
@ -32,8 +32,8 @@ const LinkIcon = props => {
} }
const ProjectLinks = ({ links }) => ( const ProjectLinks = ({ links }) => (
<div className="project__links"> <div className={styles.projectLinks}>
<h3 className="project__meta__title"> <h3 className={styles.title}>
Links <span>Learn more on the interwebz.</span> Links <span>Learn more on the interwebz.</span>
</h3> </h3>
@ -44,7 +44,7 @@ const ProjectLinks = ({ links }) => (
return ( return (
<li key={title}> <li key={title}>
<OutboundLink href={url}> <OutboundLink href={url}>
<LinkIcon title={title} className="icon" /> <LinkIcon title={title} className={icons.icon} />
{title} {title}
</OutboundLink> </OutboundLink>
</li> </li>

View File

@ -1,6 +1,6 @@
@import 'variables'; @import 'variables';
.project__links { .projectLinks {
ul { ul {
padding: 0; padding: 0;
display: flex; display: flex;
@ -17,7 +17,7 @@
margin-bottom: $spacer / 2; margin-bottom: $spacer / 2;
} }
.icon { svg {
margin-right: $spacer / 3; margin-right: $spacer / 3;
transition: .2s ease-out; transition: .2s ease-out;
margin-bottom: -.1rem; margin-bottom: -.1rem;
@ -33,7 +33,7 @@
transition-property: all; transition-property: all;
background: rgba(#fff, .15); background: rgba(#fff, .15);
.icon { svg {
fill: $brand-grey-light; fill: $brand-grey-light;
} }
@ -50,3 +50,16 @@
} }
} }
} }
.title {
font-size: $font-size-h3;
margin-bottom: $spacer * 1.5;
span {
display: block;
margin-top: $spacer / 3;
font-size: $font-size-base;
font-family: $font-family-base;
color: $brand-grey-light;
}
}

View File

@ -2,10 +2,11 @@ import React from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import Link from 'gatsby-link' import Link from 'gatsby-link'
import Img from 'gatsby-image' import Img from 'gatsby-image'
import FullWidth from '../atoms/FullWidth'
import { ReactComponent as Index } from '../../images/index.svg' import { ReactComponent as Index } from '../../images/index.svg'
import '../atoms/Icons.scss' import icons from '../atoms/Icons.module.scss'
import './ProjectNav.scss' import styles from './ProjectNav.module.scss'
const ProjectNavLink = ({ previous, next }) => { const ProjectNavLink = ({ previous, next }) => {
const slug = previous ? previous.slug : next.slug const slug = previous ? previous.slug : next.slug
@ -13,36 +14,38 @@ const ProjectNavLink = ({ previous, next }) => {
const img = previous ? previous.img : next.img const img = previous ? previous.img : next.img
return ( return (
<div className="project__nav__item"> <div className={styles.item}>
<Link className="project__nav__link prev" to={slug}> <Link className={styles.link + ' prev'} to={slug}>
<Img <Img
className="project__nav__image" className={styles.image}
sizes={img.childImageSharp.sizes} sizes={img.childImageSharp.sizes}
alt={title} alt={title}
/> />
<h1 className="project__nav__title">{title}</h1> <h1 className={styles.title}>{title}</h1>
</Link> </Link>
</div> </div>
) )
} }
const ProjectNav = ({ previous, next }) => ( const ProjectNav = ({ previous, next }) => (
<nav className="project__nav full-width"> <FullWidth>
{previous && <ProjectNavLink previous={previous} />} <nav className={styles.projectNav}>
<Link className="project__nav__index" title="Back to projects" to={'/'}> {previous && <ProjectNavLink previous={previous} />}
<Index className="icon" /> <Link className={styles.index} title="Back to projects" to={'/'}>
</Link> <Index className={icons.icon} />
{next ? ( </Link>
<ProjectNavLink next={next} /> {next ? (
) : ( <ProjectNavLink next={next} />
<div className="project__nav__item project__nav__item--end"> ) : (
<div className="project__nav__end"> <div className={`${styles.item} ${styles.itemEnd}`}>
<h3>This is the end</h3> <div className={styles.end}>
<p>I would rather not show you my websites from 1999.</p> <h3>This is the end</h3>
<p>I would rather not show you my websites from 1999.</p>
</div>
</div> </div>
</div> )}
)} </nav>
</nav> </FullWidth>
) )
ProjectNavLink.propTypes = { ProjectNavLink.propTypes = {

View File

@ -2,14 +2,14 @@
$breakpoint-project-nav: 45rem; $breakpoint-project-nav: 45rem;
.project__nav { .projectNav {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
justify-content: space-between; justify-content: space-between;
overflow: hidden; overflow: hidden;
} }
.project__nav__image { .image {
margin: 0; margin: 0;
box-shadow: 0 3px 5px rgba($brand-main, .15), box-shadow: 0 3px 5px rgba($brand-main, .15),
0 5px 16px rgba($brand-main, .15); 0 5px 16px rgba($brand-main, .15);
@ -20,7 +20,7 @@ $breakpoint-project-nav: 45rem;
} }
} }
.project__nav__item { .item {
flex: 1 1 46%; flex: 1 1 46%;
position: relative; position: relative;
transition: .2s ease-out; transition: .2s ease-out;
@ -56,16 +56,22 @@ $breakpoint-project-nav: 45rem;
} }
} }
.project__nav__title { .itemEnd {
pointer-events: none;
display: flex;
align-items: center;
}
.title {
visibility: hidden; visibility: hidden;
font-size: 0; font-size: 0;
} }
.project__nav__link { .link {
display: block; display: block;
} }
.project__nav__index { .index {
height: 100%; height: 100%;
display: block; display: block;
align-self: center; align-self: center;
@ -84,7 +90,7 @@ $breakpoint-project-nav: 45rem;
width: auto; width: auto;
} }
.icon { svg {
fill: $brand-grey-light; fill: $brand-grey-light;
width: 1.5rem; width: 1.5rem;
height: 1.5rem; height: 1.5rem;
@ -92,7 +98,7 @@ $breakpoint-project-nav: 45rem;
&:hover, &:hover,
&:focus { &:focus {
.icon { svg {
fill: $brand-cyan; fill: $brand-cyan;
} }
} }
@ -106,13 +112,7 @@ $breakpoint-project-nav: 45rem;
} }
} }
.project__nav__item--end { .end {
pointer-events: none;
display: flex;
align-items: center;
}
.project__nav__end {
padding-right: $spacer; padding-right: $spacer;
text-align: left; text-align: left;

View File

@ -1,10 +1,10 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import './ProjectTechstack.scss' import styles from './ProjectTechstack.module.scss'
const ProjectTechstack = ({ techstack }) => ( const ProjectTechstack = ({ techstack }) => (
<div className="project__techstack"> <div className={styles.projectTechstack}>
<h3 className="project__meta__title"> <h3 className={styles.title}>
Tools & Technologies <span>The tech stack I was involved with.</span> Tools & Technologies <span>The tech stack I was involved with.</span>
</h3> </h3>
<ul>{techstack.map(tech => <li key={tech}>{tech}</li>)}</ul> <ul>{techstack.map(tech => <li key={tech}>{tech}</li>)}</ul>

View File

@ -1,6 +1,6 @@
@import 'variables'; @import 'variables';
.project__techstack { .projectTechstack {
ul { ul {
padding: 0; padding: 0;
display: flex; display: flex;
@ -23,3 +23,16 @@
font-size: $font-size-base; font-size: $font-size-base;
} }
} }
.title {
font-size: $font-size-h3;
margin-bottom: $spacer * 1.5;
span {
display: block;
margin-top: $spacer / 3;
font-size: $font-size-base;
font-family: $font-family-base;
color: $brand-grey-light;
}
}

View File

@ -4,18 +4,18 @@ import Helmet from 'react-helmet'
import { FadeIn } from '../atoms/Animations' import { FadeIn } from '../atoms/Animations'
import { ReactComponent as Day } from '../../images/day.svg' import { ReactComponent as Day } from '../../images/day.svg'
import { ReactComponent as Night } from '../../images/night.svg' import { ReactComponent as Night } from '../../images/night.svg'
import './ThemeSwitch.scss' import styles from './ThemeSwitch.module.scss'
const ThemeToggle = props => { const ThemeToggle = props => {
return ( return (
<span <span
id="toggle" id="toggle"
className="checkbox__faux-container" className={styles.checkboxContainer}
aria-live="assertive" aria-live="assertive"
> >
<Day className={props.dark ? 'icon' : 'icon active'} /> <Day className={props.dark ? null : 'active'} />
<span className="checkbox__faux" /> <span className={styles.checkboxFake} />
<Night className={props.dark ? 'icon active' : 'icon'} /> <Night className={props.dark ? 'active' : null} />
</span> </span>
) )
} }
@ -48,9 +48,9 @@ class ThemeSwitch extends PureComponent {
<body className={this.state.dark ? 'dark' : null} /> <body className={this.state.dark ? 'dark' : null} />
</Helmet> </Helmet>
<FadeIn> <FadeIn>
<aside className="themeswitch"> <aside className={styles.themeSwitch}>
<label className="checkbox"> <label className={styles.checkbox}>
<span className="checkbox__label">Toggle Night Mode</span> <span className={styles.label}>Toggle Night Mode</span>
<input <input
onChange={this.handleChange} onChange={this.handleChange}
type="checkbox" type="checkbox"

View File

@ -1,12 +1,12 @@
@import 'variables'; @import 'variables';
.themeswitch { .themeSwitch {
position: absolute; position: absolute;
top: $spacer / 2; top: $spacer / 2;
right: $spacer; right: $spacer;
z-index: 10; z-index: 10;
.icon { svg {
width: .8rem; width: .8rem;
height: .8rem; height: .8rem;
margin-top: -.05rem; margin-top: -.05rem;
@ -24,7 +24,7 @@
} }
} }
.checkbox__faux-container { .checkboxContainer {
display: flex; display: flex;
align-items: center; align-items: center;
} }
@ -32,7 +32,7 @@
$knob-size: 8px; $knob-size: 8px;
$knob-space: 1px; $knob-space: 1px;
.checkbox__faux { .checkboxFake {
display: block; display: block;
position: relative; position: relative;
width: ($knob-size + ($knob-space * 2)) * 2; width: ($knob-size + ($knob-space * 2)) * 2;
@ -74,7 +74,7 @@ $knob-space: 1px;
} }
[type='checkbox'], [type='checkbox'],
.checkbox__label { .label {
width: 1px; width: 1px;
height: 1px; height: 1px;
border: 0; border: 0;
@ -87,8 +87,8 @@ $knob-space: 1px;
[type='checkbox'] { [type='checkbox'] {
&:checked { &:checked {
+ .checkbox__faux-container { + .checkboxContainer {
.checkbox__faux { .checkboxFake {
&::after { &::after {
transform: translate3d(100%, 0, 0); transform: translate3d(100%, 0, 0);
} }

View File

@ -3,7 +3,7 @@ import PropTypes from 'prop-types'
import Vcard from '../atoms/Vcard' import Vcard from '../atoms/Vcard'
import LogoUnit from '../atoms/LogoUnit' import LogoUnit from '../atoms/LogoUnit'
import Networks from '../molecules/Networks' import Networks from '../molecules/Networks'
import './Footer.scss' import styles from './Footer.module.scss'
class Footer extends PureComponent { class Footer extends PureComponent {
constructor(props) { constructor(props) {
@ -17,16 +17,16 @@ class Footer extends PureComponent {
const pkg = this.props.pkg const pkg = this.props.pkg
return ( return (
<footer className="footer"> <footer className={styles.footer}>
<LogoUnit meta={meta} minimal /> <LogoUnit meta={meta} minimal />
<Networks meta={meta} minimal /> <Networks meta={meta} minimal />
<p className="footer__actions"> <p className={styles.footer__actions}>
<Vcard meta={meta} /> <Vcard meta={meta} />
<a href={meta.gpg}>PGP/GPG key</a> <a href={meta.gpg}>PGP/GPG key</a>
<a href={pkg.bugs}>Found a bug?</a> <a href={pkg.bugs}>Found a bug?</a>
</p> </p>
<p className="footer__copyright"> <p className={styles.footer__copyright}>
<small> <small>
&copy; {this.state.year} {meta.title} &mdash; All Rights Reserved &copy; {this.state.year} {meta.title} &mdash; All Rights Reserved
</small> </small>

View File

@ -11,7 +11,7 @@
font-size: $font-size-mini; font-size: $font-size-mini;
} }
.networks { > aside {
margin-top: 0; margin-top: 0;
margin-bottom: $spacer * 2; margin-bottom: $spacer * 2;
} }

View File

@ -6,7 +6,7 @@ import Networks from '../molecules/Networks'
import Availability from '../molecules/Availability' import Availability from '../molecules/Availability'
import ThemeSwitch from '../molecules/ThemeSwitch' import ThemeSwitch from '../molecules/ThemeSwitch'
import LogoUnit from '../atoms/LogoUnit' import LogoUnit from '../atoms/LogoUnit'
import './Header.scss' import styles from './Header.module.scss'
class Header extends PureComponent { class Header extends PureComponent {
constructor(props) { constructor(props) {
@ -25,9 +25,9 @@ class Header extends PureComponent {
toggleClasses = () => { toggleClasses = () => {
if (this.props.isHomepage) { if (this.props.isHomepage) {
this.setState({ classes: 'header' }) this.setState({ classes: styles.header })
} else { } else {
this.setState({ classes: 'header header--minimal' }) this.setState({ classes: `${styles.header} ${styles.minimal}` })
} }
} }
@ -39,7 +39,7 @@ class Header extends PureComponent {
<header className={this.state.classes}> <header className={this.state.classes}>
<ThemeSwitch /> <ThemeSwitch />
<FadeIn> <FadeIn>
<Link className="header__logounit-link" to={'/'}> <Link className={styles.header__link} to={'/'}>
<LogoUnit meta={meta} minimal={!isHomepage} /> <LogoUnit meta={meta} minimal={!isHomepage} />
</Link> </Link>
</FadeIn> </FadeIn>

View File

@ -12,20 +12,20 @@
text-align: center; text-align: center;
} }
.header__logounit-link { .header__link {
pointer-events: none; pointer-events: none;
display: block; display: block;
width: 100%; width: 100%;
} }
.header--minimal { .minimal {
height: auto; height: auto;
@media (min-width: 30rem) { @media (min-width: 30rem) {
padding-top: $spacer * 2; padding-top: $spacer * 2;
} }
.header__logounit-link { .header__link {
pointer-events: all; pointer-events: all;
width: auto; width: auto;
} }

View File

@ -3,7 +3,7 @@ import PropTypes from 'prop-types'
import Link from 'gatsby-link' import Link from 'gatsby-link'
import ProjectImage from '../components/atoms/ProjectImage' import ProjectImage from '../components/atoms/ProjectImage'
import FullWidth from '../components/atoms/FullWidth' import FullWidth from '../components/atoms/FullWidth'
import './index.scss' import styles from './index.module.scss'
const Home = ({ data }) => { const Home = ({ data }) => {
const projects = data.allProjectsYaml.edges const projects = data.allProjectsYaml.edges
@ -14,9 +14,9 @@ const Home = ({ data }) => {
const { slug, title, img } = node const { slug, title, img } = node
return ( return (
<article className="projects__project" key={slug}> <article className={styles.project} key={slug}>
<Link to={slug}> <Link to={slug}>
<h1 className="projects__project__title">{title}</h1> <h1 className={styles.title}>{title}</h1>
<ProjectImage sizes={img.childImageSharp.sizes} alt={title} /> <ProjectImage sizes={img.childImageSharp.sizes} alt={title} />
</Link> </Link>
</article> </article>

View File

@ -1,6 +1,6 @@
@import 'variables'; @import 'variables';
.projects__project { .project {
text-align: center; text-align: center;
margin-bottom: $spacer * 4; margin-bottom: $spacer * 4;
@ -42,7 +42,7 @@
} }
} }
.projects__project__title { .title {
visibility: hidden; visibility: hidden;
font-size: 0; font-size: 0;
margin: 0; margin: 0;