Tvick22 / platformer3x

Student repository for Trimester 3, Spring 2024. (Leaderboard Team)
https://tvick22.github.io/platformer3x/
Apache License 2.0
0 stars 0 forks source link

Theme Switch Button Steps (for future reference) #24

Closed myamadriaga closed 1 month ago

myamadriaga commented 2 months ago

There isn't a direct order you need to go in for this, although I started with finding the way I wanted to create the button and the keywords I wanted to use. I started with trying to create the theme switch as one function, but that didn't work overall.

The method I used had two different sass files, connecting to two different JS files which the function controlled in the SettingsControl file. I created a dark-mode.scss, and a light-mode.scss file.

This is the code used for the dark-mode.scss, as a reference:


.dark-mode {  
    background-color: black;

    a {
        color: rgb(75, 186, 255);
    }

    a:hover {
        color: #7a7976;
    }
    .site-title, .site-title:visited, .site-nav, .page-link {
        color: #FFFFFF;
    }

    .site-nav {
        background-color: #000000;
        border-color: #FFFFFF;
    }

    * {
        scrollbar-color: #FFFFFF; 
    }

    pre, code {
        // BVas a lighter colour to better highlight short code words
        border-color: #FFFFFF;
        background-color:#000000 ;
    }

    .page-description {
        color: #FFFFFF
    }

    .post-meta {
        color: #FFFFFF;
    }

    .post-content p, .post-content li {
        color: #FFFFFF;
    }

    .btn {
        background-color: #000000;
        color: #FFFFFF;
        border-color: #FFFFFF;
    }

    .btn:hover {
        background-color: #7a7976;
    }

    table th{
        background-color: #000000;
        border-color: #FFFFFF;
        color: #FFFFFF;
    }

    table td{
        background-color: #000000;
        border-color: #FFFFFF;
        color: #FFFFFF;
    }

    .flash {
        color: #5e5d5b;
        filter: brightness(80%);
    }

    .post-list > li > div {
        box-shadow: none;
        background-color: #FFFFFF;
        border: none;
    }

    li .post-meta-description {
        color: #FFFFFF;
    }

    .search-result-preview{
        color: #FFFFFF; 
    }

    .search-result-highlight {
        color:yellow !important;
        font-weight:bold !important;
    }

    .search-results-list-item .search-result-title {
        color: cornflowerblue !important;
    }

    .button#startGame {
        color:#FFFFFF;
        background-color: #000000;
    }

    .leaderboard-button {
        color:#FFFFFF;
        background-color: #000000;
    }

    .input.userID {
        background: #000000;
    }

    .table.levels {
        background-color: #000000;
    }

    .sidebar {
        color:#000000;
        background-color: #FFFFFF;
    }
    .p {
        color: #FFFFFF;
    }

    .submenu {
        color: #FFFFFF;
        background-color: #000000
    }

    .menu-icon {
        color: #000000;
    }

    .div {
        color:#000000;
        background-color:#FFFFFF;
    }
    .container canvas {
        /* Reset styles for canvases within .container */
        background: none;
        /* Add any other styles you want to reset */
    }
}

for the light mode, all that needs to be done is switch the hex code properties to the opposite colors. There is an invert filter that also exists, but I'm not sure if that will work as well--I'm listing what ended up working for me.

I stored the two files in custom-styles.scss, preferably in order of how I want the files to switch.

// Guide: https://github.com/jekyll/minima/blob/master/README.md
@import "minima/dark-mode";
@import "minima/light-mode"; 

Now that the sass is created, and it is checked that they both work, we can create 2 functions that remove and add the light and dark mode. (Again, this is not the easiest way, but the function does work.) lightMode.js:

// lightMode.js
export function enableLightMode() {
    // Code to enable light mode
    document.body.classList.remove('dark-mode');
    document.body.classList.add('light-mode');
}

darkMode.js:

// darkMode.js
export function enableDarkMode() {
    // Code to enable dark mode
    document.body.classList.add('dark-mode');
    document.body.classList.remove('light-mode');
}

those files will be used with the function that we created in SettingsControl.js. Import the two files into SettingsControl.js so the code knows what files you're referring to when you use it within the code with an if, else statement.

