-
-
Notifications
You must be signed in to change notification settings - Fork 24
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement blog post grid and card components, GraphQL nodes and queries
The last remaining main page is `/blog` which presents an overview of Nord's blog posts in a three-column grid of card components sorted descending by their publish date. Each card consists of an cover image together with the title of the post. The latest post spans over two columns at the top for a nice visual structure and better recognizability. While a one-column card uses a cover image the latest post will use a "banner" that will either be the same image with a larger width, a variant of it or a completly different one. A blog post itself makes use of the MDX features and the custom MDX components mentioned in the paragraph above. To simplify the usage of the "cover" and "banner" image they are be processed with Gatsby's `onCreateNode` (1) API in combination with Gatsby's `mapping` configuration feature (2). This allows to map the paths to the images to a `File` node that will then be handled by the Gatsby image processing plugin workflow (3) also documented in the commit about image handling. Another required node is the `heroImage` field that queries for a `hero.(png|jpg|jpeg)` image that is used as the hero of a blog post. To allow to also use videos in blog posts or even as header a custom `Video` MDX component has been implemented including the optional `heroVideo` and `heroVideoPoster` GraphQL node fields. All together that results in the following required and optional images/videos mapped to specific node fields with reserved file names per blog post directory for simple usage via GraphQL queries: - `bannerImage` <-> `banner.(png|jpg|jpeg)` - The required banner image of a blog post card (used when currently the latest two-column wide post placed on top of the grid). - `coverImage` <-> `cover.(png|jpg|jpeg)` - The required cover image of a one-column blog post. - `heroImage` <-> `hero.(png|jpg|jpeg)` - The required hero image of a blog post. - `heroVideo` <-> `hero.(mp4|webm)` - The optional hero video of a blog post. - `heroVideoPoster` <-> `heroposter.(png|jpg|jpeg)` - The optional poster image of a blog post `heroVideo`. >>> Known Problems To prevent the `unknwon field` GraphQL error during build time (4) (e.g. when there are no blog posts yet) a "dummy"/"placeholder" blog post and docs page will be created. Anyway, this will be removed as soon as there is finally the first blog post and docs page. Later on the project will migrate to the shiny new schema customization API (5). References: (1) https://www.gatsbyjs.org/docs/node-apis/#onCreateNode (2) https://www.gatsbyjs.org/docs/gatsby-config/#mapping-node-types (3) https://www.gatsbyjs.org/docs/working-with-images (4) gatsbyjs/gatsby#3344 (5) https://www.gatsbyjs.org/blog/2019-03-04-new-schema-customization GH-129
- Loading branch information
1 parent
f2e213a
commit 6d48c68
Showing
30 changed files
with
633 additions
and
86 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Empty file.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,7 @@ | ||
export const frontmatter = { | ||
contentImages: ["./placeholder.png"], | ||
title: "GraphQL query error draft stub", | ||
introduction: "This file must be kept to prevent GraphQL queries to fail when no blog posts are in the filesystem.", | ||
heroImage: "./placeholder.png", | ||
publishTime: "00:00:00+0000", | ||
coverTitleColor: "", | ||
draft: true | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
71 changes: 71 additions & 0 deletions
71
src/components/organisms/page/blog/SectionBlogPostsCardGrid/SectionBlogPostsCardGrid.jsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
/* | ||
* Copyright (C) 2018-present Arctic Ice Studio <[email protected]> | ||
* Copyright (C) 2018-present Sven Greb <[email protected]> | ||
* | ||
* Project: Nord Docs | ||
* Repository: https://github.com/arcticicestudio/nord-docs | ||
* License: MIT | ||
*/ | ||
|
||
import React from "react"; | ||
import PropTypes from "prop-types"; | ||
|
||
import { contentBlogPostPropTypes } from "data/graphql/fragmentPropTypes"; | ||
import { WaveFooter } from "atoms/core/vectors/divider"; | ||
import Section, { Content } from "containers/core/Section"; | ||
import EmptyState from "molecules/core/EmptyState"; | ||
|
||
import { BlogPostCard, Grid } from "./styled"; | ||
import { emptyStateIllustrationStyles } from "../../shared/styles"; | ||
|
||
/** | ||
* The component that represents the landing section of the blog posts page. | ||
* | ||
* @author Arctic Ice Studio <[email protected]> | ||
* @author Sven Greb <[email protected]> | ||
* @since 0.3.0 | ||
*/ | ||
const SectionBlogPostsCardGrid = ({ blogPosts, ...passProps }) => ( | ||
<Section {...passProps}> | ||
<Content centered> | ||
{blogPosts.length ? ( | ||
<Grid> | ||
{blogPosts.map( | ||
( | ||
{ frontmatter: { title, coverTitleColor }, fields: { bannerImage, coverImage, slugParentRoute, slug } }, | ||
idx | ||
) => ( | ||
<BlogPostCard | ||
key={title} | ||
blogPostUrl={`${slugParentRoute}${slug}`} | ||
coverTitleColor={coverTitleColor} | ||
fluid={idx === 0 ? bannerImage?.childImageSharp?.fluid : coverImage?.childImageSharp?.fluid} | ||
large={idx === 0} | ||
single={blogPosts.length === 1} | ||
> | ||
{title} | ||
</BlogPostCard> | ||
) | ||
)} | ||
</Grid> | ||
) : ( | ||
<EmptyState | ||
headline="Oh, there's nothing here yet" | ||
illustrationStyles={emptyStateIllustrationStyles} | ||
subline="Please check back later, we're working hard on this page!" | ||
/> | ||
)} | ||
</Content> | ||
<WaveFooter /> | ||
</Section> | ||
); | ||
|
||
SectionBlogPostsCardGrid.propTypes = { | ||
blogPosts: PropTypes.arrayOf( | ||
PropTypes.shape({ | ||
...contentBlogPostPropTypes | ||
}) | ||
).isRequired | ||
}; | ||
|
||
export default SectionBlogPostsCardGrid; |
10 changes: 10 additions & 0 deletions
10
src/components/organisms/page/blog/SectionBlogPostsCardGrid/index.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
/* | ||
* Copyright (C) 2018-present Arctic Ice Studio <[email protected]> | ||
* Copyright (C) 2018-present Sven Greb <[email protected]> | ||
* | ||
* Project: Nord Docs | ||
* Repository: https://github.com/arcticicestudio/nord-docs | ||
* License: MIT | ||
*/ | ||
|
||
export { default } from "./SectionBlogPostsCardGrid"; |
54 changes: 54 additions & 0 deletions
54
...ponents/organisms/page/blog/SectionBlogPostsCardGrid/styled/BlogPostCard/BlogPostCard.jsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
/* | ||
* Copyright (C) 2018-present Arctic Ice Studio <[email protected]> | ||
* Copyright (C) 2018-present Sven Greb <[email protected]> | ||
* | ||
* Project: Nord Docs | ||
* Repository: https://github.com/arcticicestudio/nord-docs | ||
* License: MIT | ||
*/ | ||
|
||
import React from "react"; | ||
import PropTypes from "prop-types"; | ||
|
||
import { contentMdxImageFluidPropTypes } from "data/graphql/fragmentPropTypes"; | ||
import { A } from "atoms/core/html-elements"; | ||
|
||
import Card from "./Card"; | ||
import Title from "./Title"; | ||
import Image from "./Image"; | ||
import TitleBox from "./TitleBox"; | ||
|
||
/** | ||
* The card component to represent a blog post. | ||
* | ||
* @author Arctic Ice Studio <[email protected]> | ||
* @author Sven Greb <[email protected]> | ||
* @since 0.10.0 | ||
*/ | ||
const BlogPostCard = ({ blogPostUrl, children, coverTitleColor, fluid, large, single, ...passProps }) => ( | ||
<Card large={large} single={single} {...passProps}> | ||
<A to={blogPostUrl}> | ||
<Image fluid={fluid} /> | ||
<TitleBox> | ||
<Title coverTitleColor={coverTitleColor}>{children}</Title> | ||
</TitleBox> | ||
</A> | ||
</Card> | ||
); | ||
|
||
BlogPostCard.propTypes = { | ||
blogPostUrl: PropTypes.string.isRequired, | ||
children: PropTypes.node.isRequired, | ||
coverTitleColor: PropTypes.string, | ||
fluid: PropTypes.shape({ ...contentMdxImageFluidPropTypes }).isRequired, | ||
large: PropTypes.bool, | ||
single: PropTypes.bool | ||
}; | ||
|
||
BlogPostCard.defaultProps = { | ||
coverTitleColor: "", | ||
large: false, | ||
single: false | ||
}; | ||
|
||
export default BlogPostCard; |
42 changes: 42 additions & 0 deletions
42
src/components/organisms/page/blog/SectionBlogPostsCardGrid/styled/BlogPostCard/Card.jsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
/* | ||
* Copyright (C) 2018-present Arctic Ice Studio <[email protected]> | ||
* Copyright (C) 2018-present Sven Greb <[email protected]> | ||
* | ||
* Project: Nord Docs | ||
* Repository: https://github.com/arcticicestudio/nord-docs | ||
* License: MIT | ||
*/ | ||
|
||
import styled from "styled-components"; | ||
|
||
import { | ||
mixinDropShadowAmbientLight, | ||
mixinDropShadowAmbientLightHover, | ||
mixinDropShadowDirectLight, | ||
mixinDropShadowDirectLightHover, | ||
transitionThemedModeSwitch | ||
} from "styles/shared"; | ||
|
||
/** | ||
* The styled card component to represent a blog post. | ||
* | ||
* @author Arctic Ice Studio <[email protected]> | ||
* @author Sven Greb <[email protected]> | ||
* @since 0.10.0 | ||
*/ | ||
const Card = styled.article` | ||
position: relative; | ||
border-radius: 12px; | ||
box-shadow: ${mixinDropShadowDirectLight()}, ${mixinDropShadowAmbientLight()}; | ||
transition: ${transitionThemedModeSwitch("box-shadow")}, ${transitionThemedModeSwitch("background-color")}; | ||
&:hover { | ||
box-shadow: ${mixinDropShadowDirectLightHover()}, ${mixinDropShadowAmbientLightHover()}; | ||
} | ||
${({ theme }) => theme.media.tabletPortrait` | ||
grid-column: ${({ large, single }) => large && `auto/span ${single ? 3 : 2}`}; | ||
`}; | ||
`; | ||
|
||
export default Card; |
34 changes: 34 additions & 0 deletions
34
src/components/organisms/page/blog/SectionBlogPostsCardGrid/styled/BlogPostCard/Image.jsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
/* | ||
* Copyright (C) 2018-present Arctic Ice Studio <[email protected]> | ||
* Copyright (C) 2018-present Sven Greb <[email protected]> | ||
* | ||
* Project: Nord Docs | ||
* Repository: https://github.com/arcticicestudio/nord-docs | ||
* License: MIT | ||
*/ | ||
|
||
import styled from "styled-components"; | ||
import GatsbyImage from "gatsby-image"; | ||
|
||
import { BLOG_POST_IMAGE_MIN_HEIGHT } from "config/internal/constants"; | ||
import { transitionThemedModeSwitch } from "styles/shared"; | ||
|
||
/** | ||
* An styled Gatsby image. | ||
* | ||
* @author Arctic Ice Studio <[email protected]> | ||
* @author Sven Greb <[email protected]> | ||
* @since 0.10.0 | ||
* @see https://www.gatsbyjs.org/docs/working-with-images | ||
*/ | ||
const Image = styled(GatsbyImage)` | ||
min-height: ${BLOG_POST_IMAGE_MIN_HEIGHT / 2}px; | ||
max-height: ${BLOG_POST_IMAGE_MIN_HEIGHT / 2}px; | ||
border-radius: 12px; | ||
overflow: hidden; | ||
transition: ${transitionThemedModeSwitch("box-shadow")}; | ||
user-select: none; | ||
pointer-events: none; | ||
`; | ||
|
||
export default Image; |
Oops, something went wrong.