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

Merge pull request #6 from kremalicious/feature/projectslider

Add projects slider
This commit is contained in:
Matthias Kretschmann 2018-06-12 00:31:06 +02:00 committed by GitHub
commit 2f13a07652
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 131 additions and 178 deletions

View File

@ -1,6 +1,7 @@
{ {
"extends": [ "extends": [
"stylelint-config-standard", "stylelint-config-standard",
"stylelint-config-css-modules",
"./node_modules/prettier-stylelint/config.js" "./node_modules/prettier-stylelint/config.js"
], ],
"syntax": "scss", "syntax": "scss",

View File

@ -61,6 +61,7 @@
"prettier-stylelint": "^0.4.2", "prettier-stylelint": "^0.4.2",
"slugify": "^1.3.0", "slugify": "^1.3.0",
"stylelint": "^9.2.1", "stylelint": "^9.2.1",
"stylelint-config-css-modules": "^1.2.0",
"stylelint-config-standard": "^18.2.0" "stylelint-config-standard": "^18.2.0"
}, },
"browserslist": [ "browserslist": [

View File

@ -31,7 +31,7 @@
font-size: $font-size-h4; font-size: $font-size-h4;
color: $brand-grey; color: $brand-grey;
.dark & { :global(.dark) & {
color: $brand-grey-light; color: $brand-grey-light;
} }
@ -45,14 +45,16 @@
transform-origin: top center; transform-origin: top center;
transform-box: border-box; transform-box: border-box;
// stylelint-disable no-descending-specificity
.logounit__title, .logounit__title,
.logounit__description { .logounit__description {
color: $brand-grey-light; color: $brand-grey-light;
.dark & { :global(.dark) & {
color: $brand-grey; color: $brand-grey;
} }
} }
// stylelint-enable no-descending-specificity
.logounit__logo { .logounit__logo {
margin-bottom: $spacer / 3; margin-bottom: $spacer / 3;

View File

@ -10,7 +10,7 @@
display: block; display: block;
transition: opacity .2s ease-out; transition: opacity .2s ease-out;
.dark & { :global(.dark) & {
color: $text-color-light--dark; color: $text-color-light--dark;
} }
@ -24,7 +24,7 @@
position: fixed; position: fixed;
bottom: $spacer; bottom: $spacer;
.dark & { :global(.dark) & {
background: rgba($body-background-color--dark, .8); background: rgba($body-background-color--dark, .8);
color: $brand-light; color: $brand-light;
} }

View File

@ -48,6 +48,16 @@
transition: none; transition: none;
background: rgba(#fff, .15); background: rgba(#fff, .15);
} }
:global(.dark) & {
background: darken($body-background-color--dark, 1%);
&:hover,
&:focus {
box-shadow: 0 6px 10px rgba(darken($brand-main, 20%), .1),
0 10px 25px rgba(darken($brand-main, 20%), .1);
}
}
} }
} }

View File

