Focal Point
[SHARING] Easy Dark Theme Toggle

This topic can be found at:
https://forums.informationbuilders.com/eve/forums/a/tpc/f/7971057331/m/9957034296

January 27, 2020, 02:44 PM
Hallway
[SHARING] Easy Dark Theme Toggle
I discovered a quick way to turn a web page to a dark theme with two CSS properties:
 
body.dark {
    background-color: black;
    filter: invert(1) hue-rotate(180deg);
}
 

You can then add some javascript and add an event listener to a button that will toggle the class dark to the body tag to switch the dark mode on/off.

In the example below, it adds in a toggle switch using the FontAwesome library, adds in the theme selection to the browser local storage and will read from the local storage when it is run so it will keep the user preference on which theme they last had:

SET PAGE-NUM=OFF
TABLE FILE ibisamp/car
SUM DEALER_COST/D12M
    RETAIL_COST/D12M
    COMPUTE MARGIN/D12.2% = (RETAIL_COST - DEALER_COST) / DEALER_COST * 100 ;
BY COUNTRY
BY CAR
BY MODEL
ON TABLE HOLD FORMAT HTMTABLE
ON TABLE RECOMPUTE
ON TABLE SET STYLE *
INCLUDE=IBFS:/FILE/IBI_HTML_DIR/ibi_themes/flat.sty,$
TYPE=TITLE, BACKCOLOR=RED, COLOR=WHITE,$
ENDSTYLE
END

-RUN

-HTMLFORM BEGIN NOEVAL
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Dark Theme Toggle</title>
    <!--  ⤹ FontAwesome JS ⤸ -->
    <script defer src="https://use.fontawesome.com/releases/v5.8.1/js/all.js"></script>
    <style>
        /* ⤹ dark class on Body element ⤸ */
        body.dark {
            background-color: black;
            filter: invert(1) hue-rotate(180deg);
        }
        /* ⤹ Toggle button styling ⤸ */
        #btnTheme{
            font-size: 2rem;
            border: none;
            background: none;
            outline: none;
            cursor: pointer;
        }
    </style>
</head>
<body>
    <nav>
        <!--  ⤹ Button to toggle darkmode - empty for now, will get populated with FontAwesome toggle Icon ⤸ -->
        <button id="btnTheme" title="Dark Theme Toggle"></button>
    </nav>
    <main>
        <!--  ⤹ Insert IBI held HTMTABLE into the DOM ⤸ -->
        !IBI.FIL.HOLD;
    </main>
    <script>
    //After DOM has loaded.
        //⤹ Set the element that you want to toggle the 'dark' class on as a variable ⤸
        const htmlElement = document.querySelector('body');
        //⤹ Set the toggle button as a variable ⤸
        const btnToggle = document.querySelector('#btnTheme');
        //⤹ Check the localStorage for a theme value. If there is one get the value, if not return an empty array  ⤸
        const elementClassList = localStorage.getItem('theme') ? JSON.parse(localStorage.getItem('theme')) : [] ;
        //⤹ Look for the 'dark' theme in the local storage array, and if the index is not -1 then it exists. ⤸
        if (elementClassList.indexOf('dark') !== -1) {
            //⤹ Add the 'dark' class to the element ⤸
            htmlElement.classList.add('dark');
            //⤹ Add the toggle on icon to the button ⤸
            btnToggle.innerHTML = '<i class="fas fa-toggle-on"></i>';
        } else {
            // ⤹ no class is added to element and the 'toggle off' icon is added to button ⤸
            btnToggle.innerHTML = '<i class="fas fa-toggle-off"></i>';
        }

        //⤹ add onclick event listener to the button ⤸
        document.querySelector('#btnTheme').addEventListener('click', function () {
            //⤹ toggle the dark class on the element ⤸
            htmlElement.classList.toggle('dark');
            //⤹ Toggle the 'fa-toggle-off' class of the svg that FontAwesome created in the button ⤸
            btnToggle.firstChild.classList.toggle('fa-toggle-off');
            //⤹ Toggle the 'fa-toggle-on' class of the svg that FontAwesome created in the button ⤸
            btnToggle.firstChild.classList.toggle('fa-toggle-on');
            //⤹ set the local storage with the class list of the element ⤸
            localStorage.setItem('theme', JSON.stringify(htmlElement.classList.value.split(' ')) );
        })
    </script>
</body>
</html>
-HTMLFORM END
 

This message has been edited. Last edited by: Hallway,


Hallway

 
Prod: 8202M1
Test: 8202M4
Repository:
 
OS:
 
Outputs:
 
 
 
 
January 27, 2020, 03:05 PM
Waz
Interesting.....


Waz...

Prod:WebFOCUS 7.6.10/8.1.04Upgrade:WebFOCUS 8.2.07OS:LinuxOutputs:HTML, PDF, Excel, PPT
In Focus since 1984
Pity the lost knowledge of an old programmer!

January 27, 2020, 03:14 PM
Hallway
I should add that it only works on modern browsers (RIP IE)


Hallway

 
Prod: 8202M1
Test: 8202M4
Repository:
 
OS:
 
Outputs:
 
 
 
 
February 21, 2020, 02:24 PM
Shingles
Nice. I spent about a month adding the ability to toggle between a dark and light theme on all our portals. I did it quite a bit differently. Your's is probably easier, but I really like my approach too. I have much more control as to the colours that are used and I can use more than two themes.

Basically I created a new portal where users can select a dark or light theme via a drop down (I used a drop down in case we want to add a third colour theme). The user's selection is saved to a table in the data warehouse. Then each fex runs some code to read that table (via an -INCLUDE) and then set one of two sets of variables. For example if dark is chosen, then we include dark.sty which sets &BACKCOL1 = '#112233'. If light is chosen then light.sty is used which sets &BACKCOL01 = '#FFFFFF'. And then it was just modifying the stylesheet used by our tables and chart fexes to use &BACKCOL01 instead of the hard coded colour that was there before.

Really fun exercise. And I got the chance to really let those creative juices flow. It took long to do only because I had to modify and test each and every dashboard (we have about 13). And each of those are made up by 5-40 fexes. The logic is pretty simple though:
1) Read a file
2) Set one of two sets of variables (light.sty or dark.sty). The variables in each of these are the same, but their values are different.
3) Include the stylesheet that uses the vars from step 2

This message has been edited. Last edited by: Shingles,


WebFOCUS 8201, SP 0.1, Windows 7, HTML