DEV Community

Claradev32
Claradev32

Posted on • Originally published at blog.openreplay.com

Creating a theme in a Gatsby application with Stitches

Gatsby is a popular React framework used to build webpages and apps. Its design prioritizes security, scalability, and performance. Gatsby is supported by a large ecosystem, which includes Plugins for integrating services, themes for simple configuration, and Recipes for automating routine tasks. In this tutorial, you'll learn how to create a theme in Gatsby with Stitches.

To get started with this tutorial, ensure you have the following

  • Node.js version 14 or later installed
  • yarn package manager installed.
  • Prior Knowledge of Stitches
  • Prior Knowledge of Gatsby

What is stitches?

Stiches is a React framework that allows you to confidently create and style reusable components. It includes support for other frameworks such as Vue, Svelte, and Vanilla HTML.
Stitches were created to help developers avoid unnecessary prop interpolations at runtime, thereby improving application performance. Let’s start by creating a new Gatsby application.

gatsby new gatsby-site https://github.com/gatsbyjs/gatsby-starter-hello-world
Enter fullscreen mode Exit fullscreen mode

The above command will clone the Gatsby starter application with the folder structure below.

📦gatsby-site
┣ 📂src
┃ ┗ 📂pages
┃ ┃ ┗ 📜index.js
┣ 📂static
┃ ┗ 📜favicon.ico
┣ 📜.gitignore
┣ 📜.prettierignore
┣ 📜.prettierrc
┣ 📜LICENSE
┣ 📜README.md
┣ 📜gatsby-config.js
┣ 📜package-lock.json
┗ 📜package.json

Setup and Configuring Stitches

Now let's configure stitches with your Gatsby application. First, you need to install the Gatsby plugin for styling with Stitches with the command below.

yarn add gatsby-theme-stitches @stitches/react
Enter fullscreen mode Exit fullscreen mode

Once the installation is completed, open the gatsby-config.js file and add Stitches to the array of plugins with the code snippet below.

module.exports = {
  /* Your site config here */
  plugin: ['gatsby-theme-stitches'],
}
Enter fullscreen mode Exit fullscreen mode

At this point, you are ready to start styling your Gatsby application with Stitches. There are two ways around this.

  1. You can choose to create your config by shadowing the gatsby-theme-stitches/src/config module
  2. You can import the properties directly into your application.
import { styled } from 'gatsby-theme-stitches/src/config';
Enter fullscreen mode Exit fullscreen mode

To use the first method, create a gatsby-theme-stitches/config.js file and add the following configurations.

import { createStitches } from '@stitches/react';

// You should exports all properties
export const {
  styled,
  css,
  globalCss,
  keyframes,
  getCssText,
  theme,
  createTheme,
  config,
} = createStitches({
   theme: {
    colors: {
      black500: "hsl(0, 0%, 0%)",
      white500: "hsl(0, 0%, 100%)",
      gray500: "hsl(206,10%,76%)",
      blue500: "hsl(206,100%,50%)",
      purple500: "hsl(252,78%,60%)",
      green500: "hsl(148,60%,60%)",
      red500: "hsl(352,100%,62%)",
    },
    space: {
      1: "5px",
      2: "10px",
      3: "15px",
    },
    fontSizes: {
      1: "12px",
      2: "13px",
      3: "15px",
    },
    fonts: {
      untitled: "Untitled Sans, apple-system, sans-serif",
      mono: "Söhne Mono, menlo, monospace",
    },
    borderRadius: {
      1: "5px",
      2: "10px",
      3: "15px",
    },
    borders: {
      1: "1px solid #ccc",
      2: "2px solid #ccc",
      3: "3px solid #ccc",
      4: "none",
    },
    paddings: {
      1: "5px",
      2: "10px",
      3: "15px",
    },
    margins: {
      1: "5px",
      2: "10px",
      3: "15px",
    },
    widths: {
      1: "100%",
      2: "50%",
      3: "25%",
    },
  },
});
Enter fullscreen mode Exit fullscreen mode

