Styled Components 101 💅 Lecture 2: Creating a theme + Light/Dark theme toggler example ☀️🌙
Tags: react, javascript, css, tutorial
Published: 2021-07-25 12:49:22

Hello, everybody! 👋
And welcome to the 2nd lecture of the __Styled Components 101 series__ 🙌

In this lecture, we'll be covering the __creation of a custom theme__ with Styled Components.

If you're new to Styled Components and this lecture is the first one you run into, I suggest taking a look at the previous lecture first, where we covered some basic concepts and examples of Styled Components.

With all this said, let's move on to today's topic 👇

#Creating the theme file 🔮
First things first. Before start generating components and other component-related stuff, what we need to do is __create the file__ that will host our __app's theme__.

This theme file will be just a regular JavaScript file with _js_ extension that will contain an object called _theme_ with properties and values that we'll be using to style our components.

As easy as that 💁‍♂️

Let's have a look at how this file looks like:

`theme.js`
```js
const theme = {
   colors: {
      plum: "#52314b",
      rose: "#c3537d",
      dryrose: "#dd7f9a",
      primrose: "#e8babf",
      white: "#fff"
   }
}

export default theme;
```

For now, we'll be working only with colors, but every property/value you can imagine that is used for styling will also be set in this file: values regarding fonts, padding, margin, etc. In short, every value that you'd set up in a CSS file.

Don't forget to export your theme object. Otherwise, there's no way for it to be found by the app 👍

And that's all for the theme file. We're now set to head on to the next step 😼

#Making the theme file reachable by the app 🕵️

In order for the theme file to be able to be accessed, we need to provide it to the app. To do this, we'll import the component _ThemeProvider_ from _styled-components_ and will wrap our app with it.

`App.js`
```jsx
import { ThemeProvider } from "styled-components";
import theme from "./theme";

const App = () => {
   return(
      <ThemeProvider theme={theme}>
         //your code here  
      </ThemeProvider>
   )
}
export default App;
```
Now, our theme is recognized by the app and can be accessed and used from anywhere throughout it.

#Using the theme inside a _styled_ component 💅

Retrieving theme values from within a _styled_ component is a really easy process, since the theme is __implicit__ to the component props. 

Let's see how to style a _styled_ component making use of a couple values from our custom theme:

`BasicThemedButton.js`

```js
import styled from "styled-components";

export default styled.button`
   background-color: ${props => props.theme.colors.primrose};
   color: ${props => props.theme.colors.white};
   font-size: 1.25rem;
   border: none;
   border-radius: 5px;
   padding: 10px;
`
```
Our custom theme is implicitly passed-in as a prop and it's easily accessed because the component is also wrapped by the provider:

`App.js`
```jsx
import { ThemeProvider } from "styled-components";
import theme from "./theme";
import BasicThemedButton from "./components/BasicThemedButton";

const App = () => {
   return(
      <ThemeProvider theme={theme}>
         <BasicThemedButton>I am a basic themed button! 🤗</BasicThemedButton>  
      </ThemeProvider>
   )
}
export default App;
```
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1ptnhmydwx9fp1qsyqr5.png)

#Using the theme inside a custom React component ⚛️

To use our theme inside a custom React component, we need to write a little bit more code, but not a big deal at all.


`ThemedButton.js` ≡ React component

```jsx
import React, { useContext } from "react";
import StyledButton from "./StyledButton";
import { ThemeContext } from "styled-components";

const ThemedButton = () => {
   const theme = useContext(ThemeContext);
   return(
      <StyledButton bgColor={theme.colors.plum} color={theme.colors.white}>I am a themed button 😜</StyledButton>
   )
}

export default ThemedButton;
```

`StyledButton.js` ≡ Styled component

```js
import styled from "styled-components";

export default styled.button`
   background-color: ${props => props.bgColor};
   color: ${props => props.color};
   padding: 10px;
   border: none;
   border-radius: 5px;
   font-size: 1.25rem;
`
```

This time, the values from the theme are passed to the _styled_ component __via props__, which have been previously retrieved in the React component by making use of the ___useContext___ hook and the ___ThemeContext___ component from _styled-components_.

Note that we'll be calling our React component as we regularly do:

