Custom Themes and Dark Mode Release
Tags: webdev, javascript, opensource, design
Published: 2023-12-12 02:54:07

Well, this is it! Exciting stuff I know. Both issues on the integration of [dark mode](https://github.com/TheShiveshNetwork/Pokedex/issues/12) and [custom themes](https://github.com/TheShiveshNetwork/Pokedex/issues/22) have been completed! This marks the end of the 3 post series outlining my experience implementing these 2 functionalities. 

However, it doesn't feel right to not add a little more information on my experience with the custom theme functionality, so here are some notes I wrote down while reimplementing it which didn't make it into the previous post:

#### Unreleased Notes

My progress on the custom themes has been going great! Right now I'm planning on adding 2 new themes, a Gameboy theme, that will work off the limited palette of the original Gameboy and a Pokemon Home theme, based on the colours used in the [Pokemon Home](https://www.nintendo.com/us/store/products/pokemon-home-switch/) app. 

![Gameboy Colours](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/htw6q90pfs17ihp5nvom.png)
> Gameboy palette example

![Home Ref 1](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5ux1kqf8rjl6xdxhp8dw.png)

![Home Ref 2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l4x30uqkq1bpo039t4cs.png)
> Pokemon Home reference images

My prediction was correct, using the scraped data would've been a lot for the web app, even though I spent quite some time gathering all the portraits for the Pokemon, I deleted the data and found an alternate way to handle everything: states and ID tracking. 

See the entirety of the styling right now is based on a dropdown, so essentially, when a style is changed:

```html
<select id="themeSel">
    <option value="">Light</option>
    <option value="dark" selected={theme == "dark"}>Dark</option>
    <option value="gameboy" selected={theme == "gameboy"}>Gameboy</option>
    <option value="home" selected={theme == "home"}>Pokemon Home</option>
</select>
```
Tracking the value of the select component `"themeSel"` along with a state variable `"theme"` enabled me to track the selected theme directory-wide by simply referencing the ID of the dropdown. This lets me do fun things like dynamically change the styling of the background and other areas like the cards easily when using a custom theme. This is a pretty big change over the simple toggle I had previously implemented for dark mode.

Using a reference to the dropdown also allows me to dynamically make API calls, as opposed to storing all that data locally. If the Gameboy theme is selected, I want to be able to change the official art portraits to the pixel-based sprites seen in most of the games. Of course, if the home theme is selected, I want to use the home model to show off all the Pokemon. I already have an idea as to what needs to be done for the home theme because of some reference pictures taken from the Nintendo store's site. That's all for the update!

#### Anyways...

So yes, both functionalities are implemented and fully functional. It was super fun implementing the new themes as it almost required me to create a skeleton theme manager that can be used to implement any number of new themes! I ran into a few problems, mainly with how I handled storing all the themes, which was promptly fixed up by reducing the scale of what I was doing. For example...

```js
    const toggleDarkMode = () => {
      const newTheme = !isDarkMode;
        const newTheme = !isDarkMode;
        setIsDarkMode(newTheme);
        setIsHomeTheme(false);
        setIsGameboyTheme(false);
        localStorage.setItem('isDarkMode', JSON.stringify(newTheme));
        localStorage.setItem('isHomeMode', JSON.stringify(false));
        localStorage.setItem('isGBMode', JSON.stringify(false));
    };
```

this chunk of code handled everything JUST for toggling dark mode... yeah it's ugly, and it made me realize almost immediately after creating this abomination that I should scale back on how I handle it. Now it's handled in a much neater fashion;

```js
    useEffect(() => {
        const savedTheme = localStorage.getItem('theme');
        if (savedTheme !== null) {
            setTheme(savedTheme);
        }
    }, []);

    const handleThemeChange = (newTheme) => {
        setTheme(newTheme);
        localStorage.setItem('theme', newTheme);
    };
```

these 2 do it all! the useEffect is mainly just for extracting the theme when loading the site so that it remembers what theme you had stored in a previous session, whereas the handleThemeChange, works its magic when you change the theme while using the site. There's a lot more to it, but the bread and butter is right here, and it was a ton of fun to figure out and implement!

## Completing my goals

It took a lot of time (mainly because of my overcomplication with the implementation) but it was a fantastic experience to work on these features. Dark Mode is interesting because working on it made me realize that it can be as easy or as hard as you want it to be to implement. It's one of these features where there are almost a million ways to implement it but luckily I realized a bit after overdeveloping it that there was a much better and neater solution. Custom Themes are almost the same, I spent a good couple of days crafting a comprehensive list using a mixture of web scraping and manual formatting only for me to realize how benign an implementation like this is for such a feature. Of course, it would've worked, but at what cost? Working on the dark mode feature gave me a good idea as to how I would need to handle the custom themes, and working on custom themes gave me an excellent idea as to how custom theme frameworks are built. Tailwind CSS made all of this a breeze by allowing me to create custom colours that could be easily referenced.

The PRs and issues can be found below, as well as pictures of the final look for all the themes!

### Issues

{% embed https://github.com/TheShiveshNetwork/Pokedex/issues/12 %}

{% embed https://github.com/TheShiveshNetwork/Pokedex/issues/22 %}

### PRs

{% embed https://github.com/TheShiveshNetwork/Pokedex/pull/23 %}

{% embed https://github.com/TheShiveshNetwork/Pokedex/pull/26 %}

***EDIT: 12-12-2023*** Something seemed to have gone wrong with the merging of the previous PR according to the repo owner, so I made another identical one found here: {% embed https://github.com/TheShiveshNetwork/Pokedex/pull/28 %}

## The final not final TIL

I learned a good amount from the implementation of these features; how to create and style a dark mode (in more ways than one) using both stylesheets and CSS frameworks, creating custom themes using these frameworks, saving styling themes to a local cache and loading it, and lastly, dynamic API calling through referencing IDs. I felt like I poured my heart into these final features, which was reflected in the code review conducted by the repo owner. It was truly a wonderful experience.

## Closing thoughts

It's been an incredible 4 months since my open-source journey began and this is not the end of it. I want to deeply thank you all for reading my posts and keeping up! It was a great semester and I'm so happy I got to learn and experiment so much with open-source projects, something that means the absolute most to me. I hope you all enjoy your holiday season and once more, thank you for following the start of my open source journey!