In the above code snippet, you have exported all the available Stitches properties. So You can import and use them. Then we defined the themes for the elements in our application. We'll can use the theme properties to style our elements.

Create and style custom elements.

Now let's go ahead and use Stitches to create the style for the elements we'll use in our Gatsby application. For separation of concern sake, we'll create components folder in the root directory of the project for all the element's styles. In the component folder, create a new file named Button.js and add the code snippets below.

import { styled } from '../../stitches.config';

export const Button = styled("button", {
   // base styles
  display: "block",
  border: "$4",
  borderRadius: "$1",
  color: "$white500",

  variants: {
    size: {
      sm: {
        fontSize: "13px",
        height: "25px",
        paddingRight: "10px",
        paddingLeft: "10px",
      },
      lg: {
        fontSize: "15px",
        height: "35px",
        paddingLeft: "15px",
        paddingRight: "15px",
      },
    },
    bg: {
      primary: {
        backgroundColor: "#2196f3",
        "&:hover": {
          backgroundColor: "#64b5f6",
        },
      },
      secondary: {
        backgroundColor: "#009688",
        "&:hover": {
          backgroundColor: "#4db6ac",
        },
      },
      danger: {
        backgroundColor: "#f44336",
        "&:hover": {
          backgroundColor: "#ef9a9a",
        },
      },
      success: {
        backgroundColor: "#4caf50",
        color: "white",
        "&:hover": {
          backgroundColor: "#a5d6a7",
        },
      },
    },
  },
});
Enter fullscreen mode Exit fullscreen mode

In the above code snippet, we imported the styled properties from Stitches config file, which will allow us to customize the component. We used the properties we defined in our theme to add the base style of the element using the $ symbol followed by the theme properties. Then we used the variants property to define the styling for the background color (bg) and size (size) of the component.
Next, create a Container.js and add the code snippets below.

import { styled } from "@stitches/react";

export const Container = styled("div", {
   // base styles
  display: "flex",
  flexDirection: "column",
  justifyContent: "center",
  padding: "$2",
  backgroundColor: "$white500",

  variants: {
    fd: {
      column: {
        flexDirection: "column",
      },
      row: {
        flexDirection: "row",
      },
    },
    size: {
      sm: {
        width: "100%",
        height: "50px",
      },
      lg: {
        width: "100%",
        height: "60px",
      },
    },
    align: {
      center: {
        alignItems: "center",
      },
      left: {
        alignItems: "flex-start",
      },
      right: {
        alignItems: "flex-end",
      },
    },
  },
});
Enter fullscreen mode Exit fullscreen mode

In the Container component, we base style themes and defined the styling to align and set the size of the container using the varriant property.
Next, create an Image.js file and add the code snippet below.

import { styled } from "@stitches/react"

export const Image = styled("img", {
  display: "block",
  width: "$1",
  height: "auto",
  maxWidth: "100%",
  maxHeight: "100%",
  margin: "0 auto",
  variants: {
    size: {
      sm: {
        width: "50%",
        height: "50%",
        maxWidth: "100%",
        maxHeight: "100%",
        margin: "0 auto",
      },
      lg: {
        width: "100%",
        height: "auto",
        maxWidth: "100%",
        maxHeight: "100%",
        margin: "0 auto",
      },
    },
  },
})
Enter fullscreen mode Exit fullscreen mode

We also defined the styling to have a large and small image, we also defined the style to change the image alignment and we applied the themes to the base styles.

Next, create a Header.js file and add the code snippet below.

import { styled } from "@stitches/react";