`App.js`
```jsx
import { ThemeProvider } from "styled-components";
import theme from "./theme";
import ThemedButton from "./components/ThemedButton";

const App = () => {
   return(
      <ThemeProvider theme={theme}>
         <ThemedButton/>
      </ThemeProvider>
   )
}
export default App;
```

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2blqu53pmdr6gzzslo2o.png)

#The _theme_ prop 🤖
The _theme_ prop is used to pass in an inline object that contains the specification for the theme to a styled component. 

`App.js`

```jsx
import { ThemeProvider } from "styled-components";
import StyledButton from "./components/StyledButton";
import theme from "./theme";

const App = () => {
   return(
      <ThemeProvider theme={theme}>
         <StyledButton theme={{bg: theme.colors.primrose, color: theme.colors.white}}>I am a button with a theme prop! 😎</StyledButton>
      </ThemeProvider>
   )
}
export default App;
```

`StyledButton.js`
```js
import styled from "styled-components";

export default styled.button`
   background-color: ${props => props.theme.bg};
   color: ${props => props.theme.color};
   padding: 10px;
   border: none;
   border-radius: 5px;
`
```

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mmtme1uroaum58rgmdj9.png)

This method can be useful if we don't have many properties, but, when we have a robust application with several properties and values for styling, this method becomes difficult to maintain and tricky to deal with ❌

#Using JavaScript objects to write our styles rather than CSS 🤹‍♀️

Did you know that is also possible to write custom styles using __JS instead of CSS__ in Styled Components? And it's easier than you may think.

Let's have a look at the following snippet:

`JSStyledButton.js`

```js
import styled from "styled-components";

export default styled.button(props => ({
   backgroundColor: props.bgColor,
   fontSize: "1.5rem",
   color: props.color
}));
```

`App.js`
```jsx
import { ThemeProvider } from "styled-components";
import theme from "./theme";
import JSStyledButton from "./components/JSStyledButton";

const App = () => {
   return(
      <ThemeProvider theme={theme}>
         <JSStyledButton bgColor={theme.colors.plum} color={theme.colors.white}>I am a JS Styled Button 🤠</JSStyledButton> 
      </ThemeProvider>
   )
}
export default App;
```

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xa3cp7u3luuyoue7x2m3.png)

Notice that property names are written in __camelcase__ notation, as we're using a JavaScript object, but it's also accepted to write them within __double quotes__, like this:

```js
import styled from "styled-components";

export default styled.button(props => ({
   "background-color": props.bgColor,
   "font-size": "1.5rem",
   color: props.color
}));
```

Also note that the used method to specify the styles is similar to the one we use when __extending styles from a supercomponent__ (_Lecture 1 - Inheriting styles from another component_ section):

```js
...
export default styled.button(...);
...
```

#And now... 👑 The jewel in the crown: Let's create a Light/Dark theme toggler with Styled Components

Theory is cool but, but let's get our hands dirty and let's create something interesting using themes 👏

###Excuse me, but... what exactly is a _theme toggler_? 🤔

We can say that a theme toggler is a _system_ that allows to __switch between a light and a dark theme__ with just one click by using a button or an emoji. Cool, right?

In this tutorial, we'll implement a styled button that will perform this task really fast and efficiently.

And now, let's get it started 👉

##The components and files 🎬

These are the components and files that will make up our app:

`Button.js`: the button that will switch between themes.

`GlobalStyles.js`: a component that will inject global styles into the app.

`ThemeToggler.js`: the component that will receive the theme as a prop, which, in turn, will be passed in to the _Button_ component.

`useDarkTheme.js`: a custom hook that will contain the business logic. 

`App.js`: the main app. It will wrap everything up with the theme provider and will include the global styles.

`themes.js`: the file that will host our themes (we already know how to do this at this point 😺).

##Let's first create our _themes_ file 📝

`themes.js`

```js
export const lightTheme = {
    background: '#fff',
    color: '#1d1f28',
    buttonBg: '#c5718d'
}

export const darkTheme = {
    background: '#1d1f28',
    color: '#fafafa',
    buttonBg: '#515d90'
}
```

Not a lot to remark here: we have defined both themes with their respective style properties. Don't forget to export them both 👍

##Now let's go with the _switch_ button 🔵

`Button.js`

```js
import styled from "styled-components";

export default styled.button`
   font-family: "Monaco", monospace;
   cursor: pointer;
   border: none;
   background-color: ${({ theme }) => theme.buttonBg};
   color: #fff;
   padding: 10px;
   border-radius: 5px;
   font-size: 1.5rem;
