mirror of
https://github.com/kremalicious/portfolio.git
synced 2024-12-23 01:29:41 +01:00
Merge pull request #42 from kremalicious/feature/scrollbar
custom scrollbar for project nav
This commit is contained in:
commit
db469c4315
39
README.md
39
README.md
@ -45,36 +45,57 @@ The whole [portfolio](https://matthiaskretschmann.com) is a React-based Single P
|
||||
|
||||
### 💍 One data file to rule all pages
|
||||
|
||||
All content is powered by one YAML file, [`data/projects.yml`](data/projects.yml) where all the portfolio's projects are defined. The project description itself is transformed from Markdown.
|
||||
All content is powered by one YAML file where all the portfolio's projects are defined. The project description itself is transformed from Markdown written inside the YAML file.
|
||||
|
||||
Gatsby automatically creates pages from each item in that file utilizing the [`src/templates/Project.jsx`](src/templates/Project.jsx) template.
|
||||
Gatsby automatically creates pages from each item in that file utilizing the [`Project.jsx`](src/templates/Project.jsx) template.
|
||||
|
||||
- [`data/projects.yml`](data/projects.yml)
|
||||
- [`src/templates/Project.jsx`](src/templates/Project.jsx)
|
||||
|
||||
### 💅 Theme switcher
|
||||
|
||||
Includes a theme switcher which allows user to toggle between a light and a dark theme. Switching between them also happens automatically based on user's local sunset and sunrise times. Uses Cloudflare's geo location HTTP header functionality.
|
||||
|
||||
If you want to know how, have a look at the respective component under [`src/components/molecules/ThemeSwitch.jsx`](src/components/molecules/ThemeSwitch.jsx)
|
||||
If a visitor has set the theme manually that selection is remembered in localStorage, and is restored on next visit.
|
||||
|
||||
If you want to know how, have a look at the respective components:
|
||||
|
||||
- [`src/components/molecules/ThemeSwitch.jsx`](src/components/molecules/ThemeSwitch.jsx)
|
||||
- [`src/store/provider.jsx`](src/store/provider.jsx)
|
||||
|
||||
### 🏆 SEO component
|
||||
|
||||
Includes a SEO component which automatically switches all required `meta` tags for search engines, Twitter Cards, and Facebook OpenGraph tags based on the browsed route/page.
|
||||
|
||||
If you want to know how, have a look at the respective component under [`src/components/atoms/SEO.jsx`](src/components/atoms/SEO.jsx)
|
||||
If you want to know how, have a look at the respective component:
|
||||
|
||||
- [`src/components/atoms/SEO.jsx`](src/components/atoms/SEO.jsx)
|
||||
|
||||
### 📇 Client-side vCard creation
|
||||
|
||||
The _Add to addressbook_ link in the footer automatically creates a downloadable vCard file on the client-side, based on data defined in `data/meta.yml`.
|
||||
|
||||
If you want to know how, have a look at the respective component under [`src/components/atoms/Vcard.jsx`](src/components/atoms/Vcard.jsx)
|
||||
If you want to know how, have a look at the respective component:
|
||||
|
||||
- [`src/components/atoms/Vcard.jsx`](src/components/atoms/Vcard.jsx)
|
||||
|
||||
### 💫 Page transitions
|
||||
|
||||
Includes mechanism for transitioning between route changes with full page transitions defined with [react-pose](https://popmotion.io/pose/). Mechanism ~~stolen~~ inspired by [gatsby-universal](https://github.com/fabe/gatsby-universal).
|
||||
|
||||
If you want to know how, have a look at the respective components:
|
||||
|
||||
- [`src/components/Layout.jsx`](src/components/Layout.jsx)
|
||||
- [`src/helpers/wrapPageElement.jsx`](src/helpers/wrapPageElement.jsx)
|
||||
- [`gatsby-browser.js`](gatsby-browser.js)
|
||||
- [`gatsby-ssr.js`](gatsby-ssr.js)
|
||||
|
||||
### 📈 Matomo (formerly Piwik) analytics tracking
|
||||
|
||||
Site sends usage statistics to my own [Matomo](https://matomo.org) installation. To make this work in Gatsby, I created and open sourced a plugin, [gatsby-plugin-matomo](https://github.com/kremalicious/gatsby-plugin-matomo), which is in use on this site.
|
||||
|
||||
- [gatsby-plugin-matomo](https://github.com/kremalicious/gatsby-plugin-matomo)
|
||||
|
||||
### 🖼 Project images
|
||||
|
||||
All project images live under `src/images` and are automatically attached to each project based on the inclusion of the project's `slug` in their filenames.
|
||||
@ -83,7 +104,9 @@ All project images make use of the excellent [gatsby-image](https://github.com/g
|
||||
|
||||
All together, Gatsby automatically generates all required image sizes for delivering responsible, responsive images to visitors, including lazy loading of all images. Also includes the [intersection-observer polyfill](https://github.com/w3c/IntersectionObserver) to make lazy loading work properly in Safari.
|
||||
|
||||
All project images use one single component defined in [`src/components/molecules/ProjectImage.jsx`](src/components/molecules/ProjectImage.jsx). In there, one main GraphQL query fragment is defined, which then gets used throughout other GraphQL queries.
|
||||
All project images use one single component where one main GraphQL query fragment is defined, which then gets used throughout other GraphQL queries.
|
||||
|
||||
- [`src/components/molecules/ProjectImage.jsx`](src/components/molecules/ProjectImage.jsx)
|
||||
|
||||
### 💎 Importing SVG assets
|
||||
|
||||
@ -99,7 +122,9 @@ import { ReactComponent as Logo } from './components/svg/Logo'
|
||||
|
||||
Includes a component for adding the Typekit snippet.
|
||||
|
||||
If you want to know how, have a look at the respective component under [`src/components/atoms/Typekit.jsx`](src/components/atoms/Typekit.jsx)
|
||||
If you want to know how, have a look at the respective component:
|
||||
|
||||
- [`src/components/atoms/Typekit.jsx`](src/components/atoms/Typekit.jsx)
|
||||
|
||||
## ✨ Development
|
||||
|
||||
|
@ -21,14 +21,5 @@
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
composes: metaTitle from '../../templates/Project.module.scss';
|
||||
}
|
||||
|
@ -2,7 +2,6 @@ import React, { Component } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { Link, graphql, StaticQuery } from 'gatsby'
|
||||
import Img from 'gatsby-image'
|
||||
import FullWidth from '../atoms/FullWidth'
|
||||
import styles from './ProjectNav.module.scss'
|
||||
|
||||
const query = graphql`
|
||||
@ -73,26 +72,24 @@ export default class ProjectNav extends Component {
|
||||
const projects = data.allProjectsYaml.edges
|
||||
|
||||
return (
|
||||
<FullWidth>
|
||||
<nav
|
||||
className={styles.projectNav}
|
||||
ref={node => (this.scrollContainer = node)}
|
||||
>
|
||||
{projects.map(({ node }) => {
|
||||
const current = node.slug === slug
|
||||
<nav
|
||||
className={styles.projectNav}
|
||||
ref={node => (this.scrollContainer = node)}
|
||||
>
|
||||
{projects.map(({ node }) => {
|
||||
const current = node.slug === slug
|
||||
|
||||
return (
|
||||
<div
|
||||
className={styles.item}
|
||||
key={node.slug}
|
||||
ref={node => current && (this.currentItem = node)}
|
||||
>
|
||||
<ProjectLink node={node} />
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</nav>
|
||||
</FullWidth>
|
||||
return (
|
||||
<div
|
||||
className={styles.item}
|
||||
key={node.slug}
|
||||
ref={node => current && (this.currentItem = node)}
|
||||
>
|
||||
<ProjectLink node={node} />
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</nav>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
|
@ -1,7 +1,6 @@
|
||||
@import 'variables';
|
||||
|
||||
.projectNav {
|
||||
// composes: fullWidth from '../atoms/FullWidth.module.scss';
|
||||
white-space: nowrap;
|
||||
overflow-y: hidden;
|
||||
overflow-x: auto;
|
||||
@ -11,6 +10,28 @@
|
||||
&::-moz-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: lighten($brand-grey-light, 25%);
|
||||
|
||||
:global(.dark) & {
|
||||
background: lighten($body-background-color--dark, 15%);
|
||||
}
|
||||
}
|
||||
|
||||
// stylelint-disable-next-line no-descending-specificity
|
||||
&::-webkit-scrollbar-track {
|
||||
background: darken($body-background-color, 2%);
|
||||
|
||||
:global(.dark) & {
|
||||
background: lighten($body-background-color--dark, 2%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.item {
|
||||
|
@ -28,14 +28,5 @@
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
composes: metaTitle from '../../templates/Project.module.scss';
|
||||
}
|
||||
|
@ -9,11 +9,10 @@ import ProjectTechstack from '../components/molecules/ProjectTechstack'
|
||||
import ProjectLinks from '../components/molecules/ProjectLinks'
|
||||
import ProjectNav from '../components/molecules/ProjectNav'
|
||||
import SEO from '../components/atoms/SEO'
|
||||
|
||||
import styles from './Project.module.scss'
|
||||
|
||||
const ProjectMeta = ({ links, techstack }) => (
|
||||
<footer className={styles.project__meta}>
|
||||
<footer className={styles.meta}>
|
||||
{!!links && <ProjectLinks links={links} />}
|
||||
{!!techstack && <ProjectTechstack techstack={techstack} />}
|
||||
</footer>
|
||||
@ -22,7 +21,7 @@ const ProjectMeta = ({ links, techstack }) => (
|
||||
const ProjectImages = ({ projectImages, title }) => (
|
||||
<FullWidth>
|
||||
{projectImages.map(({ node }) => (
|
||||
<div className={styles.spacer} key={node.id}>
|
||||
<div className={styles.imageWrap} key={node.id}>
|
||||
<ProjectImage fluid={node.fluid} alt={title} />
|
||||
</div>
|
||||
))}
|
||||
@ -44,11 +43,11 @@ const Project = ({ data }) => {
|
||||
|
||||
<article>
|
||||
<header>
|
||||
<h1 className={styles.project__title}>{title}</h1>
|
||||
<h1 className={styles.title}>{title}</h1>
|
||||
</header>
|
||||
<ReactMarkdown
|
||||
source={descriptionWithLineBreaks}
|
||||
className={styles.project__description}
|
||||
className={styles.description}
|
||||
/>
|
||||
<ProjectImages projectImages={projectImages} title={title} />
|
||||
<ProjectMeta links={links} techstack={techstack} />
|
||||
|
@ -1,7 +1,7 @@
|
||||
@import 'variables';
|
||||
@import '../components/molecules/ProjectImage.module';
|
||||
|
||||
.spacer {
|
||||
.imageWrap {
|
||||
margin-bottom: $spacer * 3;
|
||||
|
||||
@media (min-width: $screen-xs) {
|
||||
@ -9,7 +9,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.project__title {
|
||||
.title {
|
||||
font-size: $font-size-h2;
|
||||
|
||||
@media (min-width: $screen-xs) {
|
||||
@ -17,12 +17,12 @@
|
||||
}
|
||||
}
|
||||
|
||||
.project__description {
|
||||
.description {
|
||||
font-size: $font-size-base;
|
||||
margin-bottom: $spacer * 2;
|
||||
}
|
||||
|
||||
.project__meta {
|
||||
.meta {
|
||||
margin-top: -($spacer);
|
||||
margin-bottom: $spacer * 5;
|
||||
display: grid;
|
||||
@ -35,7 +35,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.project__meta__title {
|
||||
.metaTitle {
|
||||
font-size: $font-size-h3;
|
||||
margin-bottom: $spacer * 1.5;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user