mirror of
https://github.com/kremalicious/portfolio.git
synced 2024-12-23 01:29:41 +01:00
Merge pull request #41 from kremalicious/feature/grid
move layout to CSS grid
This commit is contained in:
commit
0f61672a3f
@ -1,6 +1,17 @@
|
|||||||
@import 'variables';
|
@import 'variables';
|
||||||
|
|
||||||
.screen {
|
.screen {
|
||||||
flex: 1;
|
margin-top: $spacer * $line-height;
|
||||||
padding: $spacer;
|
|
||||||
|
> article {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns:
|
||||||
|
[full-start] minmax($spacer, 1fr)
|
||||||
|
[main-start] minmax(0, 38rem) [main-end]
|
||||||
|
minmax($spacer, 1fr) [full-end];
|
||||||
|
|
||||||
|
> * {
|
||||||
|
grid-column: main;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,15 +0,0 @@
|
|||||||
import React from 'react'
|
|
||||||
import PropTypes from 'prop-types'
|
|
||||||
import styles from './Content.module.scss'
|
|
||||||
|
|
||||||
const Content = props => (
|
|
||||||
<div className={styles.content} {...props}>
|
|
||||||
{props.children}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
|
|
||||||
Content.propTypes = {
|
|
||||||
children: PropTypes.node
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Content
|
|
@ -1,4 +0,0 @@
|
|||||||
.content {
|
|
||||||
max-width: 38rem;
|
|
||||||
margin: 0 auto;
|
|
||||||
}
|
|
@ -1,9 +1,5 @@
|
|||||||
|
@import 'variables';
|
||||||
|
|
||||||
.fullWidth {
|
.fullWidth {
|
||||||
width: 100vw;
|
grid-column: full !important;
|
||||||
position: relative;
|
|
||||||
left: 50%;
|
|
||||||
right: 50%;
|
|
||||||
margin-left: -50vw;
|
|
||||||
margin-right: -50vw;
|
|
||||||
text-align: center;
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
@import 'variables';
|
@import 'variables';
|
||||||
|
|
||||||
.projectImage {
|
.projectImage {
|
||||||
max-height: 100vh;
|
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
display: block;
|
display: block;
|
||||||
@ -20,7 +19,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
img {
|
img {
|
||||||
max-height: 100vh;
|
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,18 +3,15 @@
|
|||||||
.projectLinks {
|
.projectLinks {
|
||||||
ul {
|
ul {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
display: flex;
|
display: grid;
|
||||||
flex-wrap: wrap;
|
grid-template-columns: 1fr 1fr;
|
||||||
margin-left: -($spacer / 2);
|
grid-gap: $spacer / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
li {
|
li {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
flex: 0 0 calc(50% - #{$spacer / 2});
|
|
||||||
margin-left: $spacer / 2;
|
|
||||||
margin-bottom: $spacer / 2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
// composes: fullWidth from '../atoms/FullWidth.module.scss';
|
// composes: fullWidth from '../atoms/FullWidth.module.scss';
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow-y: hidden;
|
overflow-y: hidden;
|
||||||
overflow-x: scroll;
|
overflow-x: auto;
|
||||||
-webkit-overflow-scrolling: touch;
|
-webkit-overflow-scrolling: touch;
|
||||||
|
|
||||||
&::-webkit-scrollbar,
|
&::-webkit-scrollbar,
|
||||||
@ -22,7 +22,7 @@
|
|||||||
margin-right: $spacer * 2;
|
margin-right: $spacer * 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 30rem) {
|
@media (min-width: $screen-xs) {
|
||||||
width: 40vw;
|
width: 40vw;
|
||||||
max-width: 500px;
|
max-width: 500px;
|
||||||
margin-left: $spacer * 2;
|
margin-left: $spacer * 2;
|
||||||
|
@ -3,9 +3,9 @@
|
|||||||
.projectTechstack {
|
.projectTechstack {
|
||||||
ul {
|
ul {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
display: flex;
|
display: grid;
|
||||||
flex-wrap: wrap;
|
grid-template-columns: 1fr 1fr;
|
||||||
margin-left: -($spacer / 2);
|
grid-gap: $spacer / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
li {
|
li {
|
||||||
@ -18,9 +18,6 @@
|
|||||||
border-radius: .25rem;
|
border-radius: .25rem;
|
||||||
border: .05rem solid transparent;
|
border: .05rem solid transparent;
|
||||||
color: $brand-grey-light;
|
color: $brand-grey-light;
|
||||||
margin-left: $spacer / 2;
|
|
||||||
margin-bottom: $spacer / 2;
|
|
||||||
flex: 0 0 calc(50% - #{$spacer / 2});
|
|
||||||
font-size: $font-size-small;
|
font-size: $font-size-small;
|
||||||
|
|
||||||
:global(.dark) & {
|
:global(.dark) & {
|
||||||
|
@ -24,10 +24,6 @@
|
|||||||
padding-top: $spacer * 2;
|
padding-top: $spacer * 2;
|
||||||
padding-bottom: 0;
|
padding-bottom: 0;
|
||||||
|
|
||||||
@media (min-width: 30rem) {
|
|
||||||
padding-bottom: $spacer / 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header__link {
|
.header__link {
|
||||||
pointer-events: all;
|
pointer-events: all;
|
||||||
width: auto;
|
width: auto;
|
||||||
|
@ -2,9 +2,8 @@ import React, { Component } from 'react'
|
|||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import { Link } from 'gatsby'
|
import { Link } from 'gatsby'
|
||||||
import giphyAPI from 'giphy-js-sdk-core'
|
import giphyAPI from 'giphy-js-sdk-core'
|
||||||
import Content from '../components/atoms/Content'
|
|
||||||
import Button from '../components/atoms/Button'
|
import Button from '../components/atoms/Button'
|
||||||
import './404.scss'
|
import styles from './404.module.scss'
|
||||||
|
|
||||||
// Famous last words:
|
// Famous last words:
|
||||||
// "It's just the 404 page so why not expose the dev API key"
|
// "It's just the 404 page so why not expose the dev API key"
|
||||||
@ -22,16 +21,14 @@ export default class NotFound extends Component {
|
|||||||
this.getRandomGif()
|
this.getRandomGif()
|
||||||
}
|
}
|
||||||
|
|
||||||
getRandomGif() {
|
async getRandomGif() {
|
||||||
giphyClient
|
try {
|
||||||
.random('gifs', { tag })
|
let response = await giphyClient.random('gifs', { tag })
|
||||||
.then(response => {
|
const gif = response.data.images.original.mp4
|
||||||
const gif = response.data.images.original.mp4
|
this.setState({ gif })
|
||||||
this.setState({ gif })
|
} catch (error) {
|
||||||
})
|
return error
|
||||||
.catch(err => {
|
}
|
||||||
return err
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
handleClick = e => {
|
handleClick = e => {
|
||||||
@ -41,22 +38,22 @@ export default class NotFound extends Component {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<Content className="content content--404">
|
<article className={styles.content}>
|
||||||
<h1>Shenanigans, page not found.</h1>
|
<h1>Shenanigans, page not found.</h1>
|
||||||
<p>
|
<p>
|
||||||
You might want to check the url, or{' '}
|
You might want to check the url, or{' '}
|
||||||
<Link to={'/'}>go back to the homepage</Link>. Or just check out some
|
<Link to={'/'}>go back to the homepage</Link>. Or just check out some{' '}
|
||||||
cat fail gifs, entirely your choice.
|
{tag} gifs, entirely your choice.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<video className="gif" src={this.state.gif} autoPlay loop />
|
<video className="gif" src={this.state.gif} autoPlay loop />
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<Button onClick={this.handleClick}>
|
<Button
|
||||||
Show me another cat fail gif
|
onClick={this.handleClick}
|
||||||
</Button>
|
>{`Get another '${tag}' gif`}</Button>
|
||||||
</div>
|
</div>
|
||||||
</Content>
|
</article>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,19 +1,18 @@
|
|||||||
@import 'variables';
|
@import 'variables';
|
||||||
|
|
||||||
.content--404 {
|
.content {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
max-width: 35rem;
|
max-width: 35rem;
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
|
|
||||||
.gif {
|
video {
|
||||||
display: inline-block;
|
display: block;
|
||||||
width: auto;
|
width: auto;
|
||||||
height: 300px;
|
height: 300px;
|
||||||
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);
|
||||||
margin-top: $spacer / 4;
|
margin: $spacer / 4 auto $spacer / 2 auto;
|
||||||
margin-bottom: $spacer / 2;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -2,29 +2,26 @@ import React from 'react'
|
|||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import { Link, graphql } from 'gatsby'
|
import { Link, graphql } from 'gatsby'
|
||||||
import ProjectImage from '../components/molecules/ProjectImage'
|
import ProjectImage from '../components/molecules/ProjectImage'
|
||||||
import FullWidth from '../components/atoms/FullWidth'
|
|
||||||
import styles from './index.module.scss'
|
import styles from './index.module.scss'
|
||||||
|
|
||||||
const Home = ({ data }) => {
|
const Home = ({ data }) => {
|
||||||
const projects = data.allProjectsYaml.edges
|
const projects = data.allProjectsYaml.edges
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FullWidth>
|
<div className={styles.projects}>
|
||||||
<div className={styles.projects}>
|
{projects.map(({ node }) => {
|
||||||
{projects.map(({ node }) => {
|
const { slug, title, img } = node
|
||||||
const { slug, title, img } = node
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<article className={styles.project} key={slug}>
|
<article className={styles.project} key={slug}>
|
||||||
<Link to={slug}>
|
<Link to={slug}>
|
||||||
<h1 className={styles.title}>{title}</h1>
|
<h1 className={styles.title}>{title}</h1>
|
||||||
<ProjectImage fluid={img.childImageSharp.fluid} alt={title} />
|
<ProjectImage fluid={img.childImageSharp.fluid} alt={title} />
|
||||||
</Link>
|
</Link>
|
||||||
</article>
|
</article>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
</FullWidth>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
@import 'variables';
|
@import 'variables';
|
||||||
|
|
||||||
.projects {
|
.projects {
|
||||||
@media (min-width: 55rem) {
|
display: grid;
|
||||||
display: flex;
|
grid-template-columns: 1fr;
|
||||||
justify-content: space-between;
|
grid-gap: $spacer * 3;
|
||||||
flex-wrap: wrap;
|
|
||||||
|
@media (min-width: $screen-md) {
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
max-width: calc(#{$projectImageMaxWidth} + #{$spacer * 2});
|
max-width: calc(#{$projectImageMaxWidth} + #{$spacer * 2});
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
padding: $spacer $spacer * 2;
|
padding: $spacer $spacer * 3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -26,23 +28,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.project {
|
.project {
|
||||||
flex: 0 0 calc(50% - #{$spacer});
|
|
||||||
text-align: center;
|
|
||||||
margin-bottom: $spacer * 6;
|
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
@media (min-width: 55rem) {
|
|
||||||
margin-bottom: $spacer * 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:last-child {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
a {
|
||||||
display: block;
|
display: block;
|
||||||
position: relative;
|
position: relative;
|
||||||
margin: 0 auto;
|
|
||||||
|
|
||||||
&::after {
|
&::after {
|
||||||
content: '';
|
content: '';
|
||||||
|
@ -67,3 +67,11 @@ $color-headings--dark: $brand-main-light;
|
|||||||
/////////////////////////////////////
|
/////////////////////////////////////
|
||||||
|
|
||||||
$spacer: ($font-size-base * $line-height);
|
$spacer: ($font-size-base * $line-height);
|
||||||
|
|
||||||
|
// Responsive breakpoints
|
||||||
|
/////////////////////////////////////
|
||||||
|
|
||||||
|
$screen-xs: 30em;
|
||||||
|
$screen-sm: 40em;
|
||||||
|
$screen-md: 60em;
|
||||||
|
$screen-lg: 70em;
|
||||||
|
@ -3,7 +3,6 @@ import PropTypes from 'prop-types'
|
|||||||
import Helmet from 'react-helmet'
|
import Helmet from 'react-helmet'
|
||||||
import ReactMarkdown from 'react-markdown'
|
import ReactMarkdown from 'react-markdown'
|
||||||
import { graphql } from 'gatsby'
|
import { graphql } from 'gatsby'
|
||||||
import Content from '../components/atoms/Content'
|
|
||||||
import FullWidth from '../components/atoms/FullWidth'
|
import FullWidth from '../components/atoms/FullWidth'
|
||||||
import ProjectImage from '../components/molecules/ProjectImage'
|
import ProjectImage from '../components/molecules/ProjectImage'
|
||||||
import ProjectTechstack from '../components/molecules/ProjectTechstack'
|
import ProjectTechstack from '../components/molecules/ProjectTechstack'
|
||||||
@ -43,16 +42,16 @@ const Project = ({ data }) => {
|
|||||||
|
|
||||||
<SEO project={project} />
|
<SEO project={project} />
|
||||||
|
|
||||||
<article className={styles.project}>
|
<article>
|
||||||
<Content>
|
<header>
|
||||||
<h1 className={styles.project__title}>{title}</h1>
|
<h1 className={styles.project__title}>{title}</h1>
|
||||||
<ReactMarkdown
|
</header>
|
||||||
source={descriptionWithLineBreaks}
|
<ReactMarkdown
|
||||||
className={styles.project__description}
|
source={descriptionWithLineBreaks}
|
||||||
/>
|
className={styles.project__description}
|
||||||
<ProjectImages projectImages={projectImages} title={title} />
|
/>
|
||||||
<ProjectMeta links={links} techstack={techstack} />
|
<ProjectImages projectImages={projectImages} title={title} />
|
||||||
</Content>
|
<ProjectMeta links={links} techstack={techstack} />
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
<ProjectNav slug={project.slug} />
|
<ProjectNav slug={project.slug} />
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
.spacer {
|
.spacer {
|
||||||
margin-bottom: $spacer * 3;
|
margin-bottom: $spacer * 3;
|
||||||
|
|
||||||
@media (min-width: 30rem) {
|
@media (min-width: $screen-xs) {
|
||||||
margin-bottom: $spacer * 6;
|
margin-bottom: $spacer * 6;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -12,27 +12,26 @@
|
|||||||
.project__title {
|
.project__title {
|
||||||
font-size: $font-size-h2;
|
font-size: $font-size-h2;
|
||||||
|
|
||||||
@media (min-width: 30rem) {
|
@media (min-width: $screen-xs) {
|
||||||
font-size: $font-size-h1;
|
font-size: $font-size-h1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.project__description {
|
.project__description {
|
||||||
font-size: $font-size-base;
|
font-size: $font-size-base;
|
||||||
margin-bottom: $spacer * 3;
|
margin-bottom: $spacer * 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
.project__meta {
|
.project__meta {
|
||||||
margin-top: $spacer * 5;
|
margin-top: -($spacer);
|
||||||
margin-bottom: $spacer * 5;
|
margin-bottom: $spacer * 5;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
grid-gap: $spacer * 2;
|
||||||
|
|
||||||
@media (min-width: 40rem) {
|
@media (min-width: $screen-sm) {
|
||||||
display: flex;
|
grid-template-columns: 1fr 1fr;
|
||||||
justify-content: space-between;
|
grid-gap: $spacer * 2;
|
||||||
|
|
||||||
> div {
|
|
||||||
flex: 0 0 45%;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user