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

refactor & restyling

This commit is contained in:
Matthias Kretschmann 2019-10-28 23:00:55 +01:00
parent a6294e523f
commit 2a31adc585
Signed by: m
GPG Key ID: 606EEEF3C479A91F
75 changed files with 309 additions and 430 deletions

View File

@ -68,12 +68,12 @@ As a fallback, QR codes are generated with [react-qr-svg](https://github.com/no2
If you want to know how this works, have a look at the respective components under If you want to know how this works, have a look at the respective components under
- [`src/components/Web3Donation/index.jsx`](src/components/Web3Donation/index.jsx) - [`src/components/molecules/Web3Donation/index.jsx`](src/components/molecules/Web3Donation/index.jsx)
- [`src/components/Web3Donation/Account.jsx`](src/components/Web3Donation/Account.jsx) - [`src/components/molecules/Web3Donation/Account.jsx`](src/components/molecules/Web3Donation/Account.jsx)
- [`src/components/Web3Donation/InputGroup.jsx`](src/components/Web3Donation/InputGroup.jsx) - [`src/components/molecules/Web3Donation/InputGroup.jsx`](src/components/molecules/Web3Donation/InputGroup.jsx)
- [`src/components/Web3Donation/Conversion.jsx`](src/components/Web3Donation/Conversion.jsx) - [`src/components/molecules/Web3Donation/Conversion.jsx`](src/components/molecules/Web3Donation/Conversion.jsx)
- [`src/components/Web3Donation/Alerts.jsx`](src/components/Web3Donation/Alerts.jsx) - [`src/components/molecules/Web3Donation/Alerts.jsx`](src/components/molecules/Web3Donation/Alerts.jsx)
- [`src/components/Web3Donation/utils.jsx`](src/components/Web3Donation/utils.jsx) - [`src/components/molecules/Web3Donation/utils.jsx`](src/components/molecules/Web3Donation/utils.jsx)
- [`src/components/atoms/Qr.jsx`](src/components/atoms/Qr.jsx) - [`src/components/atoms/Qr.jsx`](src/components/atoms/Qr.jsx)
### 🔍 Search ### 🔍 Search
@ -84,9 +84,9 @@ A global search is provided with [gatsby-plugin-lunr](https://github.com/humanse
If you want to know how this works, have a look at the respective components under If you want to know how this works, have a look at the respective components under
- [`src/components/Search/Search.jsx`](src/components/Search/Search.jsx) - [`src/components/molecules/Search/Search.jsx`](src/components/molecules/Search/Search.jsx)
- [`src/components/Search/SearchResults.jsx`](src/components/Search/SearchResults.jsx) - [`src/components/molecules/Search/SearchResults.jsx`](src/components/molecules/Search/SearchResults.jsx)
- more in [`src/components/Search/`](src/components/Search/) - more in [`src/components/molecules/Search/`](src/components/molecules/Search/)
### 🕸 Related Posts ### 🕸 Related Posts

View File

@ -140,9 +140,9 @@ So it's a pretty good idea to make this backwards compatible with some quick if
if ( (function_exists('has_post_thumbnail')) && (has_post_thumbnail()) ) { if ( (function_exists('has_post_thumbnail')) && (has_post_thumbnail()) ) {
the_post_thumbnail(); the_post_thumbnail();
} else { } else {
$postimage = get_post_meta($post->ID, 'post-image', true); $Image = get_post_meta($post->ID, 'post-image', true);
if ($postimage) { if ($Image) {
echo '<img src="'.$postimage.'" alt="" />'; echo '<img src="'.$Image.'" alt="" />';
} }
} }
``` ```

View File

@ -10,6 +10,8 @@ tags:
- goodies - goodies
- gatsby - gatsby
- matomo - matomo
featured: true
--- ---
Plugin for [Gatsby](https://www.gatsbyjs.org) to add tracking with the open-source analytics platform [Matomo](https://matomo.org) (formerly Piwik) onto a site, prioritizing user experience & privacy with sensible defaults. Plugin for [Gatsby](https://www.gatsbyjs.org) to add tracking with the open-source analytics platform [Matomo](https://matomo.org) (formerly Piwik) onto a site, prioritizing user experience & privacy with sensible defaults.

View File

@ -35,7 +35,6 @@ module.exports = {
options: { options: {
maxWidth: 630, maxWidth: 630,
quality: 80, quality: 80,
withWebp: true,
linkImagesToOriginal: true, linkImagesToOriginal: true,
showCaptions: true, showCaptions: true,
backgroundColor: 'none', backgroundColor: 'none',

View File

@ -7,7 +7,7 @@ const redirects = [
] ]
exports.generatePostPages = (createPage, posts, numPages) => { exports.generatePostPages = (createPage, posts, numPages) => {
const postTemplate = path.resolve('src/templates/Post.tsx') const postTemplate = path.resolve('src/templates/Post/index.tsx')
// Create Post pages // Create Post pages
posts.forEach(post => { posts.forEach(post => {

View File

@ -35,18 +35,18 @@
"dms2dec": "^1.1.0", "dms2dec": "^1.1.0",
"fast-exif": "^1.0.1", "fast-exif": "^1.0.1",
"fraction.js": "^4.0.12", "fraction.js": "^4.0.12",
"gatsby": "^2.17.1", "gatsby": "^2.17.5",
"gatsby-image": "^2.2.29", "gatsby-image": "^2.2.30",
"gatsby-plugin-catch-links": "^2.1.15", "gatsby-plugin-catch-links": "^2.1.15",
"gatsby-plugin-feed": "^2.3.19", "gatsby-plugin-feed": "^2.3.19",
"gatsby-plugin-lunr": "^1.5.2", "gatsby-plugin-lunr": "^1.5.2",
"gatsby-plugin-manifest": "^2.2.23", "gatsby-plugin-manifest": "^2.2.24",
"gatsby-plugin-matomo": "^0.7.2", "gatsby-plugin-matomo": "^0.7.2",
"gatsby-plugin-meta-redirect": "^1.1.1", "gatsby-plugin-meta-redirect": "^1.1.1",
"gatsby-plugin-offline": "^3.0.16", "gatsby-plugin-offline": "^3.0.17",
"gatsby-plugin-react-helmet": "^3.1.13", "gatsby-plugin-react-helmet": "^3.1.13",
"gatsby-plugin-sass": "^2.1.20", "gatsby-plugin-sass": "^2.1.20",
"gatsby-plugin-sharp": "^2.2.32", "gatsby-plugin-sharp": "^2.2.33",
"gatsby-plugin-sitemap": "^2.2.19", "gatsby-plugin-sitemap": "^2.2.19",
"gatsby-plugin-svgr": "^2.0.2", "gatsby-plugin-svgr": "^2.0.2",
"gatsby-plugin-typescript": "^2.1.15", "gatsby-plugin-typescript": "^2.1.15",
@ -58,10 +58,10 @@
"gatsby-remark-images": "^3.1.28", "gatsby-remark-images": "^3.1.28",
"gatsby-remark-smartypants": "^2.1.14", "gatsby-remark-smartypants": "^2.1.14",
"gatsby-remark-vscode": "^1.2.0", "gatsby-remark-vscode": "^1.2.0",
"gatsby-source-filesystem": "^2.1.33", "gatsby-source-filesystem": "^2.1.34",
"gatsby-source-graphql": "^2.1.20", "gatsby-source-graphql": "^2.1.21",
"gatsby-transformer-remark": "^2.6.30", "gatsby-transformer-remark": "^2.6.31",
"gatsby-transformer-sharp": "^2.3.0", "gatsby-transformer-sharp": "^2.3.1",
"graphql": "^14.5.8", "graphql": "^14.5.8",
"intersection-observer": "^0.7.0", "intersection-observer": "^0.7.0",
"js-scrypt": "^0.2.0", "js-scrypt": "^0.2.0",
@ -73,7 +73,7 @@
"react-clipboard.js": "^2.0.13", "react-clipboard.js": "^2.0.13",
"react-dom": "^16.11.0", "react-dom": "^16.11.0",
"react-helmet": "^5.2.1", "react-helmet": "^5.2.1",
"react-modal": "^3.10.1", "react-modal": "^3.11.1",
"react-pose": "^4.0.9", "react-pose": "^4.0.9",
"react-qr-svg": "^2.2.1", "react-qr-svg": "^2.2.1",
"react-transition-group": "^4.3.0", "react-transition-group": "^4.3.0",
@ -88,25 +88,25 @@
"@babel/preset-env": "^7.6.3", "@babel/preset-env": "^7.6.3",
"@babel/preset-typescript": "^7.6.0", "@babel/preset-typescript": "^7.6.0",
"@svgr/webpack": "^4.3.3", "@svgr/webpack": "^4.3.3",
"@testing-library/jest-dom": "^4.1.2", "@testing-library/jest-dom": "^4.2.0",
"@testing-library/react": "^9.3.0", "@testing-library/react": "^9.3.0",
"@types/classnames": "^2.2.9", "@types/classnames": "^2.2.9",
"@types/jest": "^24.0.19", "@types/jest": "^24.0.20",
"@types/lunr": "^2.3.2", "@types/lunr": "^2.3.2",
"@types/node": "^12.11.5", "@types/node": "^12.11.7",
"@types/react": "^16.9.9", "@types/react": "^16.9.11",
"@types/react-dom": "^16.9.2", "@types/react-dom": "^16.9.3",
"@types/react-helmet": "^5.0.13", "@types/react-helmet": "^5.0.13",
"@types/react-modal": "^3.10.0", "@types/react-modal": "^3.10.0",
"@types/react-transition-group": "^4.2.3", "@types/react-transition-group": "^4.2.3",
"@types/shortid": "0.0.29", "@types/shortid": "0.0.29",
"@types/web3": "^1.0.20", "@types/web3": "^1.0.20",
"@typescript-eslint/eslint-plugin": "^2.5.0", "@typescript-eslint/eslint-plugin": "^2.6.0",
"@typescript-eslint/parser": "^2.5.0", "@typescript-eslint/parser": "^2.6.0",
"babel-eslint": "^10.0.3", "babel-eslint": "^10.0.3",
"babel-jest": "^24.9.0", "babel-jest": "^24.9.0",
"eslint": "^6.5.1", "eslint": "^6.6.0",
"eslint-config-prettier": "^6.4.0", "eslint-config-prettier": "^6.5.0",
"eslint-loader": "^3.0.2", "eslint-loader": "^3.0.2",
"eslint-plugin-graphql": "^3.1.0", "eslint-plugin-graphql": "^3.1.0",
"eslint-plugin-jsx-a11y": "^6.2.3", "eslint-plugin-jsx-a11y": "^6.2.3",
@ -117,7 +117,7 @@
"jest": "^24.9.0", "jest": "^24.9.0",
"markdownlint-cli": "^0.19.0", "markdownlint-cli": "^0.19.0",
"node-iptc": "^1.0.5", "node-iptc": "^1.0.5",
"node-sass": "^4.12.0", "node-sass": "^4.13.0",
"npm-run-all": "^4.1.5", "npm-run-all": "^4.1.5",
"ora": "^4.0.0", "ora": "^4.0.0",
"pify": "^4.0.1", "pify": "^4.0.1",

30
src/@types/Image.d.ts vendored Normal file
View File

@ -0,0 +1,30 @@
import { FixedObject, FluidObject } from 'gatsby-image'
export interface ImageProps {
title?: string
fluid?: FluidObject
fixed?: FixedObject
alt: string
original?: { src: string }
}
export interface ImageNode {
childImageSharp: ImageProps
fields: {
exif: Exif
}
}
export interface Exif {
iso: string
model: string
fstop: string
shutterspeed: string
focalLength: string
lensModel: string
exposure: string
gps: {
latitude: string
longitude: string
}
}

32
src/@types/Post.d.ts vendored Normal file
View File

@ -0,0 +1,32 @@
import { ImageNode } from './Image'
export interface Fields {
slug: string
date: string
githubLink?: string
}
export interface Frontmatter {
title: string
type?: string
description?: string
image?: ImageNode
author?: string
updated?: string
tags?: string[]
linkurl?: string
style?: {
publicURL?: string
}
changelog?: string
}
export interface Post {
id?: string
html?: string
excerpt?: string
frontmatter: Frontmatter
fields?: Fields
rawMarkdownBody?: string
fileAbsolutePath?: string
}

View File

@ -1,53 +0,0 @@
import { FluidObject } from 'gatsby-image'
export interface PostMetadataFields {
slug: string
date: string
githubLink: string
}
export interface PostMetadataImageExif {
iso: string
model: string
fstop: string
shutterspeed: string
focalLength: string
lensModel: string
exposure: string
gps: {
latitude: string
longitude: string
}
}
export interface PostMetadataImage {
childImageSharp: { fluid: FluidObject }
fields: {
exif: PostMetadataImageExif
}
}
export interface PostMetadataFrontmatter {
type?: string
title: string
description?: string
image?: PostMetadataImage
author?: string
updated?: string
tags?: string[]
linkurl?: string
style?: {
publicURL?: string
}
changelog?: string
}
export interface PostMetadata {
id?: string
html?: string
excerpt?: string
frontmatter: PostMetadataFrontmatter
fields?: PostMetadataFields
rawMarkdownBody?: string
fileAbsolutePath?: string
}

View File

@ -14,7 +14,7 @@ export interface Author {
ether: string ether: string
} }
export interface SiteMetadata { export interface Site {
siteTitle: string siteTitle: string
siteTitleShort: string siteTitleShort: string
siteDescription: string siteDescription: string

View File

@ -1,22 +0,0 @@
import React from 'react'
import Image from '../atoms/Image'
import styles from './PostImage.module.scss'
import { FluidObject, FixedObject } from 'gatsby-image'
interface PostImageProps {
title?: string
fluid?: FluidObject
fixed?: FixedObject
alt: string
}
const PostImage = ({ title, fluid, fixed, alt }: PostImageProps) => (
<figure className={styles.postImage}>
<Image fluid={fluid} fixed={fixed} alt={alt} />
{title && (
<figcaption className={styles.postImageTitle}>{title}</figcaption>
)}
</figure>
)
export default PostImage

View File

@ -1,9 +1,9 @@
import React from 'react' import React from 'react'
import ExifMap from './ExifMap' import ExifMap from './ExifMap'
import styles from './Exif.module.scss' import styles from './Exif.module.scss'
import { PostMetadataImageExif } from '../../@types/PostMetadata' import { Exif as ExifMeta } from '../../@types/Post'
export default function Exif({ exif }: { exif: PostMetadataImageExif }) { export default function Exif({ exif }: { exif: ExifMeta }) {
const { iso, model, fstop, shutterspeed, focalLength, exposure, gps } = exif const { iso, model, fstop, shutterspeed, focalLength, exposure, gps } = exif
return ( return (

View File

@ -10,7 +10,7 @@
@media (min-width: 940px) { @media (min-width: 940px) {
max-width: 940px; max-width: 940px;
border-radius: 0.25rem; border-radius: $border-radius;
overflow: hidden; overflow: hidden;
} }

View File

@ -1,30 +1,24 @@
import React from 'react' import React from 'react'
import { graphql } from 'gatsby' import { graphql } from 'gatsby'
import Img, { FixedObject, FluidObject } from 'gatsby-image' import Img from 'gatsby-image'
import styles from './Image.module.scss' import styles from './Image.module.scss'
import { ImageProps } from '../../@types/Image'
export default function Image({ export const Image = ({ fluid, fixed, alt }: ImageProps) => (
fluid, <Img
fixed, className={styles.imageWrap}
alt backgroundColor="transparent"
}: { fluid={fluid}
fluid?: FluidObject fixed={fixed}
fixed?: FixedObject alt={alt}
alt: string />
}) { )
return (
<Img
className={styles.imageWrap}
backgroundColor="transparent"
fluid={fluid}
fixed={fixed}
alt={alt}
/>
)
}
export const imageSizeDefault = graphql` export const imageSizeDefault = graphql`
fragment ImageFluid on ImageSharp { fragment ImageFluid on ImageSharp {
original {
src
}
fluid(maxWidth: 940, quality: 85) { fluid(maxWidth: 940, quality: 85) {
...GatsbyImageSharpFluid_withWebp_noBase64 ...GatsbyImageSharpFluid_withWebp_noBase64
} }
@ -33,7 +27,10 @@ export const imageSizeDefault = graphql`
export const imageSizeThumb = graphql` export const imageSizeThumb = graphql`
fragment ImageFluidThumb on ImageSharp { fragment ImageFluidThumb on ImageSharp {
fluid(maxWidth: 200, maxHeight: 85, quality: 85, cropFocus: CENTER) { original {
src
}
fluid(maxWidth: 400, maxHeight: 170, quality: 85, cropFocus: CENTER) {
...GatsbyImageSharpFluid_withWebp_noBase64 ...GatsbyImageSharpFluid_withWebp_noBase64
} }
} }

View File

@ -2,7 +2,7 @@ import React from 'react'
import { graphql, useStaticQuery } from 'gatsby' import { graphql, useStaticQuery } from 'gatsby'
import { Helmet } from 'react-helmet' import { Helmet } from 'react-helmet'
import { useSiteMetadata } from '../../hooks/use-site-metadata' import { useSiteMetadata } from '../../hooks/use-site-metadata'
import { PostMetadata } from '../../@types/PostMetadata' import { Post } from '../../@types/Post'
const query = graphql` const query = graphql`
query { query {
@ -117,7 +117,7 @@ export default function SEO({
slug, slug,
postSEO postSEO
}: { }: {
post?: PostMetadata post?: Post
slug?: string slug?: string
postSEO?: boolean postSEO?: boolean
}) { }) {

View File

@ -2,26 +2,16 @@
@import 'mixins'; @import 'mixins';
.featured { .featured {
@include breakoutviewport;
@include divider; @include divider;
display: flex; display: grid;
justify-content: space-between; gap: $spacer;
flex-wrap: wrap; grid-template-columns: 1fr 1fr;
padding-left: $spacer; padding-bottom: $spacer * 3;
padding-right: $spacer; margin-bottom: -($spacer / 2);
margin-bottom: -($spacer);
padding-bottom: $spacer * $line-height;
@media (min-width: $screen-xs) {
padding-bottom: $spacer * 3;
margin-top: $spacer * $line-height;
}
@media (min-width: $screen-md) { @media (min-width: $screen-md) {
padding-left: 0; @include breakoutviewport;
padding-right: 0;
justify-content: initial;
} }
} }
@ -44,28 +34,6 @@
.featuredItem { .featuredItem {
position: relative; position: relative;
max-width: 12rem;
flex: 0 0 48%;
margin-bottom: $spacer / 2;
&:last-child {
margin-bottom: 0;
display: none;
}
@media (min-width: $screen-xs) {
flex: 1;
max-width: none;
margin-left: $spacer / 2;
&:last-child {
display: block;
}
&:first-child {
margin-left: 0;
}
}
a { a {
display: block; display: block;

View File

@ -1,17 +1,17 @@
import React from 'react' import React from 'react'
import { Link, graphql, useStaticQuery } from 'gatsby' import { Link, graphql, useStaticQuery } from 'gatsby'
import Image from '../atoms/Image' import { Image } from '../atoms/Image'
import styles from './Featured.module.scss' import styles from './Featured.module.scss'
import { PostMetadata } from '../../@types/PostMetadata' import { Post } from '../../@types/Post'
function FeaturedPure({ function FeaturedPure({
data data
}: { }: {
data: { allMarkdownRemark: { edges: [{ node: PostMetadata }] } } data: { allMarkdownRemark: { edges: [{ node: Post }] } }
}) { }) {
return ( return (
<div className={styles.featured}> <div className={styles.featured}>
{data.allMarkdownRemark.edges.map(({ node }: { node: PostMetadata }) => { {data.allMarkdownRemark.edges.map(({ node }: { node: Post }) => {
const { title, image } = node.frontmatter const { title, image } = node.frontmatter
const { slug } = node.fields const { slug } = node.fields

View File

@ -4,7 +4,7 @@ import { Link } from 'gatsby'
import Hamburger from '../atoms/Hamburger' import Hamburger from '../atoms/Hamburger'
import styles from './Menu.module.scss' import styles from './Menu.module.scss'
import { useSiteMetadata } from '../../hooks/use-site-metadata' import { useSiteMetadata } from '../../hooks/use-site-metadata'
import { MenuItem } from '../../@types/SiteMetadata' import { MenuItem } from '../../@types/Site'
export default function Menu() { export default function Menu() {
const [menuOpen, setMenuOpen] = useState(false) const [menuOpen, setMenuOpen] = useState(false)

View File

@ -52,8 +52,6 @@
} }
.title { .title {
@include heading-band;
font-size: $font-size-h3; font-size: $font-size-h3;
} }

View File

@ -1,11 +1,8 @@
import React, { useState } from 'react' import React, { useState } from 'react'
import { graphql, useStaticQuery } from 'gatsby' import { graphql, useStaticQuery } from 'gatsby'
import PostTeaser from '../Post/PostTeaser' import PostTeaser from '../../templates/Post/PostTeaser'
import styles from './RelatedPosts.module.scss' import styles from './RelatedPosts.module.scss'
import { import { Post, Frontmatter } from '../../@types/Post'
PostMetadata,
PostMetadataFrontmatter
} from '../../@types/PostMetadata'
const query = graphql` const query = graphql`
query { query {
@ -36,11 +33,11 @@ const query = graphql`
` `
function postsWithDataFilter( function postsWithDataFilter(
posts: [{ node: PostMetadata }], posts: [{ node: Post }],
key: keyof PostMetadataFrontmatter, key: keyof Frontmatter,
valuesToFind: string[] valuesToFind: string[]
) { ) {
const newArray = posts.filter(({ node }: { node: PostMetadata }) => { const newArray = posts.filter(({ node }: { node: Post }) => {
const frontmatterKey = node.frontmatter[key] as [] const frontmatterKey = node.frontmatter[key] as []
if ( if (
@ -54,7 +51,7 @@ function postsWithDataFilter(
} }
function photosWithDataFilter(posts: []) { function photosWithDataFilter(posts: []) {
const newArray = posts.filter((post: { node: PostMetadata }) => { const newArray = posts.filter((post: { node: Post }) => {
const { fileAbsolutePath } = post.node const { fileAbsolutePath } = post.node
if (fileAbsolutePath.includes('content/photos')) { if (fileAbsolutePath.includes('content/photos')) {
@ -93,7 +90,7 @@ export default function RelatedPosts({
{filteredPosts {filteredPosts
.sort(() => 0.5 - Math.random()) .sort(() => 0.5 - Math.random())
.slice(0, 6) .slice(0, 6)
.map(({ node }: { node: PostMetadata }) => ( .map(({ node }: { node: Post }) => (
<PostTeaser key={node.id} post={node} /> <PostTeaser key={node.id} post={node} />
))} ))}
</ul> </ul>

View File

@ -1,5 +1,5 @@
import React from 'react' import React from 'react'
import { ReactComponent as SearchIcon } from '../../images/magnifying-glass.svg' import { ReactComponent as SearchIcon } from '../../../images/magnifying-glass.svg'
import styles from './SearchButton.module.scss' import styles from './SearchButton.module.scss'
const SearchButton = (props: any) => ( const SearchButton = (props: any) => (

View File

@ -1,7 +1,7 @@
@import 'variables'; @import 'variables';
.searchInput { .searchInput {
composes: input from '../atoms/Input.module.scss'; composes: input from '../../atoms/Input.module.scss';
&::-webkit-search-cancel-button { &::-webkit-search-cancel-button {
display: none; display: none;

View File

@ -1,5 +1,5 @@
import React from 'react' import React from 'react'
import Input from '../atoms/Input' import Input from '../../atoms/Input'
import styles from './SearchInput.module.scss' import styles from './SearchInput.module.scss'
export default function SearchInput({ export default function SearchInput({

View File

@ -1,11 +1,11 @@
import React from 'react' import React from 'react'
import ReactDOM from 'react-dom' import ReactDOM from 'react-dom'
import { graphql, useStaticQuery } from 'gatsby' import { graphql, useStaticQuery } from 'gatsby'
import Container from '../atoms/Container' import Container from '../../atoms/Container'
import PostTeaser from '../Post/PostTeaser' import PostTeaser from '../../../templates/Post/PostTeaser'
import SearchResultsEmpty from './SearchResultsEmpty' import SearchResultsEmpty from './SearchResultsEmpty'
import styles from './SearchResults.module.scss' import styles from './SearchResults.module.scss'
import { PostMetadata } from '../../@types/PostMetadata' import { Post } from '../../../@types/Post'
export interface Results { export interface Results {
slug: string slug: string
@ -40,7 +40,7 @@ function SearchResultsPure({
toggleSearch, toggleSearch,
posts posts
}: { }: {
posts: [{ node: PostMetadata }] posts: [{ node: Post }]
searchQuery: string searchQuery: string
results: Results[] results: Results[]
toggleSearch(): void toggleSearch(): void
@ -53,10 +53,9 @@ function SearchResultsPure({
{results.map((page: { slug: string }) => {results.map((page: { slug: string }) =>
posts posts
.filter( .filter(
({ node }: { node: PostMetadata }) => ({ node }: { node: Post }) => node.fields.slug === page.slug
node.fields.slug === page.slug
) )
.map(({ node }: { node: PostMetadata }) => ( .map(({ node }: { node: Post }) => (
<PostTeaser <PostTeaser
key={page.slug} key={page.slug}
post={node} post={node}

View File

@ -1,5 +1,5 @@
import React from 'react' import React from 'react'
import Input from '../atoms/Input' import Input from '../../atoms/Input'
import Account from './Account' import Account from './Account'
import Conversion from './Conversion' import Conversion from './Conversion'
import styles from './InputGroup.module.scss' import styles from './InputGroup.module.scss'

View File

@ -2,7 +2,7 @@ import React, { useState } from 'react'
import Container from '../atoms/Container' import Container from '../atoms/Container'
import Vcard from '../molecules/Vcard' import Vcard from '../molecules/Vcard'
import ThemeSwitch from '../molecules/ThemeSwitch' import ThemeSwitch from '../molecules/ThemeSwitch'
import ModalThanks from '../molecules/ModalThanks' import ModalThanks from './ModalThanks'
import { ReactComponent as Github } from '../../images/github.svg' import { ReactComponent as Github } from '../../images/github.svg'
import { ReactComponent as Bitcoin } from '../../images/bitcoin.svg' import { ReactComponent as Bitcoin } from '../../images/bitcoin.svg'

View File

@ -1,7 +1,7 @@
import React from 'react' import React from 'react'
import { Link } from 'gatsby' import { Link } from 'gatsby'
import Container from '../atoms/Container' import Container from '../atoms/Container'
import Search from '../Search' import Search from '../molecules/Search'
import Menu from '../molecules/Menu' import Menu from '../molecules/Menu'
import { ReactComponent as Logo } from '../../images/logo.svg' import { ReactComponent as Logo } from '../../images/logo.svg'

View File

@ -1,14 +1,27 @@
import React, { lazy, Suspense } from 'react' import React, { lazy, Suspense } from 'react'
import shortid from 'shortid'
import { Author } from '../../@types/Site'
import { useSiteMetadata } from '../../hooks/use-site-metadata' import { useSiteMetadata } from '../../hooks/use-site-metadata'
import Modal from '../atoms/Modal' import Modal from '../atoms/Modal'
import styles from './ModalThanks.module.scss' import styles from './ModalThanks.module.scss'
const Web3Donation = lazy(() => import('../Web3Donation')) const Web3Donation = lazy(() => import('../molecules/Web3Donation'))
const Qr = lazy(() => import('../atoms/Qr')) const Qr = lazy(() => import('../atoms/Qr'))
const Coin = ({ address, author }: { address: string; author: Author }) => (
<div className={styles.coin}>
<Suspense fallback={<div>Loading...</div>}>
<Qr title={address} address={(author as any)[address]} />
</Suspense>
</div>
)
export default function ModalThanks(props: any) { export default function ModalThanks(props: any) {
const { author } = useSiteMetadata() const { author } = useSiteMetadata()
const coins = Object.keys(author).filter(
key => key === 'bitcoin' || key === 'ether'
)
return ( return (
<Modal <Modal
@ -26,15 +39,9 @@ export default function ModalThanks(props: any) {
<p>Send Bitcoin or Ether from any wallet.</p> <p>Send Bitcoin or Ether from any wallet.</p>
</header> </header>
{Object.keys(author) {coins.map((address: string) => (
.filter(key => key === 'bitcoin' || key === 'ether') <Coin key={shortid.generate()} address={address} author={author} />
.map((address: string, i: number) => ( ))}
<div key={i} className={styles.coin}>
<Suspense fallback={<div>Loading...</div>}>
<Qr title={address} address={(author as any)[address]} />
</Suspense>
</div>
))}
</div> </div>
</Modal> </Modal>
) )

View File

@ -1,7 +1,7 @@
import { useStaticQuery, graphql } from 'gatsby' import { useStaticQuery, graphql } from 'gatsby'
import { SiteMetadata } from '../@types/SiteMetadata' import { Site } from '../@types/Site'
export function useSiteMetadata(): SiteMetadata { export function useSiteMetadata(): Site {
const query = graphql` const query = graphql`
query { query {
site { site {

View File

@ -1,9 +1,9 @@
import React from 'react' import React from 'react'
import { graphql, Link } from 'gatsby' import { graphql, Link } from 'gatsby'
import PostImage from '../components/Post/PostImage' import PostImage from '../templates/Post/PostImage'
import Page from '../templates/Page' import Page from '../templates/Page'
import styles from './goodies.module.scss' import styles from './goodies.module.scss'
import { PostMetadata } from '../@types/PostMetadata' import { Post } from '../@types/Post'
const page = { const page = {
frontmatter: { frontmatter: {
@ -13,7 +13,7 @@ const page = {
} }
} }
const GoodiesThumb = ({ post }: { post: PostMetadata }) => { const GoodiesThumb = ({ post }: { post: Post }) => {
const { title, image } = post.frontmatter const { title, image } = post.frontmatter
const { slug } = post.fields const { slug } = post.fields
@ -33,7 +33,7 @@ export default function Goodies({
data, data,
location location
}: { }: {
data: { goodies: { edges: [{ node: PostMetadata }] } } data: { goodies: { edges: [{ node: Post }] } }
location: Location location: Location
}) { }) {
return ( return (

View File

@ -1,9 +1,9 @@
import React from 'react' import React from 'react'
import { graphql, Link } from 'gatsby' import { graphql, Link } from 'gatsby'
import Page from '../templates/Page' import Page from '../templates/Page'
import PostImage from '../components/Post/PostImage' import PostImage from '../templates/Post/PostImage'
import styles from './photos.module.scss' import styles from './photos.module.scss'
import { PostMetadata } from '../@types/PostMetadata' import { Post } from '../@types/Post'
const page = { const page = {
frontmatter: { frontmatter: {
@ -12,7 +12,7 @@ const page = {
} }
} }
const PhotoThumb = ({ photo }: { photo: PostMetadata }) => { const PhotoThumb = ({ photo }: { photo: Post }) => {
const { title, image } = photo.frontmatter const { title, image } = photo.frontmatter
const { slug } = photo.fields const { slug } = photo.fields
const { fluid } = image.childImageSharp const { fluid } = image.childImageSharp
@ -32,7 +32,7 @@ export default function Photos({
data, data,
location location
}: { }: {
data: { photos: { edges: [{ node: PostMetadata }] } } data: { photos: { edges: [{ node: Post }] } }
location: Location location: Location
}) { }) {
return ( return (

View File

@ -1,32 +0,0 @@
.gatsby-resp-image-figure,
.gatsby-resp-image-wrapper {
margin-bottom: $spacer;
}
.anchor {
margin-top: $spacer / 3;
font-size: $font-size-large;
color: $brand-grey-light;
font-weight: 700;
span {
transition: opacity 0.2s ease-out;
}
}
h1,
h2,
h3,
h4,
h5,
h6 {
.anchor span {
opacity: 0;
}
&:hover {
.anchor span {
opacity: 1;
}
}
}

View File

@ -1,57 +1,5 @@
@import 'variables'; @import 'variables';
// Centering Blocks
/////////////////////////////////////
@mixin aligncenter() {
display: block;
margin-left: auto;
margin-right: auto;
}
// Toggling content
/////////////////////////////////////
// Hide from both screenreaders and browsers: h5bp.com/u
@mixin hide() {
display: none !important;
visibility: hidden;
}
@mixin show() {
display: block;
visibility: visible;
}
// Hide only visually, but have it available for screenreaders: h5bp.com/v
@mixin visuallyhidden() {
border: 0;
clip: rect(0 0 0 0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
// Extends the .visuallyhidden class to allow the
// element to be focusable when navigated to via the keyboard: h5bp.com/p
&.focusable:active,
&.focusable:focus {
clip: auto;
height: auto;
margin: 0;
overflow: visible;
position: static;
width: auto;
}
}
// Hide visually and from screenreaders, but maintain layout
@mixin invisible() {
visibility: hidden;
}
// CSS image replacement // CSS image replacement
///////////////////////////////////// /////////////////////////////////////
@ -132,20 +80,6 @@
} }
} }
// Heading band
/////////////////////////////////////
@mixin heading-band() {
display: inline-block;
background: rgba(255, 255, 255, 0.5);
padding: ($spacer/2) $spacer ($spacer/2) 100%;
margin-left: -100%;
:global(.dark) & {
background: darken($body-background-color--dark, 2%);
}
}
// Layout breakout // Layout breakout
///////////////////////////////////// /////////////////////////////////////

View File

@ -68,7 +68,7 @@ $font-family-monospace: 'Fira Code', 'Fira Mono', Menlo, Monaco, Consolas,
$font-family-headings: 'brandon-grotesque', 'Avenir Next', 'Helvetica Neue', $font-family-headings: 'brandon-grotesque', 'Avenir Next', 'Helvetica Neue',
Helvetica, Arial, sans-serif; Helvetica, Arial, sans-serif;
$font-weight-headings: 500; $font-weight-headings: 700;
$line-height-headings: 1.1; $line-height-headings: 1.1;
$color-headings: $brand-main; $color-headings: $brand-main;
@ -81,7 +81,7 @@ $spacer: ($font-size-base * $line-height);
$padding-base-vertical: 0.75rem; $padding-base-vertical: 0.75rem;
$padding-base-horizontal: 1.25rem; $padding-base-horizontal: 1.25rem;
$border-radius: 3px; $border-radius: 0.25rem;
// Code // Code
///////////////////////////////////// /////////////////////////////////////

View File

@ -26,10 +26,7 @@ body {
line-height: $line-height; line-height: $line-height;
color: $text-color; color: $text-color;
text-rendering: optimizeLegibility; text-rendering: optimizeLegibility;
letter-spacing: -0.01em;
font-feature-settings: 'liga', 'kern'; font-feature-settings: 'liga', 'kern';
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
min-height: 100vh; min-height: 100vh;
transition: background 0.4s $easing; transition: background 0.4s $easing;
background: $body-background-color; background: $body-background-color;
@ -105,20 +102,6 @@ a {
// Headings // Headings
///////////////////////////////////// /////////////////////////////////////
h1,
h2 {
margin-top: $spacer * $line-height;
margin-bottom: $spacer * 2;
}
h3,
h4,
h5,
h6 {
margin-top: $spacer * $line-height;
margin-bottom: $spacer;
}
h1 { h1 {
font-size: $font-size-h2; font-size: $font-size-h2;
@ -128,8 +111,6 @@ h1 {
} }
h2 { h2 {
@include heading-band();
font-size: $font-size-h3; font-size: $font-size-h3;
@media (min-width: $screen-xs) { @media (min-width: $screen-xs) {
@ -174,7 +155,11 @@ h6 {
font-family: $font-family-headings; font-family: $font-family-headings;
line-height: $line-height-headings; line-height: $line-height-headings;
font-weight: $font-weight-headings; font-weight: $font-weight-headings;
letter-spacing: -0.02em; letter-spacing: -0.01em;
margin-top: $spacer * $line-height;
margin-bottom: $spacer;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
// stylelint-disable no-descending-specificity // stylelint-disable no-descending-specificity
&, &,
@ -376,4 +361,3 @@ blockquote {
@import 'code'; @import 'code';
@import 'buttons'; @import 'buttons';
@import 'alerts'; @import 'alerts';
@import 'content';

View File

@ -3,7 +3,7 @@ import { Helmet } from 'react-helmet'
import SEO from '../components/atoms/SEO' import SEO from '../components/atoms/SEO'
import Layout from '../components/Layout' import Layout from '../components/Layout'
import styles from './Page.module.scss' import styles from './Page.module.scss'
import { PostMetadata } from '../@types/PostMetadata' import { Post } from '../@types/Post'
export default function Page({ export default function Page({
title, title,
@ -16,7 +16,7 @@ export default function Page({
children: any children: any
section?: string section?: string
location?: Location location?: Location
post?: PostMetadata post?: Post
}) { }) {
return ( return (
<> <>

View File

@ -1,26 +0,0 @@
@import 'variables';
@import 'mixins';
.hentry {
width: 100%;
padding-top: $spacer;
padding-bottom: $spacer * 3;
> a {
display: block;
}
&:only-child {
padding-bottom: $spacer;
}
}
.postImageWrap {
@include breakoutviewport();
figure {
max-width: none;
margin-top: $spacer * 1.5;
margin-bottom: 0;
}
}

View File

@ -1,5 +1,5 @@
import React, { useState } from 'react' import React, { useState } from 'react'
import ModalThanks from '../molecules/ModalThanks' import ModalThanks from '../../components/organisms/ModalThanks'
import styles from './PostActions.module.scss' import styles from './PostActions.module.scss'
import { ReactComponent as Twitter } from '../../images/twitter.svg' import { ReactComponent as Twitter } from '../../images/twitter.svg'

View File

@ -1,9 +1,9 @@
import React from 'react' import React from 'react'
import Changelog from '../atoms/Changelog' import Changelog from '../../components/atoms/Changelog'
import { PostMetadata } from '../../@types/PostMetadata' import { Post } from '../../@types/Post'
// Remove lead paragraph from content // Remove lead paragraph from content
const PostContent = ({ post }: { post: PostMetadata }) => { const PostContent = ({ post }: { post: Post }) => {
const separator = '<!-- more -->' const separator = '<!-- more -->'
const changelog = post.frontmatter.changelog const changelog = post.frontmatter.changelog

View File

@ -1,7 +1,7 @@
@import 'variables'; @import 'variables';
@import 'mixins'; @import 'mixins';
.postImageTitle { .imageTitle {
transition: 0.1s ease-out; transition: 0.1s ease-out;
font-size: $font-size-h3; font-size: $font-size-h3;
font-family: $font-family-headings; font-family: $font-family-headings;
@ -9,7 +9,6 @@
font-weight: $font-weight-headings; font-weight: $font-weight-headings;
font-style: normal; font-style: normal;
text-align: left; text-align: left;
letter-spacing: -0.02em;
margin: 0; margin: 0;
position: absolute; position: absolute;
top: 10%; top: 10%;
@ -22,7 +21,7 @@
transform: translate3d(0, -20px, 0); transform: translate3d(0, -20px, 0);
} }
.postImage { .image {
display: block; display: block;
a & { a & {
@ -31,7 +30,7 @@
} }
a:hover & { a:hover & {
.postImageTitle { .imageTitle {
opacity: 1; opacity: 1;
transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0);
} }

View File

@ -0,0 +1,13 @@
import React from 'react'
import { Image } from '../../components/atoms/Image'
import styles from './PostImage.module.scss'
import { ImageProps } from '../../@types/Image'
const PostImage = ({ title, fluid, fixed, alt, original }: ImageProps) => (
<figure className={styles.image} data-original={original && original.src}>
<Image fluid={fluid} fixed={fixed} alt={alt} />
{title && <figcaption className={styles.imageTitle}>{title}</figcaption>}
</figure>
)
export default PostImage

View File

@ -1,10 +1,10 @@
import React from 'react' import React from 'react'
import styles from './PostLead.module.scss' import styles from './PostLead.module.scss'
import { PostMetadata } from '../../@types/PostMetadata' import { Post } from '../../@types/Post'
// Extract lead paragraph from content // Extract lead paragraph from content
// Grab everything before more tag, or just first paragraph // Grab everything before more tag, or just first paragraph
const PostLead = ({ post, index }: { post: PostMetadata; index?: boolean }) => { const PostLead = ({ post, index }: { post: Post; index?: boolean }) => {
let lead let lead
const content = post.html const content = post.html
const separator = '<!-- more -->' const separator = '<!-- more -->'

View File

@ -1,12 +1,12 @@
import React from 'react' import React from 'react'
import { Link } from 'gatsby' import { Link } from 'gatsby'
import slugify from 'slugify' import slugify from 'slugify'
import Time from '../atoms/Time' import Time from '../../components/atoms/Time'
import { useSiteMetadata } from '../../hooks/use-site-metadata' import { useSiteMetadata } from '../../hooks/use-site-metadata'
import styles from './PostMeta.module.scss' import styles from './PostMeta.module.scss'
import { PostMetadata } from '../../@types/PostMetadata' import { Post } from '../../@types/Post'
export default function PostMeta({ post }: { post: PostMetadata }) { export default function PostMeta({ post }: { post: Post }) {
const siteMeta = useSiteMetadata() const siteMeta = useSiteMetadata()
const { author, updated, tags, type } = post.frontmatter const { author, updated, tags, type } = post.frontmatter
const { date } = post.fields const { date } = post.fields

View File

@ -1,14 +1,14 @@
import React from 'react' import React from 'react'
import { Link } from 'gatsby' import { Link } from 'gatsby'
import Image from '../atoms/Image' import { Image } from '../../components/atoms/Image'
import styles from './PostTeaser.module.scss' import styles from './PostTeaser.module.scss'
import { PostMetadata } from '../../@types/PostMetadata' import { Post } from '../../@types/Post'
export default function PostTeaser({ export default function PostTeaser({
post, post,
toggleSearch toggleSearch
}: { }: {
post: PostMetadata post: Post
toggleSearch?: () => void toggleSearch?: () => void
}) { }) {
const { image, title } = post.frontmatter const { image, title } = post.frontmatter

View File

@ -0,0 +1,63 @@
@import 'variables';
@import 'mixins';
.hentry {
width: 100%;
padding-top: $spacer;
padding-bottom: $spacer * 3;
> a {
display: block;
}
&:only-child {
padding-bottom: $spacer;
}
.gatsby-resp-image-figure,
.gatsby-resp-image-wrapper {
margin-bottom: $spacer;
}
:global(.anchor) {
margin-top: $spacer / 3;
font-size: $font-size-large;
color: $brand-grey-light;
&:hover,
&:focus {
color: $link-color;
}
span {
transition: opacity 0.2s ease-out;
}
}
h1,
h2,
h3,
h4,
h5,
h6 {
:global(.anchor) span {
opacity: 0;
}
&:hover {
:global(.anchor) span {
opacity: 1;
}
}
}
}
.imageWrap {
@include breakoutviewport();
figure {
max-width: none;
margin-top: $spacer * 1.5;
margin-bottom: 0;
}
}

View File

@ -1,19 +1,19 @@
import React from 'react' import React from 'react'
import { Helmet } from 'react-helmet' import { Helmet } from 'react-helmet'
import { graphql } from 'gatsby' import { graphql } from 'gatsby'
import Layout from '../components/Layout' import Layout from '../../components/Layout'
import PostImage from '../components/Post/PostImage' import PostImage from './PostImage'
import PostTitle from '../components/Post/PostTitle' import PostTitle from './PostTitle'
import PostLead from '../components/Post/PostLead' import PostLead from './PostLead'
import PostContent from '../components/Post/PostContent' import PostContent from './PostContent'
import PostActions from '../components/Post/PostActions' import PostActions from './PostActions'
import PostLinkActions from '../components/Post/PostLinkActions' import PostLinkActions from './PostLinkActions'
import SEO from '../components/atoms/SEO' import SEO from '../../components/atoms/SEO'
import PostMeta from '../components/Post/PostMeta' import PostMeta from './PostMeta'
import Exif from '../components/atoms/Exif' import Exif from '../../components/atoms/Exif'
import RelatedPosts from '../components/molecules/RelatedPosts' import RelatedPosts from '../../components/molecules/RelatedPosts'
import styles from './Post.module.scss' import styles from './index.module.scss'
import { PostMetadata } from '../@types/PostMetadata' import { Post as PostMetadata } from '../../@types/Post'
export default function Post({ export default function Post({
data, data,
@ -40,8 +40,12 @@ export default function Post({
{type === 'post' && <PostLead post={post} />} {type === 'post' && <PostLead post={post} />}
{type === 'photo' && <PostContent post={post} />} {type === 'photo' && <PostContent post={post} />}
{image && ( {image && (
<div className={styles.postImageWrap}> <div className={styles.imageWrap}>
<PostImage fluid={image.childImageSharp.fluid} alt={title} /> <PostImage
fluid={image.childImageSharp.fluid}
alt={title}
original={image.childImageSharp.original}
/>
</div> </div>
)} )}
{image && image.fields && <Exif exif={image.fields.exif} />} {image && image.fields && <Exif exif={image.fields.exif} />}

View File

@ -9,28 +9,13 @@
padding-top: $spacer * 2; padding-top: $spacer * 2;
padding-bottom: $spacer * 2; padding-bottom: $spacer * 2;
@media (min-width: $screen-sm) {
padding-top: $spacer * 3;
padding-bottom: $spacer * 3;
&:first-of-type {
padding-top: $spacer * 4;
}
}
:global(.gatsby-image-wrapper) { :global(.gatsby-image-wrapper) {
max-height: 100vh; max-height: 100vh;
} }
} }
.archiveTitle { .archiveTitle {
@include heading-band();
font-size: $font-size-h3; font-size: $font-size-h3;
margin-top: 0; margin-top: 0;
margin-bottom: 0; margin-bottom: 0;
@media (min-width: $screen-md) {
margin-left: -117%;
}
} }

View File

@ -1,25 +1,25 @@
import React from 'react' import React from 'react'
import { Link, graphql } from 'gatsby' import { Link, graphql } from 'gatsby'
import Layout from '../components/Layout' import Layout from '../components/Layout'
import PostImage from '../components/Post/PostImage' import PostImage from './Post/PostImage'
import PostTitle from '../components/Post/PostTitle' import PostTitle from './Post/PostTitle'
import PostLead from '../components/Post/PostLead' import PostLead from './Post/PostLead'
import PostContent from '../components/Post/PostContent' import PostContent from './Post/PostContent'
import PostMore from '../components/Post/PostMore' import PostMore from './Post/PostMore'
import PostLinkActions from '../components/Post/PostLinkActions' import PostLinkActions from './Post/PostLinkActions'
import SEO from '../components/atoms/SEO' import SEO from '../components/atoms/SEO'
import Pagination from '../components/molecules/Pagination' import Pagination from '../components/molecules/Pagination'
import Featured from '../components/molecules/Featured' import Featured from '../components/molecules/Featured'
import styles from './Posts.module.scss' import styles from './Posts.module.scss'
import stylesPost from './Post.module.scss' import stylesPost from './Post/index.module.scss'
import { PostMetadata } from '../@types/PostMetadata' import { Post } from '../@types/Post'
export default function Posts({ export default function Posts({
data, data,
location, location,
pageContext pageContext
}: { }: {
data: { allMarkdownRemark: { edges: [{ node: PostMetadata }] } } data: { allMarkdownRemark: { edges: [{ node: Post }] } }
location: Location location: Location
pageContext: { pageContext: {
tag: string tag: string
@ -31,7 +31,7 @@ export default function Posts({
const edges = data.allMarkdownRemark.edges const edges = data.allMarkdownRemark.edges
const { tag, currentPageNumber, numPages, nextPage } = pageContext const { tag, currentPageNumber, numPages, nextPage } = pageContext
const PostsList = edges.map(({ node }: { node: PostMetadata }) => { const PostsList = edges.map(({ node }: { node: Post }) => {
const { type, linkurl, title, image } = node.frontmatter const { type, linkurl, title, image } = node.frontmatter
const { slug } = node.fields const { slug } = node.fields
@ -43,11 +43,12 @@ export default function Posts({
{image && ( {image && (
<Link to={slug} title={title}> <Link to={slug} title={title}>
<div className={stylesPost.postImageWrap}> <div className={stylesPost.imageWrap}>
<PostImage <PostImage
title={type === 'photo' ? title : null} title={type === 'photo' ? title : null}
fluid={image.childImageSharp.fluid} fluid={image.childImageSharp.fluid}
alt={title} alt={title}
original={image.childImageSharp.original}
/> />
</div> </div>
</Link> </Link>