@ -1,61 +1,77 @@
import React from 'react' import React, { Component } 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 FullWidth from '../atoms/FullWidth'
import { ReactComponent as Index } from '../../images/index.svg'
import icons from '../atoms/Icons.module.scss'
import styles from './ProjectNav.module.scss' import styles from './ProjectNav.module.scss'
const ProjectNavLink = ({ previous, next }) => { const ProjectItem = ({ title, slug, img, current }) => (
const slug = previous ? previous.slug : next.slug <div className={styles.item} id={current ? 'current' : null}>
const title = previous ? previous.title : next.title <Link className={styles.link} to={slug}>
const img = previous ? previous.img : next.img <Img
className={styles.image}
return ( sizes={img.childImageSharp.sizes}
<div className={styles.item}> alt={title}
<Link className={styles.link + ' prev'} to={slug}> />
<Img <h1 className={styles.title}>{title}</h1>
className={styles.image} </Link>
sizes={img.childImageSharp.sizes} </div>
alt={title}
/>
<h1 className={styles.title}>{title}</h1>
</Link>
</div>
)
}
const ProjectNav = ({ previous, next }) => (
<FullWidth>
<nav className={styles.projectNav}>
{previous && <ProjectNavLink previous={previous} />}
<Link className={styles.index} title="Back to projects" to={'/'}>
<Index className={icons.icon} />
</Link>
{next ? (
<ProjectNavLink next={next} />
) : (
<div className={`${styles.item} ${styles.itemEnd}`}>
<div className={styles.end}>
<h3>This is the end</h3>
<p>I would rather not show you my websites from 1999.</p>
</div>
</div>
)}
</nav>
</FullWidth>
) )
ProjectNavLink.propTypes = { class ProjectNav extends Component {
previous: PropTypes.object, constructor(props) {
next: PropTypes.object super(props)
}
componentDidUpdate() {
this.scrollToCurrent()
}
scrollToCurrent = () => {
const container = window.document.getElementById('scrollContainer')
const current = window.document.getElementById('current')
const currentLeft = current.getBoundingClientRect().left
const currentWidth = current.clientWidth
const finalPosition = currentLeft - window.innerWidth / 2 + currentWidth / 2
container.scrollLeft = finalPosition
}
render() {
const { projects, project } = this.props
return (
<FullWidth>
<nav className={styles.projectNav} id="scrollContainer">
{projects.map(({ node }) => {
const current = node.slug === project.slug
return (
<ProjectItem
key={node.slug}
title={node.title}
current={current}
slug={node.slug}
img={node.img}
/>
)
})}
</nav>
</FullWidth>
)
}
}
ProjectItem.propTypes = {
current: PropTypes.bool,
title: PropTypes.string,
slug: PropTypes.string,
img: PropTypes.object
} }
ProjectNav.propTypes = { ProjectNav.propTypes = {
previous: PropTypes.object, projects: PropTypes.array,
next: PropTypes.object project: PropTypes.object
} }
export default ProjectNav export default ProjectNav

View File

@ -1,12 +1,24 @@
@import 'variables'; @import 'variables';
$breakpoint-project-nav: 45rem;
.projectNav { .projectNav {
display: flex; white-space: nowrap;
flex-wrap: wrap; overflow-y: hidden;
justify-content: space-between; overflow-x: scroll;
overflow: hidden; -webkit-overflow-scrolling: touch;
&::-webkit-scrollbar {
display: none;
}
}
.item {
display: inline-block;
width: 40vw;
margin-left: $spacer * 2;
&:last-child {
margin-right: $spacer * 2;
}
} }
.image { .image {
@ -14,54 +26,12 @@ $breakpoint-project-nav: 45rem;
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);
.dark & { :global(.dark) & {
box-shadow: 0 3px 5px rgba(darken($brand-main, 20%), .15), box-shadow: 0 3px 5px rgba(darken($brand-main, 20%), .15),
0 5px 16px rgba(darken($brand-main, 20%), .15); 0 5px 16px rgba(darken($brand-main, 20%), .15);
} }
} }
.item {
flex: 1 1 46%;
position: relative;
transition: .2s ease-out;
max-width: 500px;
&:first-child {
margin-right: $spacer / 2;
&:hover,
&:focus {
transform: translate3d(-.5rem, 0, 0);
}
}
/* stylelint-disable no-descending-specificity */
&:last-child {
margin-left: $spacer / 2;
&:hover,
&:focus {
transform: translate3d(.5rem, 0, 0);
}
}
/* stylelint-enable no-descending-specificity */
@media (min-width: $breakpoint-project-nav) {
flex-basis: 33%;
&:first-child,
&:last-child {
margin: 0;
}
}
}
.itemEnd {
pointer-events: none;
display: flex;
align-items: center;
}
.title { .title {
visibility: hidden; visibility: hidden;
font-size: 0; font-size: 0;
@ -70,69 +40,3 @@ $breakpoint-project-nav: 45rem;
.link { .link {
display: block; display: block;
} }
.index {
height: 100%;
display: block;
align-self: center;
margin-top: $spacer * 2;
margin-left: $spacer;
margin-right: $spacer;
transition: .2s ease-out;
order: 3;
width: 100%;
@media (min-width: $breakpoint-project-nav) {
margin-top: 0;
margin-left: $spacer * 4;
margin-right: $spacer * 4;
order: initial;
width: auto;
}
svg {
fill: $brand-grey-light;
width: 1.5rem;
height: 1.5rem;
}
&:hover,
&:focus {
svg {
fill: $brand-cyan;
}
}
&:first-child {
margin-left: 48.5%;
}
&:last-child {
margin-right: auto;
}
}
.end {
padding-right: $spacer;
text-align: left;
h3 {
font-size: $font-size-h4;
margin-bottom: $spacer / 4;
color: $brand-grey-light;
@media (min-width: $breakpoint-project-nav) {
font-size: $font-size-h3;
}
}
p {
margin: 0;
color: $brand-grey-light;
font-size: $font-size-small;
@media (min-width: $breakpoint-project-nav) {
font-size: $font-size-base;
}
}
}

View File

@ -21,6 +21,11 @@
margin-bottom: $spacer / 2; margin-bottom: $spacer / 2;
flex: 0 0 calc(50% - #{$spacer / 2}); flex: 0 0 calc(50% - #{$spacer / 2});
font-size: $font-size-base; font-size: $font-size-base;
:global(.dark) & {
background: darken($body-background-color--dark, 1%);
color: $brand-grey;
}
} }
} }

