ScottSpence.com

Scott's Digital Garden.

Chakra UI and Gatsby - Getting Started

Ok, so this is another one of those “let’s use a new CSS-in-JS library on a Gatsby default starter project” post.

In this case it’s Chakra UI, it’s recently gone v1 and I’m keen to use it.

What I’m going to be doing is styling the Gatsby starter default using Chakra UI and chucking in a theme toggle as well.

This will involve swapping out the styles that come with the Gatsby starter default with Chakra UI ones.

The end result I’m aiming for is for it to look the same as before but using Chakra UI in place of the styling it comes with.

You can follow along too, or you can TL;DR for the video.

Pre requisites

The usual notes on development environment, this comes with the presumption you’ll already have a development environment set up and configured. If you don’t have a development environment then you can always use CodeSandbox.io to get up and running with an environment.

In the examples here I’m using Node version 14.13.0.

Here’s some of the dependencies being used in this guide, they’re all latest versions at the time of writing this.

1"@chakra-ui/gatsby-plugin": "^1.0.0",
2"@chakra-ui/icons": "^1.0.1",
3"@chakra-ui/react": "^1.0.1",
4"@emotion/react": "^11.1.1",
5"@emotion/styled": "^11.0.0",
6"framer-motion": "^2.9.4",
7"gatsby": "^2.26.1",
8"react": "^17.0.1",
9"react-dom": "^17.0.1",

Create the thing

Spin up a new Gatsby project with npx:

1npx gatsby new gatsby-chakra-ui

You can install and use the Gatsby CLI if you like, in this instance I’m going npx as I’m not going to need any of the Gatsby CLI functionality.

Wait for that to finish doing it’s thing then change directory to the freshly created gatsby project. Cool, cool, do a quick yarn develop to make sure everything’s installed ok with no issues.

Install the things

Now to install the dependencies needed, there’s a few, the \ here is so that I can display the items that need installing in a nice format:

1yarn add \
2 @chakra-ui/react \
3 @emotion/react \
4 @emotion/styled \
5 framer-motion \
6 @chakra-ui/gatsby-plugin \
7 @chakra-ui/icons

NOTE Don’t forget to add the Chakra UI Gatsby plugin to the Gatsby plugin array, I routinely do this! This note is for me just as much as you dear reader. 😊

I’ll add the plugin to the gatsby-config.js, at the time of writing this plugin name was what’s recommended in the Chakra UI documentation and shouldn’t be confused with the Gatsby documentation.

