-
-
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
DocsPage
and BlogPost
template components
This includes styled components like `PaperSheet` for a uniform docs design. The `MDXProvider` has been configured to map custom HTML components to default Markdown elements and a wrapper component for doc pages has been implemented to define specific styles like "Inter UI" font family. GH-129
- Loading branch information
1 parent
8dc497e
commit 7344faa
Showing
7 changed files
with
500 additions
and
0 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
/* | ||
* 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 MDXRenderer from "gatsby-mdx/mdx-renderer"; | ||
import { MDXProvider } from "@mdx-js/tag"; | ||
import { graphql } from "gatsby"; | ||
import camelCase from "camelcase"; | ||
|
||
import BaseLayout from "layouts/core/BaseLayout"; | ||
import Section, { Content } from "containers/core/Section"; | ||
|
||
import PageTypoHead from "../shared/PageTypoHead"; | ||
import mappedHtmlElementComponents from "../shared/mappedHtmlElementComponents"; | ||
import { blogPostTemplatePropTypes } from "../shared/propTypes"; | ||
|
||
/** | ||
* A template for blog posts with custom HTML components and injected props that can be used in the MDX document. | ||
* | ||
* @author Arctic Ice Studio <[email protected]> | ||
* @author Sven Greb <[email protected]> | ||
* @since 0.10.0 | ||
* @see https://mdxjs.com | ||
* @see https://github.com/ChristopherBiscardi/gatsby-mdx | ||
* | ||
*/ | ||
const BlogPost = ({ data: { mdx, images }, location: { pathname }, ...passProps }) => { | ||
/* | ||
* Make each image available as image prop in camelcase format consisting of the name and extension of the file. | ||
* Example: "snow-mountain.png" -> "snowMountainPng" | ||
*/ | ||
const blogPostImages = {}; | ||
images?.edges.forEach(({ node }) => { | ||
const { extension, name } = node; | ||
const imageName = camelCase(`${name}.${extension}`); | ||
blogPostImages[imageName] = node.childImageSharp; | ||
}); | ||
|
||
/* | ||
* Shorten the object key path for content image props by deconstructing the "childImageSharp" property. | ||
* The images can then be used by their index: `props.contentImages[0].fluid` | ||
*/ | ||
const blogPostContentImages = []; | ||
if (mdx.frontmatter?.contentImages) { | ||
mdx.frontmatter.contentImages.forEach(({ childImageSharp }) => blogPostContentImages.push(childImageSharp)); | ||
} | ||
|
||
return ( | ||
<BaseLayout pathName={pathname}> | ||
<Section> | ||
<Content as="article" centered> | ||
<PageTypoHead fontScale={9} headline={mdx.frontmatter?.title} subline={mdx.frontmatter?.introduction} /> | ||
<MDXProvider components={mappedHtmlElementComponents}> | ||
<MDXRenderer | ||
contentImages={blogPostContentImages} | ||
heroImage={mdx.frontmatter?.heroImage?.childImageSharp} | ||
images={blogPostImages} | ||
{...passProps} | ||
> | ||
{mdx.code.body} | ||
</MDXRenderer> | ||
</MDXProvider> | ||
</Content> | ||
</Section> | ||
</BaseLayout> | ||
); | ||
}; | ||
|
||
BlogPost.propTypes = blogPostTemplatePropTypes; | ||
|
||
export const pageQuery = graphql` | ||
query($id: String!, $relativeDirectory: String!) { | ||
images: allFile( | ||
filter: { relativeDirectory: { eq: $relativeDirectory }, extension: { regex: "/(png|jpe?g)/" } } | ||
sort: { fields: [name], order: ASC } | ||
) { | ||
edges { | ||
node { | ||
childImageSharp { | ||
...contentMdxDocumentImageFluid | ||
} | ||
extension | ||
name | ||
} | ||
} | ||
} | ||
mdx(id: { eq: $id }) { | ||
code { | ||
body | ||
} | ||
id | ||
...contentBlogPostFrontmatter | ||
} | ||
} | ||
`; | ||
|
||
export default BlogPost; |
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,100 @@ | ||
/* | ||
* 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 MDXRenderer from "gatsby-mdx/mdx-renderer"; | ||
import { MDXProvider } from "@mdx-js/tag"; | ||
import { graphql } from "gatsby"; | ||
import camelCase from "camelcase"; | ||
|
||
import { WaveFooter } from "atoms/core/vectors/divider"; | ||
import BaseLayout from "layouts/core/BaseLayout"; | ||
import Section, { Content } from "containers/core/Section"; | ||
|
||
import mappedHtmlElementComponents from "../shared/mappedHtmlElementComponents"; | ||
import { docsPageTemplatePropTypes } from "../shared/propTypes"; | ||
import PaperSheet from "./styled/PaperSheet"; | ||
import PageTypoHead from "../shared/PageTypoHead"; | ||
|
||
/** | ||
* A template for docs pages with custom HTML components and injected props that can be used in the MDX document. | ||
* | ||
* @author Arctic Ice Studio <[email protected]> | ||
* @author Sven Greb <[email protected]> | ||
* @since 0.10.0 | ||
* @see https://mdxjs.com | ||
* @see https://github.com/ChristopherBiscardi/gatsby-mdx | ||
* | ||
*/ | ||
const DocsPage = ({ data: { mdx, images }, location: { pathname }, ...passProps }) => { | ||
/* | ||
* Make each image available as image prop in camelcase format consisting of the name and extension of the file. | ||
* Example: "snow-mountain.png" -> "snowMountainPng" | ||
*/ | ||
const blogPostImages = {}; | ||
images?.edges.forEach(({ node }) => { | ||
const { extension, name } = node; | ||
const imageName = camelCase(`${name}.${extension}`); | ||
blogPostImages[imageName] = node.childImageSharp; | ||
}); | ||
|
||
/* Shorten the object key path for content image props by deconstructing the "childImageSharp" property. */ | ||
const blogPostContentImages = []; | ||
if (mdx.frontmatter?.contentImages) { | ||
mdx.frontmatter.contentImages.forEach(({ childImageSharp }) => blogPostContentImages.push(childImageSharp)); | ||
} | ||
|
||
return ( | ||
<BaseLayout headerVariant="tertiary" pathName={pathname}> | ||
<Section variant="tertiary"> | ||
<Content as="article" centered> | ||
<MDXProvider components={mappedHtmlElementComponents}> | ||
<PageTypoHead fontScale={6.5} headline={mdx.frontmatter?.title} subline={mdx.frontmatter?.subline} /> | ||
<PaperSheet> | ||
<MDXRenderer contentImages={blogPostContentImages} images={blogPostImages} {...passProps}> | ||
{mdx.code.body} | ||
</MDXRenderer> | ||
</PaperSheet> | ||
</MDXProvider> | ||
</Content> | ||
<WaveFooter /> | ||
</Section> | ||
</BaseLayout> | ||
); | ||
}; | ||
|
||
DocsPage.propTypes = docsPageTemplatePropTypes; | ||
|
||
export const pageQuery = graphql` | ||
query($id: String!, $relativeDirectory: String!) { | ||
images: allFile( | ||
filter: { relativeDirectory: { eq: $relativeDirectory }, extension: { regex: "/(png|jpe?g)/" } } | ||
sort: { fields: [name], order: ASC } | ||
) { | ||
edges { | ||
node { | ||
childImageSharp { | ||
...contentMdxDocumentImageFluid | ||
} | ||
extension | ||
name | ||
} | ||
} | ||
} | ||
mdx(id: { eq: $id }) { | ||
code { | ||
body | ||
} | ||
id | ||
...contentDocsPageFrontmatter | ||
} | ||
} | ||
`; | ||
|
||
export default DocsPage; |
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,50 @@ | ||
/* | ||
* 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 { rgba } from "polished"; | ||
|
||
import { colors, media, motion, themedMode, MODE_BRIGHT_SNOW_FLURRY, MODE_DARK_NIGHT_FROST } from "styles/theme"; | ||
import { baseBackgroundColor } from "containers/core/shared/styles"; | ||
|
||
const dropShadowColorAmbientLight = themedMode({ | ||
[MODE_BRIGHT_SNOW_FLURRY]: rgba(colors.shadow.base[MODE_BRIGHT_SNOW_FLURRY], 0.1), | ||
[MODE_DARK_NIGHT_FROST]: rgba(colors.shadow.base[MODE_DARK_NIGHT_FROST], 0.1) | ||
}); | ||
|
||
const dropShadowColorDirectLight = themedMode({ | ||
[MODE_BRIGHT_SNOW_FLURRY]: rgba(colors.shadow.base[MODE_BRIGHT_SNOW_FLURRY], 0.25), | ||
[MODE_DARK_NIGHT_FROST]: rgba(colors.shadow.base[MODE_DARK_NIGHT_FROST], 0.25) | ||
}); | ||
|
||
/** | ||
* A styled paper sheet component. | ||
* | ||
* @author Arctic Ice Studio <[email protected]> | ||
* @author Sven Greb <[email protected]> | ||
* @since 0.10.0 | ||
*/ | ||
const PaperSheet = styled.div` | ||
background-color: ${baseBackgroundColor}; | ||
overflow: hidden; | ||
width: 100%; | ||
margin: 0 auto; | ||
padding: 0 1em; | ||
border-radius: 8px; | ||
box-shadow: 0 4px 6px ${dropShadowColorDirectLight}, 0 5px 7px ${dropShadowColorAmbientLight}; | ||
transition: box-shadow ${motion.speed.duration.transition.base.themeModeSwitch}ms ease-in-out, | ||
background-color ${motion.speed.duration.transition.base.themeModeSwitch}ms ease-in-out; | ||
${media.phoneLandscape` | ||
max-width: 95%; | ||
padding: 2em 4em; | ||
`}; | ||
`; | ||
|
||
export default PaperSheet; |
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,84 @@ | ||
/* | ||
* 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 styled from "styled-components"; | ||
|
||
import { H1, P } from "atoms/core/html-elements"; | ||
import { colors, media, motion, ms, themedMode, MODE_BRIGHT_SNOW_FLURRY, MODE_DARK_NIGHT_FROST } from "styles/theme"; | ||
|
||
const fontColor = themedMode({ | ||
[MODE_BRIGHT_SNOW_FLURRY]: colors.nord2, | ||
[MODE_DARK_NIGHT_FROST]: colors.font.base[MODE_DARK_NIGHT_FROST] | ||
}); | ||
|
||
const Headline = styled(H1)` | ||
font-size: ${({ fontScale }) => ms(fontScale)}; | ||
color: ${fontColor}; | ||
margin-bottom: 0.8em; | ||
font-weight: 500; | ||
transition: color ${motion.speed.duration.transition.base.themeModeSwitch}ms ease-in-out; | ||
${media.tabletLandscape` | ||
font-size: ${({ fontScale }) => ms(fontScale + 1)}; | ||
`}; | ||
${media.desktop` | ||
font-size: ${({ fontScale }) => ms(fontScale + 2)}; | ||
`}; | ||
`; | ||
|
||
const Subline = styled(P)` | ||
max-width: 80%; | ||
margin: 1em auto; | ||
font-size: ${({ fontScale }) => ms(fontScale / 3.2)}; | ||
${media.tabletLandscape` | ||
max-width: 70%; | ||
`}; | ||
${media.desktop` | ||
max-width: 60%; | ||
`}; | ||
`; | ||
|
||
const Wrapper = styled.div` | ||
max-width: 90%; | ||
text-align: center; | ||
margin: 0 auto 4em auto; | ||
`; | ||
|
||
/** | ||
* A typography header consisting of a large headline and a subline. | ||
* | ||
* @author Arctic Ice Studio <[email protected]> | ||
* @author Sven Greb <[email protected]> | ||
* @since 0.10.0 | ||
*/ | ||
const PageTypoHead = ({ headline, fontScale, subline, ...passProps }) => | ||
headline || subline ? ( | ||
<Wrapper {...passProps}> | ||
{headline && <Headline fontScale={fontScale}>{headline}</Headline>} | ||
{subline && <Subline fontScale={fontScale}>{subline}</Subline>} | ||
</Wrapper> | ||
) : null; | ||
|
||
PageTypoHead.propTypes = { | ||
fontScale: PropTypes.number.isRequired, | ||
headline: PropTypes.string, | ||
subline: PropTypes.string | ||
}; | ||
|
||
PageTypoHead.defaultProps = { | ||
headline: "", | ||
subline: "" | ||
}; | ||
|
||
export default PageTypoHead; |
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,26 @@ | ||
/* | ||
* 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 { typography } from "styles/theme"; | ||
|
||
/** | ||
* A styled component for the `wrapper` mapping of the supported `MDXProvider` tags. | ||
* It is used to override global/inherited styles for docs pages and blog posts. | ||
* | ||
* @author Arctic Ice Studio <[email protected]> | ||
* @author Sven Greb <[email protected]> | ||
* @since 0.10.0 | ||
*/ | ||
const Wrapper = styled.div` | ||
font-family: ${typography.typefaces.straight}; | ||
`; | ||
|
||
export default Wrapper; |
Oops, something went wrong.