View File

@ -18,7 +18,7 @@
height: .7rem; height: .7rem;
} }
.dark & { :global(.dark) & {
fill: $brand-grey; fill: $brand-grey;
} }
} }
@ -55,7 +55,7 @@ $knob-space: 1px;
transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0);
} }
.dark & { :global(.dark) & {
border-color: $brand-grey; border-color: $brand-grey;
&::after { &::after {
@ -69,7 +69,7 @@ $knob-space: 1px;
cursor: pointer; cursor: pointer;
opacity: .6; opacity: .6;
.dark & { :global(.dark) & {
opacity: .8; opacity: .8;
} }

View File

@ -16,7 +16,7 @@
margin-bottom: $spacer * 2; margin-bottom: $spacer * 2;
} }
.dark & { :global(.dark) & {
color: $text-color-light--dark; color: $text-color-light--dark;
} }
} }
@ -29,12 +29,12 @@
margin-left: $spacer; margin-left: $spacer;
color: $text-color-light; color: $text-color-light;
.dark & {
color: $text-color-light--dark;
}
&:first-child { &:first-child {
margin-left: 0; margin-left: 0;
} }
:global(.dark) & {
color: $text-color-light--dark;
}
} }
} }

View File

@ -43,11 +43,10 @@ class Project extends Component {
render() { render() {
const meta = this.props.data.dataYaml const meta = this.props.data.dataYaml
const projects = this.props.data.allProjectsYaml.edges
const project = this.props.data.projectsYaml const project = this.props.data.projectsYaml
const projectImages = this.props.data.projectImages.edges const projectImages = this.props.data.projectImages.edges
const pathContext = this.props.pathContext
const { title, links, techstack } = project const { title, links, techstack } = project
const { next, previous } = pathContext
return ( return (
<Fragment> <Fragment>
@ -67,7 +66,7 @@ class Project extends Component {
</Content> </Content>
</article> </article>
<ProjectNav previous={previous} next={next} /> <ProjectNav projects={projects} project={project} />
</Fragment> </Fragment>
) )
} }
@ -90,7 +89,7 @@ Project.propTypes = {
export default Project export default Project
export const projectQuery = graphql` export const projectAndProjectsQuery = graphql`
query ProjectBySlug($slug: String!) { query ProjectBySlug($slug: String!) {
projectsYaml(slug: { eq: $slug }) { projectsYaml(slug: { eq: $slug }) {
title title
@ -136,6 +135,7 @@ export const projectQuery = graphql`
} }
} }
} }
projectImages: allImageSharp( projectImages: allImageSharp(
filter: { id: { regex: $slug } } filter: { id: { regex: $slug } }
sort: { fields: [id], order: ASC } sort: { fields: [id], order: ASC }
@ -147,5 +147,19 @@ export const projectQuery = graphql`
} }
} }
} }
allProjectsYaml {
edges {
node {
title
slug
img {
childImageSharp {
...ProjectImageSizes
}
}
}
}
}
} }
` `