diff --git a/gatsby-node.js b/gatsby-node.js index e4e28761..0088e19e 100644 --- a/gatsby-node.js +++ b/gatsby-node.js @@ -18,7 +18,7 @@ exports.createPages = async ({ graphql, actions }) => { case "eotm": return path.resolve("lib/ui/templates/EmojiTpl.js"); case "about": - return path.resolve("lib/ui/templates/AboutTpl.js"); + return path.resolve("lib/ui/templates/AboutTpl.tsx"); case "home": return path.resolve("lib/ui/templates/HomeTpl.js"); case "people": @@ -94,7 +94,7 @@ exports.createPages = async ({ graphql, actions }) => { }, { src: posts, - component: path.resolve("lib/ui/templates/BlogPostTpl.js"), + component: path.resolve("lib/ui/templates/BlogPostTpl.tsx"), prefix: "tldr" }, { diff --git a/lib/gatsby-types.d.ts b/lib/gatsby-types.d.ts index 23e3c778..f180b7f8 100644 --- a/lib/gatsby-types.d.ts +++ b/lib/gatsby-types.d.ts @@ -3083,12 +3083,12 @@ type WebPOptions = { readonly quality: InputMaybe; }; -type AboutTplQueryQueryVariables = Exact<{ +type AboutTplQueryVariables = Exact<{ uid: Scalars['String']; }>; -type AboutTplQueryQuery = { readonly markdownRemark: { readonly html: string | null, readonly frontmatter: { readonly uid: string | null, readonly title: string | null, readonly heading: string | null, readonly subheading: string | null } | null } | null }; +type AboutTplQuery = { readonly markdownRemark: { readonly html: string | null, readonly frontmatter: { readonly uid: string | null, readonly title: string | null, readonly heading: string | null, readonly subheading: string | null } | null } | null }; type BlogPostsByUIDQueryVariables = Exact<{ uid: Scalars['String']; diff --git a/lib/ui/components/tiles/Tile.tsx b/lib/ui/components/tiles/Tile.tsx index 62994451..9235fd10 100644 --- a/lib/ui/components/tiles/Tile.tsx +++ b/lib/ui/components/tiles/Tile.tsx @@ -22,7 +22,7 @@ const Element = styled.div` color: ${({ theme }) => theme.titleColor}; } ${({ onClick, href, theme, to }) => - (onClick || href || to) + onClick || href || to ? ` transition: box-shadow ${time.s}, transform ${time.s}; &:hover { @@ -32,18 +32,26 @@ const Element = styled.div` : ``}; `; -interface TileProps { - as?: C +interface TileProps + extends React.PropsWithChildren { + as?: C; space: SpaceValue; + // TODO: add `to` and `href` props, but only when `as` is Link or `a` } -const Tile = ({ space, ...props }: TileProps) => ( +const Tile = ({ + space, + children, + ...props +}: TileProps) => ( {({ BIFHEX }) => ( - + + {children} + )} diff --git a/lib/ui/partials/Body.tsx b/lib/ui/partials/Body.tsx index b9614684..3d95b91b 100644 --- a/lib/ui/partials/Body.tsx +++ b/lib/ui/partials/Body.tsx @@ -9,7 +9,11 @@ const BodyEl = styled.section` color: ${({ theme }) => theme.color}; `; -const Body: React.FC = ({ children, ...props }) => ( +interface BodyProps extends React.PropsWithChildren { + style?: React.CSSProperties; +} + +const Body: React.FC = ({ children, style }) => ( {({ BIFHEX }) => ( = ({ children, ...props }) => ( decor: BIFHEX, }} > - {children} + {children} )} diff --git a/lib/ui/templates/AboutTpl.js b/lib/ui/templates/AboutTpl.js deleted file mode 100644 index eacdbc2a..00000000 --- a/lib/ui/templates/AboutTpl.js +++ /dev/null @@ -1,59 +0,0 @@ -import { graphql } from "gatsby"; -import { object, shape } from "prop-types"; -import React, { Component } from "react"; - -import { Copy, Tile } from "ui/components"; -import { Body, Header, Helmet, Layout } from "ui/partials"; - -export default class AboutTpl extends Component { - constructor(props) { - super(props); - this.state = {}; - } - - render() { - const { frontmatter, html } = this.props.data.markdownRemark; - return ( - <> - - -
-

{frontmatter.heading}

-

{frontmatter.subheading}

-
- - - - - -
- - ); - } -} - -AboutTpl.propTypes = { - data: shape({ - markdownRemark: object.isRequired - }).isRequired -}; - -export const pageQuery = graphql` - query AboutTplQuery($uid: String!) { - markdownRemark(frontmatter: { uid: { eq: $uid } }) { - html - frontmatter { - uid - title - heading - subheading - } - } - } -`; diff --git a/lib/ui/templates/AboutTpl.tsx b/lib/ui/templates/AboutTpl.tsx new file mode 100644 index 00000000..349ac36e --- /dev/null +++ b/lib/ui/templates/AboutTpl.tsx @@ -0,0 +1,48 @@ +import { graphql, type PageProps } from "gatsby"; +import React from "react"; + +import { Copy, Tile } from "ui/components"; +import { Body, Header, Helmet, Layout } from "ui/partials"; + +const AboutTpl = ({ data, ...props }: PageProps) => { + const { frontmatter, html } = data.markdownRemark ?? {}; + + return ( + <> + + +
+

{frontmatter?.heading ?? ""}

+

{frontmatter?.subheading ?? ""}

+
+ + + + + +
+ + ); +}; + +export default AboutTpl; + +export const pageQuery = graphql` + query AboutTpl($uid: String!) { + markdownRemark(frontmatter: { uid: { eq: $uid } }) { + html + frontmatter { + uid + title + heading + subheading + } + } + } +`; diff --git a/lib/ui/templates/BlogPostTpl.js b/lib/ui/templates/BlogPostTpl.js deleted file mode 100644 index ffca2176..00000000 --- a/lib/ui/templates/BlogPostTpl.js +++ /dev/null @@ -1,85 +0,0 @@ -import { graphql } from "gatsby"; -import { object, shape } from "prop-types"; -import React, { Component } from "react"; -import { GatsbyImage } from "gatsby-plugin-image"; - -import { Body, Header, Helmet, Layout } from "ui/partials"; -import { Copy, Tile } from "ui/components"; - -export default class BlogPostTpl extends Component { - constructor(props) { - super(props); - const readingTime = Math.random() * 300; - if (typeof window !== "undefined") { - this.tick = this.tick.bind(this); - } - this.state = { - readingTime - }; - } - - tick() { - this.setState(prevState => ({ - readingTime: prevState.readingTime + Math.random() * 15 - 4 - })); - } - - render() { - const blogPost = this.props.data.markdownRemark; - const { frontmatter, html } = blogPost; - const { cover, date, title } = frontmatter; - return <> - - -
- - Reading Time: {this.state.readingTime.toFixed(2)} seconds - -

{title}

- {date} -
- - {cover ? ( - - ) : null} - - - - -
- ; - } -} - -BlogPostTpl.propTypes = { - data: shape({ - markdownRemark: object.isRequired - }).isRequired -}; - -export const pageQuery = graphql`query BlogPostsByUID($uid: String!) { - markdownRemark(frontmatter: {uid: {eq: $uid}}) { - html - frontmatter { - uid - date(formatString: "MMMM DD, YYYY") - title - cover { - childImageSharp { - gatsbyImageData( - width: 900 - quality: 90 - placeholder: DOMINANT_COLOR - layout: CONSTRAINED - ) - } - } - } - } -}`; diff --git a/lib/ui/templates/BlogPostTpl.tsx b/lib/ui/templates/BlogPostTpl.tsx new file mode 100644 index 00000000..b513742c --- /dev/null +++ b/lib/ui/templates/BlogPostTpl.tsx @@ -0,0 +1,95 @@ +import React, { useEffect, useState } from "react"; +import { graphql, type PageProps } from "gatsby"; +import { GatsbyImage } from "gatsby-plugin-image"; + +import { Body, Header, Helmet, Layout } from "ui/partials"; +import { Copy, Tile } from "ui/components"; + +const BlogPostReadTimer = () => { + const [readingTime, setReadingTime] = useState(Math.random() * 300); + + function tick() { + setReadingTime((previous) => previous + Math.random() * 15 - 4); + } + + useEffect(() => { + let timer: number; + if (typeof window !== "undefined") { + timer = window.setInterval(tick, 3000); + } + + return () => { + if (typeof window !== "undefined") { + window.clearInterval(timer); + } + }; + }, []); + + return {readingTime.toFixed(2)}; +}; + +const BlogPostTpl = ({ + data, + ...props +}: PageProps) => { + const blogPost = data.markdownRemark; + const { frontmatter, html } = blogPost ?? {}; + const { cover, date, title } = frontmatter ?? {}; + + return ( + <> + + +
+ + Reading Time: seconds + +

{title}

+ {date} +
+ + {cover?.childImageSharp?.gatsbyImageData ? ( + + ) : null} + + + + +
+ + ); +}; + +export default BlogPostTpl; + +export const pageQuery = graphql` + query BlogPostsByUID($uid: String!) { + markdownRemark(frontmatter: { uid: { eq: $uid } }) { + html + frontmatter { + uid + date(formatString: "MMMM DD, YYYY") + title + cover { + childImageSharp { + gatsbyImageData( + width: 900 + quality: 90 + placeholder: DOMINANT_COLOR + layout: CONSTRAINED + ) + } + } + } + } + } +`; diff --git a/lib/ui/templates/index.js b/lib/ui/templates/index.ts similarity index 100% rename from lib/ui/templates/index.js rename to lib/ui/templates/index.ts