Adding a “DayNight” theme to your app with react-rainbow-components.
Tags: react, javascript, programming, rainbow
Published: 2021-01-28 01:13:38

If you’d prefer to watch rather than read:
https://youtu.be/Dy0g3nLrFHE


### Why Do We Need a DayNight theme?

The DayNight functionality allows your app to easily switch between a dark ⬛ and light ⬜ theme. This has many benefits for your users, increasing usability for people with reduced-vision, and more.

Dark theme reduces the light emitted by device screens while maintaining the minimum color contrast ratios required for readability. The advantages are, it enhances visual ergonomics by reducing eye strain, facilitating screens to adjust according to current light conditions, and providing the comfort of use at night or in dark environments.

Through this article, I will show you how to implement a "DayNight" theme in your application using [react-rainbow-components](https://react-rainbow.io/). To accomplish this, you must have a general background in React, Node.js, and Yarn.


## Project Settings
### What you will need?
- Node.js
- Yarn
- Your favorite IDE (For this tutorial, I will use VSCode)

### Adding dependencies
For this project, I will use a new `create-react-app project`. If you want to know more and how to initialize a project, see: https://create-react-app.dev/

For the app styles, I will use `styled-components`. I like it because I can write styles with normal CSS syntax while having all the JS power. Once at the root of your project, let's install styled-components. For more information, see https://styled-components.com/

```
$ yarn add styled-components@4.4.1
```

Then, let's install react-rainbow-components. For more information, see https://react-rainbow.io/#/GettingStarted.

```
$ yarn add react-rainbow-components
```

Once you have your new project with all dependencies installed, we should be ready to code!


## Coding
### The Skeleton
Now we will begin to build the markup of our application. It consists of a single page that has a sidebar on the left, a group of Tiles on the top, and a list of data.

``` js
import { Sidebar, SidebarItem, Card, Table, Column } from 'react-rainbow-components';
function App() {
    return (
            <main>
                <Sidebar>
                    <SidebarItem label="Apps" />
                    <SidebarItem label="Chat" />
                    <SidebarItem label="Settings" />
                </Sidebar>
                <section>
                    <header>
                        <h1>Title</h1>
                    </header>
                    <section>
                        <Card />
                        <Card />
                        <Card />
                        <Card />
                    </section>
                    <Table
                        keyField="id"
                        data={data}
                        variant="listview"
                    >
                        <Column header="Name" field="name" />
                        <Column header="Id"  field="id" />
                        <Column header="Phone" field="phone"/>
                        <Column header="Status"  field="status" />
                    </Table>
                 </section>
             </main>
    );
}
```


### The Application component
Now we will customize the default styles of our application. Since we are using `react-rainbow-components` we will do this customization through the theme prop of the `Application` component, which must wrap your entire app.

The property `theme` will accept an object where you can specify your palette of colors. If you want to see all the properties you can customize with the theme object, see: https://react-rainbow.io/#/Customization.

``` js
function App() {
    return (
        <Application theme={themes.light}>
          ...
        </Application>
```

Create the themes object:
``` js
const themes = {
    light: {
        rainbow: {
            palette: {
                brand: '#4dc9cb',
                success: '#98D38C',
                warning: '#F7DB62',
                error: '#f2707a',
            },
        },
    },
};
```


### How style your tags?
In order to use the theme with your custom components or tags, you can use styled-components normally as you would do in other projects, and out of the box, the props will have the theme object with all the custom colors.

``` js
import styled from 'styled-components';
export const Container = styled.main`
    background: ${props => props.theme.rainbow.palette.background.secondary};
    height: 100vh;
`;
```

The page will look like this:
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/27jgjfnwidzexj3b519a.png)


### The DayNight theme colors
Now we add the dark colors to the `themes` object:

``` js
const themes = {
    light: {
        rainbow: {
            palette: {
                brand: '#4dc9cb',
                success: '#98D38C',
                warning: '#F7DB62',
                error: '#f2707a',
            },
        },
    },
    dark: {
        rainbow: {
            palette: {
                mainBackground: '#212121',
                brand: '#4dc9cb',
                success: '#98D38C',
                warning: '#F7DB62',
                error: '#f2707a',
            },
         },
    },
};
```


### The DayNight switch button
Next, we will implement the DayNight switch button functionality, so the user can change the theme of the application. We will use the local storage to keep the selected theme, even when the browser tab is closed or refreshed.


#### Implement the `useLocalTheme` hook
``` js
const useLocalTheme = () => {
    const [state, setState] = useState(() => localStorage.getItem('theme') || 'light');
    const setItem = (value) => {
        localStorage.setItem('theme', value);
        setState(value);
    }
    return [state, setItem]
}
```

With this hook, we encapsulated the logic to interact with the local storage and also used a useState to make the dark/light theme switching reactive. It will return an array with two elements. The first is the state with a string indicating the selected theme, which will be initialized with the value stored in the local storage. If no value is found, then it will fallback to light. The second element is a function that will be used to store the new theme in the local storage and also will update the state to make the application react to the theme change.


#### Implementing the switch:
Now we will use the useLocalTheme and add the onClick handler to the DayNight button:

``` js
function App() {
    const [theme, setTheme] = useLocalTheme();
    const switchIcon = theme === 'light' ? <MoonIcon /> : <SunIcon />;
    const toggleTheme = () => {
        if (theme === 'light') {
            setTheme('dark');
        } else {
            setTheme('light');
        }
    };
    return (
        <Application theme={themes[theme]}>
            ...
            <ButtonIcon
                shaded
                variant="border-filled"
                icon={switchIcon}
                size="large"
                onClick={toggleTheme} />
            ...
```


Here we added an icon that will render a moon or a sun based on the theme state. Also, we implemented the onClick handler called toggleTheme, which will make the theme switch using the function returned by the useLocalTheme hook.

The page will look like this when the theme is dark:
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/0glhy55bgqes9mywzkr2.png)

You can see the whole code and play in this sandbox:
https://codesandbox.io/s/sparkling-wave-rqzr7?file=/src/index.js


## Conclusion
As you can see, with those simple implementations, you can have a DayNight theme on your application.

Thanks for reading!