import { enableLightMode } from './lightMode.js';
import { enableDarkMode } from './darkMode.js';

I'm not directly sure if this event-listener affects the function, but I replicated one of the previous parts of the code to create this function. It seems to just be storing it in Local Storage, so I did not mess with that part.

 window.addEventListener("isTheme", (e)=>{ 
            // Update the isInverted value when an invert event is fired
            this[this.keys.isTheme] = e.detail.isTheme();
            // Update the isInverted value in the game environment
            GameEnv.isTheme = this[this.keys.isTheme]; 
            // Save the isInverted value to local storage
            this.save(this.keys.isTheme); 
        });

the code is all in a certain order, so I made sure to insert the code into the correct parts of the file.

The next part of the code, is the function and the code that will create the checkbox. Here, you can name the checkbox with inner html, then connect the event-listener function to change the theme.

 get isThemeInput() {
        const div = document.createElement("div");
        div.innerHTML = "Theme Change:"; // label

        const islightMode = document.createElement("input");  // get user defined lightmode boolean
        islightMode.type = "checkbox";
        islightMode.checked = GameEnv.lightMode; // GameEnv contains latest is lightMode state
        islightMode.addEventListener('change', () => {
            if (islightMode.checked) {
                enableLightMode();
            } else {
                enableDarkMode();
            }
        });

        // Append elements to the DOM or wherever appropriate
        div.appendChild(islightMode); 
        return div
        // Append div to your settings container
        // For example:
        // document.getElementById('settingsContainer').appendChild(div);
    }

I placed this code after the "isInverted" input. now, towards the end of the document we need to duplicate some of the code to construct the HTML input, along with event update:

  // Get/Construct HTML input and event update for theme change
        var themeChangeControl = settingsControl.isThemeInput;
        document.getElementById("sidebar").append(themeChangeControl);

This code helped me construct everything, although I ran into frequent problems, so I'll list my solutions below:

.container canvas {
    /* Reset styles for canvases within .container */
    background: none;
    /* Add any other styles you want to reset */
}

Problems I currently have:


This code structure is pretty unique, so the process for a light/dark-mode in other websites may be similar, but I don't believe it is as complicated as it was here. I think I learned a lot more about sass code and problems with things I'm trying to do, so I'm glad I was able to learn a lot more. When I would research to see how I can create the function, I think that this code structure was so specific, that not many websites really taught me how to specifically do it how I had to do it inside of this code.

I actually had to reset the code the first time I finalized the theme switch, because with commit issues and stuff breaking it was too risky to commit my changes in. I think its more polished after starting over clean.

myamadriaga commented 1 month ago

Fixing Issues on Function:

We needed the website to start on light mode, so I worked with Trevor in order to revise the code, this is what he changed it to:

get isThemeInput() {
        const localstorage = window.localStorage
        const lightmodekey = "islightMode"
        const div = document.createElement("div");
        div.innerHTML = "Theme Change:"; // label
        GameEnv.isLightMode = localstorage.getItem(lightmodekey).toLowerCase() === "true"

        const islightMode = document.createElement("input");  // get user defined lightmode boolean
        islightMode.type = "checkbox";
        if (GameEnv.isLightMode) {
            enableLightMode();
            islightMode.checked = true;
        } else {
            enableDarkMode();
            islightMode.checked = false;
        }
        islightMode.addEventListener('change', () => {
            if (islightMode.checked) {
                enableLightMode();
                GameEnv.isLightMode = true;
                localstorage.setItem(lightmodekey, GameEnv.isLightMode)
            } else {
                enableDarkMode();
                GameEnv.isLightMode = false;
                localstorage.setItem(lightmodekey, GameEnv.isLightMode)
            }
        console.log(GameEnv.isLightMode)
        });

        // Append elements to the DOM or wherever appropriate
        div.appendChild(islightMode); 
        return div
        // Append div to your settings container
        // For example:
        // document.getElementById('settingsContainer').appendChild(div);
    }

within this code, we saved it to local storage, and changed the code from a string to boolean so that it actually inputs into local storage. We defined localstorage, and lightmodekey so that it can be stored as true or false.