1plugins: [
2 `@chakra-ui/gatsby-plugin`,
3 // many more plugins 👇

Stop (Ctrl+c) and restart the dev server you’ll notice all the styles are gone, that’s the Chakra UI Gatsby plugin doing it’s thing.

Now that I have all the power of Chakra UI available to me now I’ll remove the import "./layout.css" from the layout.js component. I can also delete the layout.css file as it’s not needed.

Root Wrapper time!

So that I can access the Chakra UI Theme provider throughout the project I’m going to add the <ChakraProvider> as high up in the React component tree as possible.

I can do this by using the Gatsby wrapPageElement API in both the gatsby-browser.ja and the gatsby-ssr.js files.

So I’m not to repeating the same code in both of those files I’m going to create another file, add that in there and import that file into both the gatsby-browser.ja and the gatsby-ssr.js files.

The name and location of this file is unimportant, keep it at the root of the project with the gatsby-browser.ja and the gatsby-ssr.js files or add it to the src folder, doesn’t matter AFAIK.

Create the file, from my terminal I’ll do a touch:

1touch src/woot-wapper.tsx

Yes, I’m using a TypeScript (.tsx) file in a predominantly JavaScript project, you do you, make it a .js file if you like. I’m trying to get more used to using TS in my projects and Gatsby gives TS support out of the box now.

In the root wrapper file I’ll add the Chakra provider and the Layout component.

1import { ChakraProvider } from '@chakra-ui/react'
2import React from 'react'
3import Layout from './components/layout'
4
5export const wrapPageElement = ({ element }) => {
6 return (
7 <ChakraProvider resetCSS>
8 <Layout>{element}</Layout>
9 </ChakraProvider>
10 )
11}

So now there’s no need to import the layout component into each page that is created. I’ll need to remove the layout from component from the 404.js, index.js ,page-2.js and using-typescript.tsx pages.

Finally I’ll need to import the root wrapper into both the gatsby-ssr.js and the gatsby-browser.js files.

1import { wrapPageElement as wrap } from './src/woot-wapper'
2
3export const wrapPageElement = wrap

Theme Toggle

Using the Chakra UI theme provider means that I can use one of the provided hooks to toggle the theme.

I’m going to create a theme toggle component:

1touch src/components/toggle-theme.tsx

And add in some code to toggle the theme:

1import { MoonIcon, SunIcon } from '@chakra-ui/icons'
2import {
3 IconButton,
4 useColorMode,
5 useColorModeValue,
6} from '@chakra-ui/react'
7import React from 'react'
8
9export default function ThemeToggle() {
10 const { toggleColorMode: toggleMode } = useColorMode()
11 const ToggleIcon = useColorModeValue(SunIcon, MoonIcon)
12
13 return (
14 <IconButton
15 icon={<ToggleIcon />}
16 variant="ghost"
17 aria-label="Toggle Theme"
18 onClick={toggleMode}
19 />
20 )
21}

I’ll add this to the header component for now.

Style it with Chakra UI

Ok, now I’ve done the groundwork I can start removing the inline styles in this project, I’ll start with the header component.

I’ll straight up copy pasta the changed code in here, som of these may be a bit long, I’ll shorten them where I can so there’s no code walls.

Style the header

Here’s the component with the inline styles swapped out for Chakra UI styles.

I’ve left out the default export and prop types for brevity.

1import { Box, Heading, Link } from '@chakra-ui/react'
2import { Link as GatsbyLink } from 'gatsby'
3import React from 'react'
4import ThemeToggle from './theme-toggle'
5
6const Header = ({ siteTitle }) => (
7 <Box as="header" background="rebeccapurple" marginBottom="1.45rem">
8 <Box as="div" m="0 auto" maxW="960px" p="1.45rem 1.0875rem">
9 <Heading margin="0">
10 <Link
11 as={GatsbyLink}
12 to="/"
13 color="white"
14 _hover={{ textDecor: 'none' }}
15 >
16 {siteTitle}
17 </Link>
18 </Heading>
19 </Box>
20 <Box as="div" position="fixed" right="20px" top="20px">
21 <ThemeToggle />
22 </Box>
23 </Box>
24)

Notice that the <header> tag and the <div> tags are now both Chakra UI <Box> components?

They’re both using the Chakra UI as prop, this is a feature that allows you to pass an HTML tag or component to be rendered. Pretty neat right?

You’ll also notice that the Chakra UI Link component is being rendered as a Gatsby Link component, I also removed the underline on hover with the _hover prop.

So with that being done it takes the 42 lines that was there previously down to 35 lines of code.

I’ve also added the theme toggle button, not the best way to position it mind you, just for funsies!

Style the layout

Onto the layout component now, same thing here with the <div>, <main> and <footer> tags here.

I’m going to forgo showing the imports export and prop types here again and I’ll add in what’s changes in the render of the component.

1return (
2 <>
3 <Header siteTitle={data.site.siteMetadata?.title || `Title`} />
4 <Box as="div" m="0 auto" maxWidth="960px" p="0 1.0875rem 1.45rem">
5 <Box as="main">{children}</Box>
6 <Box as="footer" marginTop="2rem" fontSize="xl">
7 © {new Date().getFullYear()}, Built with
8 {` `}
9 <Link
10 isExternal
11 textDecor="underline"
12 color="purple.500"
13 href="https://www.gatsbyjs.com"
14 >
15 Gatsby
16 </Link>
17 </Box>
18 </Box>
19 </>
20)

You may notice the addition of the fontSize prop added to the footer, I’ll be using this a bit more when editing the pages.

There’s also additional props for the link component, I added the isExternal prop to indicate that the link is pointing to an external link, textDecor to add the link underline and color to it.

Ok, that’s it for the components, onto the pages now.

Style the 404 page

On the 404 page, I’ve added in a Chakra UI <Heading> and Text components and added the fontSize prop along with with some margin top and bottom on the text component with the my prop.

1import { Heading, Text } from '@chakra-ui/react'
2import React from 'react'
3import SEO from '../components/seo'
4
5const NotFoundPage = () => (
6 <>
7 <SEO title="404: Not found" />
8 <Heading>404: Not Found</Heading>
9 <Text fontSize="xl" my={5}>
10 You just hit a route that doesn&#39;t exist... the sadness.
11 </Text>
12 </>
13)
14
15export default NotFoundPage

Style the Index page

The index page you’ll notice is a bit larger due to the additional props needed for the link components.

1const IndexPage = () => (
2 <>
3 <SEO title="Home" />
4 <Heading>Hi people</Heading>
5 <Text fontSize="xl" my={5}>
6 Welcome to your new Gatsby site.
7 </Text>
8 <Text fontSize="xl" my={5}>
9 Now go build something great.
10 </Text>
11 <Box as="div" maxWidth="300px" marginBottom="1.45rem">
12 <Image />
13 </Box>
14 <Link
15 as={GatsbyLink}
16 textDecor="underline"
17 color="purple.500"
18 fontSize="xl"
19 to="/page-2/"
20 >
21 Go to page 2
22 </Link>
23 <br />
24 <Link
25 as={GatsbyLink}
26 textDecor="underline"
27 color="purple.500"
28 fontSize="xl"
29 to="/using-typescript/"
30 >
31 Go to "Using TypeScript"
32 </Link>
33 </>
34)

Additional props for the link components includes the text, underline and colour props I’ve already used.

Style the Page 2 page

Same as with the index page for styling the Gatsby links with Chakra UI here.

1const SecondPage = () => (
2 <>
3 <SEO title="Page two" />
4 <Heading>Hi from the second page</Heading>
5 <Text fontSize="xl" my={5}>
6 Welcome to page 2
7 </Text>
8 <Link
9 as={GatsbyLink}
10 to="/"
11 color="purple.500"
12 fontSize="xl"
13 textDecor="underline"
14 >
15 Go back to the homepage
16 </Link>
17 </>
18)

Style the Using TypeScript page

Same again with the TypeScript file here, I’ve added in the as prop to refer to the link as a Gatsby link along with the textDecor, color and fontSize props.

I’ve removed the text from this example to reduce the overall size of the code block.

1const UsingTypescript: React.FC<PageProps<DataProps>> = ({
2 data,
3 path,
4}) => (
5 <>
6 <SEO title="Using TypeScript" />
7 <Heading>Gatsby supports TypeScript by default!</Heading>
8 <Text fontSize="xl" my={6}>
9 This means that you can create and write <em>.ts/.tsx</em> files
10 ...
11 </Text>
12 <Link
13 isExternal
14 textDecor="underline"
15 color="purple.500"
16 href="https://www.gatsbyjs.com/docs/typescript/"
17 >
18 documentation about TypeScript
19 </Link>
20 <Link
21 as={GatsbyLink}
22 textDecor="underline"
23 color="purple.500"
24 fontSize="xl"
25 to="/"
26 >
27 Go back to the homepage
28 </Link>
29 </>
30)

Here’s a video detailing the process

Recap and wrap up!

That’s it for this one! To recap what I did:

  • Create a Gatsby starter using npx
  • Add Chakra UI packages
  • Created a theme toggle using the Chakra UI useColorMode hook
  • Swap out inline styles with Chakra UI components

Done!

I’m only beginning to get familiar with Chakra UI so I’ll be writing more about it as I continue to use it.

Thanks for reading 🙏

Please take a look at my other content if you enjoyed this.

Follow me on Twitter or Ask Me Anything on GitHub.

Resources

These are literally all linking to the Chakra UI documentation:

Back to Top