`
```
A regular _styled_ button. You can style it as you like best.

Note that the value for `background-color` will be set depending on the selected theme. The rest is up to you 😇

##Time for global styles 😼

`GlobalStyles.js`

```js
import { createGlobalStyle } from "styled-components";

export const GlobalStyles = createGlobalStyle`
   body {
     font-family: "Monaco", monospace;
     background: ${({ theme }) => theme.background};
     color: ${({ theme }) => theme.color};
     transition: all 0.50s linear; 
  }
`
```
___GlobalStyles___ defines the global styles for our app. They will be injected into our app by in `App.js`.


Note that for this purpose, we'll import the ___createGlobalStyle___ helper from _styled-components_, which will create a new _styled_ component that will handle global styles.

Regarding the properties, background and text colors will be retrieved from the theme. We'll also add a _transition_ property to make the switch effect smoother.


##Creating the theme toggler 💁
`ThemeToggler.js`

```jsx
import React from 'react';
import Button from "./Button";

const ThemeToggler = (props) => {
   const { themeToggler } = props;
   return (
      <Button onClick={themeToggler}>Switch Theme ☀️ 🌙</Button>
   );
};

export default ThemeToggler;
```
___ThemeToggler___ renders the Button component and provides it with the style properties that correspond to the passed-in theme.

`useDarkTheme.js`

```jsx
import { useState } from 'react';

const THEMES = {
   LIGHT: "light",
   DARK: "dark"
}

const useDarkTheme = () => {
    const [theme, setTheme] = useState(THEMES.LIGHT);
    const themeToggler = () => {
        theme === THEMES.LIGHT ? setTheme(THEMES.DARK) : setTheme(THEMES.LIGHT);
    };
    return [theme, themeToggler];
};

export default useDarkTheme;
```
___useDarkTheme___ is a custom hook that contains the logic for our toggler. We're using a hook to abstract our app as much as possible.

The switching procedure is as easy as follows: if the passed-in theme is _light_, the _dark_ theme will be set up, and vice versa.

##Building the main _app_ 😈
`App.js`

```jsx
import React from "react";
import { ThemeProvider } from "styled-components";
import { GlobalStyles } from "./components/GlobalStyles";
import { lightTheme, darkTheme } from "./themes";
import ThemeToggler from "./components/ThemeToggler";
import useDarkTheme from "./hooks/useDarkTheme";

const App = () => {
   const [theme, themeToggler] = 
   useDarkTheme();
   const selectedTheme = theme === 'light' ? lightTheme : darkTheme;

   return (
      <ThemeProvider theme={selectedTheme}>
         <>
            <GlobalStyles />
            <ThemeToggler themeToggler={themeToggler} />
            <p>Trying out light and dark themes! 😍</p>
         </>
      </ThemeProvider>
   )
}
export default App;
```

First, we're calling the _useDarkTheme_ hook, that will handle the _switch_ logic.

Then, we also need to have a function _selectedTheme_, that decides which theme is going to be used.

And now, what's only left is to wrap up ___ThemeToggler___ with ___ThemeProvider___ and include ___GlobalStyles___.


#The result ☀️ ➡️ 🌙
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h5zwv6yfcb4c5q9pgbqh.gif)

___

And this is all for the second Styled Components 101 lecture! 

Stay tuned to know more about Styled Component in future episodes of the series.

A big thanks for reading  🤗  and don't hesitate to reach out to me if you any questions or doubts about today's lecture.

![Rachel Green from Friends TV Show behind a desk saying "Ask me anything"](https://media.giphy.com/media/XFuQ4InwtXBE4DDPHM/giphy.gif)

I hope you found this article useful and I see you all in the next 👋
___

👉 You can also check out the __related slides__ for this article on Instagram 👈

{% instagram CRv7A4HDUEV %}

___

🎉 Don't forget to follow @underscorecode on [Instagram](https://instagram.com/underscorecode) and [Twitter](https://twitter.com/underscorecode) for more daily webdev content 🖥🖤

____

####And last but not least... A quick friendly reminder before we go 😊
We all know there are million ways to get things done when it comes to programming and development, and we're here to __help and learn__, so, if you know another possible way to do what others are sharing (__not better, not worse, just different__), feel free to share it if you feel like it, but, please, __always be kind and respectful__ with the author and the rest of the community. Thank you and happy coding!