export const Header = styled("nav", {
  // base styles
  display: "flex",
  flexDirection: "row",
  justifyContent: "space-between",
  alignItems: "center",
  padding: "$2",
  backgroundColor: "$white500",
  borderBottom: "1px solid #e6e6e6",

  variants: {
    size: {
      sm: {
        width: "100%",
        height: "50px",
      },
      lg: {
        width: "100%",
        height: "60px",
      },
    },
    bg: {
      primary: {
        backgroundColor: "#2196f3",
        "&:hover": {
          backgroundColor: "#64b5f6",
        },
      },
      secondary: {
        backgroundColor: "#009688",
        "&:hover": {
          backgroundColor: "#4db6ac",
        },
      },
      danger: {
        backgroundColor: "#f44336",
        "&:hover": {
          backgroundColor: "#ef9a9a",
        },
      },
      success: {
        backgroundColor: "#4caf50",
        "&:hover": {
          backgroundColor: "#a5d6a7",
        },
      },
    },
  },
});
Enter fullscreen mode Exit fullscreen mode

Next, create a Card.js file and add the code snippets below.

import { styled } from "@stitches/react";

export const Card = styled("div", {
  display: "flex",
  justifyContent: "center",
  flexDirection: "column",
  padding: "$1",
  margin: "$2"

  variants: {
    align: {
      center: {
        alignItems: "center",
      },
      left: {
        alignItems: "flex-start",
      },
      right: {
        alignItems: "flex-end",
      },
    },
    boder: {
        none: { 
            border: "none"
        },
        solid: {
            border: "solid 1px #e6e6e6"
        }
    }
  },
});
Enter fullscreen mode Exit fullscreen mode

Next, a new file Input.js and add the code snippet below.

import { styled } from "@stitches/react";

export const Input = styled("input", {
  display: "block",
  marginBottom: "10px",

  variants: {
    size: {
      sm: {
        fontSize: "13px",
        height: "25px",
        paddingRight: "10px",
        paddingLeft: "10px",
      },
      lg: {
        fontSize: "15px",
        height: "35px",
        paddingLeft: "15px",
        paddingRight: "15px",
      },
    },
  },
});
Enter fullscreen mode Exit fullscreen mode

In the above code snippet, we have an Input element to handle users' input. In the above Input component, we want to have large and small inputs, and we defined the styles for that using the variants property.

Next, a new file Text.js and add the code snippet below.

import { styled } from "@stitches/react";

export const Text = styled('p', {
    fontFamily: '$mono',
    color: '$black5000',

    variants: {
      size: {
        1: {
          fontSize: '10px',
        },
        2: {
          fontSize: '12px',
        },
        3: {
          fontSize: '14px',
        },
      },
    },
  });
Enter fullscreen mode Exit fullscreen mode

In the above code snippet, we created a component to allow us to add and style a paragraph.

Open Source Session Replay

OpenReplay is an open-source, session replay suite that lets you see what users do on your web app, helping you troubleshoot issues faster. OpenReplay is self-hosted for full control over your data.

Start enjoying your debugging experience - start using OpenReplay for free.

Creating Blog App

Now that we've styled the elements we need for this application, let's go ahead and create a blog application. First, we need to update the pages/index.js file to import all components we just created with the code snippet below.

import { Button } from "../components/Button"
import { Input } from "../components/Input"
import { Card } from "../components/Card"
import { Text } from "../components/Text"
import { Header } from "../components/Header"
import { Image } from "../components/Image"
import { Container } from "../components/Container"
Enter fullscreen mode Exit fullscreen mode

Next, we'll use the component to update the Home component with the code snippet below.

export default function Home() {
  const [modal, setModal] = useState(false)

  const showModal = () => {
    setModel(!model)
  }
  return (
    <>
      <Container>
        <Header bg="primary">
          <Text size="1">My Blog App</Text>
          <Button bg="secondary" size="sm" onClick={showModal}>
            New Blog
          </Button>
        </Header>
        {model && (
          <Card boder="solid">
            <Text size="1">Titile:</Text>
            <Input />
            <Text size="1">Content</Text>
            <Input />
            <Text size="1">Cover Image</Text>
            <Input />
            <Button bg="primary" size="sm">
              Post
            </Button>
          </Card>
        )}
        <Text>Blog Posts</Text>
      </Container>
      <Container fd="row">
        {blogs.map(blog => (
          <Card boder="solid">
            <Image src={blog.cover} size="lg" />
            <Text size="3">{blog.title}</Text>
            <Text size="1">{blog.content}</Text>
            <Text size="1">{blog.date}</Text>
          </Card>
        ))}
      </Container>
    </>
  )
}
Enter fullscreen mode Exit fullscreen mode

