how to theme your gatsby site  
Tags: gatsby, hooks, codenewbie, react
Published: 2020-09-13 02:40:47

### First of all.
The following idea can be applied to all kinds of sites while those use React, you need to know that [Gatsby](https://www.gatsbyjs.com/) is a React-based open-source framework for creating websites and apps.

#### The main Idea 💡

We need to know that themes are CSS properties that change when we select a specific theme. eg.

```javaScript
          <button type="button" onClick={handleToggle} style={styles(theme).toggle}>
            { theme === themes.light ? '☽' : '☼' }
          </button>
```
![Example of toggle a theme in a site](https://dev-to-uploads.s3.amazonaws.com/i/5qajs6b5exrjeg2xn5lf.gif)

We will create a **dark ☽** and **light  ☼** theme:

```javaScript
import { createContext, useState } from 'react'

export const themes = {
  light: {
    foreground: 'rebeccapurple',
    background: 'white'
  },
  dark: {
    foreground: 'white',
    background: 'rebeccapurple'
  }
};
export const ThemeContext = createContext();
```
We need to create also the hook to manage the state of the current theme:

```javaScript
export const useThemes = () => {
  const [mode, setMode] = useState(themes.light);

  const toggleMode = () => { 
    if (mode === themes.light) {
      setMode(themes.dark);
    } else {
      setMode(themes.light);
    }
  };

  return [mode, toggleMode]
};
```

Please create a context to wrap your app :

```
import React from "react"
import PropTypes from "prop-types"
import { useStaticQuery, graphql } from "gatsby"
```
```javaScript
import { ThemeContext, themes, useThemes } from './Context/Theme'
```
```
import Header from "./Header"
import "./layout.css"

const Layout = ({ children }) => {
```

> Import and create only one instance of our theme, this is a kind of singleton pattern.

```javaScript
  const [theme, handleToggle ] = useThemes();
```
```
  const data = useStaticQuery(graphql`
    query SiteTitleQuery {
      site {
        siteMetadata {
          title
        }
      }
    }
  `)
console.log(theme.foreground);
  return (
```

```javaScript
    <ThemeContext.Provider value={themes}>
      <Header siteTitle={data.site.siteMetadata.title} handleToggle={handleToggle} theme={theme}/>
```
```
      <div
        style={{
          color: theme.foreground,
          background: theme.background,
          margin: `0 auto`,
          maxWidth: 960,
          padding: `10rem 1.0875rem 1.45rem`,
        }}
      >
        <main>{children}</main>
        <footer>
          © {new Date().getFullYear()}, Built with
          {` `}
          <a href="https://www.gatsbyjs.org">Gatsby</a>
        </footer>
      </div>
```
```javaScript
    </ThemeContext.Provider>
```
```
  )
}

Layout.propTypes = {
  children: PropTypes.node.isRequired,
}

export default Layout
```

The **Header** component will look like:

```
import { Link } from "gatsby"
import PropTypes from "prop-types"
import React, { useContext } from "react"
import {styles} from './styles'
import { ThemeContext } from "../Context/Theme";
```

> I will use Context to compare what is the current theme and  `handleToggle` function to change between themes. 

```javaScript
function Header({ siteTitle, handleToggle, theme }) {
  const themes = useContext(ThemeContext);
```

```
  return (
    <header
      style={styles(theme).header}
    >
      <div
        style={styles(theme).navbar}
      >
        <h1 style={styles(theme).title}>
          <Link
            to="/"
            style={styles(theme).link}
          >
            {siteTitle}
          </Link>
        </h1>
        <div style={styles(theme).buttonContainer}>
```
```javaScript
          <button type="button" onClick={handleToggle} style={styles(theme).toggle}>
            { theme === themes.light ? '☽' : '☼' }
          </button>
```
```
        </div>
      </div>
    </header>
  );
}

Header.propTypes = {
  siteTitle: PropTypes.string,
}

Header.defaultProps = {
  siteTitle: ``,
}

export default Header
```
 
### Wrapping up

The main idea is to know that you can apply this to any site ;)