DEV Community

Cover image for Adding a “DayNight” theme to your app with react-rainbow-components.
Tahimi for React Rainbow

Posted on

Adding a “DayNight” theme to your app with react-rainbow-components.

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. 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
Enter fullscreen mode Exit fullscreen mode

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

$ yarn add react-rainbow-components
Enter fullscreen mode Exit fullscreen mode

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.

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>
    );
}
Enter fullscreen mode Exit fullscreen mode

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.

function App() {
    return (
        <Application theme={themes.light}>
          ...
        </Application>
Enter fullscreen mode Exit fullscreen mode

Create the themes object:

const themes = {
    light: {
        rainbow: {
            palette: {
                brand: '#4dc9cb',
                success: '#98D38C',
                warning: '#F7DB62',
                error: '#f2707a',
            },
        },
    },
};
Enter fullscreen mode Exit fullscreen mode

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.

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

The page will look like this:
Alt Text

The DayNight theme colors

Now we add the dark colors to the themes object:

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',
            },
         },
    },
};
Enter fullscreen mode Exit fullscreen mode

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

const useLocalTheme = () => {
    const [state, setState] = useState(() => localStorage.getItem('theme') || 'light');
    const setItem = (value) => {
        localStorage.setItem('theme', value);
        setState(value);
    }
    return [state, setItem]
}
Enter fullscreen mode Exit fullscreen mode

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:

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} />
            ...
Enter fullscreen mode Exit fullscreen mode

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

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!

Top comments (0)