In the above code snippet, we updated the Home component using the components we styled using Stitches. We applied the different styles we want to each of the components used in our Home component. We have a form input field that will be toggled to hide or show it using the Modal state variable.

Then we looped through the blog details we'll be creating shortly using the map function and render them to the user.

Finally, add the following blog array objects to the Home component.

...
  const blogs = [
    {
      title: "How to build a website",
      content:
        "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam euismod, nisi vel consectetur euismod, nisi nisl aliquet nisi, eget consectetur nisl nisi eget nisi. Nullam euismod, nisi vel consectetur euismod, nisi nisl aliquet nisi, eget consectetur nisl nisi eget nisi. Nullam euismod, nisi vel consectetur euismod, nisi nisl aliquet nisi, eget consectetur nisl nisi eget nisi. Nullam euismod, nisi vel consectetur euismod, nisi nisl aliquet nisi, eget consectetur nisl nisi eget nisi. Nullam euismod, nisi vel",
      cover:
        "https://www.hostgator.com/blog/wp-content/uploads/2017/09/MakeOwnWebsite.png",
      date: "2020-01-01",
    },
    {
      title: "Getting started with OpenReplay",
      content:
      "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam euismod, nisi vel consectetur euismod, nisi nisl aliquet nisi, eget consectetur nisl nisi eget nisi. Nullam euismod, nisi vel consectetur euismod, nisi nisl aliquet nisi, eget consectetur nisl nisi eget nisi. Nullam euismod, nisi vel consectetur euismod, nisi nisl aliquet nisi, eget consectetur nisl nisi eget nisi. Nullam euismod, nisi vel consectetur euismod, nisi nisl aliquet nisi, eget consectetur nisl nisi eget nisi. Nullam euismod, nisi vel",
      cover:
        "https://opengraph.githubassets.com/2ddbe84dccfbcc774b1c9861dd327d2efd7e1cd49964dc01229c181bea751e60/openreplay/documentation",
      date: "2020-01-01",
    },
    {
      title: "Node.js Vs React",
      content:
      "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam euismod, nisi vel consectetur euismod, nisi nisl aliquet nisi, eget consectetur nisl nisi eget nisi. Nullam euismod, nisi vel consectetur euismod, nisi nisl aliquet nisi, eget consectetur nisl nisi eget nisi. Nullam euismod, nisi vel consectetur euismod, nisi nisl aliquet nisi, eget consectetur nisl nisi eget nisi. Nullam euismod, nisi vel consectetur euismod, nisi nisl aliquet nisi, eget consectetur nisl nisi eget nisi. Nullam euismod, nisi vel",
      cover:
        "https://miro.medium.com/max/1400/1*CpDidbInbG4Er_0j_hknFQ.jpeg",
      date: "2020-01-01",
    },
  ]
...
Enter fullscreen mode Exit fullscreen mode

Test the application

With the blog demo application created, let's go ahead and test it out. Run the commands to change the directory to the project folder and start the application.

  cd gatsby-site
  gatsby develop
Enter fullscreen mode Exit fullscreen mode

Then navigate http://localhost:8000/ and you should see the output below on the index page.

Conclusion

You’ve learned how to create a theme UI in a Gatsby application with Stitches by building a blog demo application. First, we started with an introduction to Gatsby and Stitches. You learned how to configure Stitches with Gatsby and styled some components.
Now that you've known how to integrate Gatsby and Stitches, how would you style your next Gatsby application?

Top comments (0)