The Light Theme Dilemma

Throwback

 A year ago (around March or April 2022) I was working on the hardest function of the WhatsApp Chatlog Interpreter yet, the Light Theme option. This was especially hard because the biggest projects that I have ever worked on, are not particularly oriented to design or frontend in general.

Cereza, and some other secret projects of mine that never saw light, were discord bots with more than 1000 lines of code in total. Now, I know that 1000 lines is not really that much, but keep in mind that those projects are the result of months of work and optimization, so they are some pretty valuable 1000 lines to me.
What I'm really trying to say, is that the vast majority of my coding experience is in the backend side of things, Cereza and the other bots that I'm talking about worked entirely in NodeJS, with no real design to be made.

That's why frontend and CSS in general represent a challenge to me, so I got to catch up and develop some skills there.

Desperation

I admit it, I got to a point in which I was so desperate, I started doing and adding libraries and code that I didn't fully understand. I know that jQuery is a decent JavaScript library, but I just don't know how to use it properly, and the lines of code that I used with jQuery, were straight up copy-and-paste. Just look at this aberration:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
	if(darkmode == true)
	{
		console.log("PRIMERA VEZ")

		$("div.message" ).find( "p" ).css( "background-color", "#d9fdd3");
		//FONDO DEL CHAT
		$("div.rightSide").css("background-color", "#efeae2");
		$("div.rightSide").css("background-image", "url(images/pattern.png)");
		$("div.rightSide").css("content", "''")
		$("div.rightSide").css("position", "absolute")
		$("div.rightSide").css("top", "0")
		$("div.rightSide").css("left", "0")
		//$("div.container.rightside").css("background", "url(images/pattern.png")
		$("div.rightSide").css("opacity", "1")

		$("div.header").css("background-color", "#f0f2f5");
		$("button.button1").css("background-color", "#06cf9c");
		$("div.message" ).find( "p" ).css( "color", "#111b21" );

		$("button.button3").css("background-color", "#f0f2f5");
		$("button.button4").css("background-color", "#f0f2f5");

		document.getElementById("botonsillomodos").textContent = "Dark Mode";
		darkmode = false;
	}
	else if(darkmode == false)
	{
		console.log("SEGUNDA VEZ");

		$("div.message" ).find( "p" ).css( "background-color", "#005c4b");
		//FONDO DEL CHAT
		//$("div.chatbox").css("background-image", "url(images/pattern.png)", "opacity: 0.06");
		$('head').append("<style>.chatbox:before { opacity:0.6; }</style>");
		$("div.rightSide").css("background-color", "#0b141a");

		$("div.header").css("background-color", "#202c33");
		$("button.button1").css("background-color", "#00a884");
		$("div.message" ).find( "p" ).css( "color", "#111b21" );
		$(this).css('background', 'linear-gradient(135deg, #d9fdd3 0%, #d9fdd3 50%, transparent 50%, transparent');

		$("button.button3").css("background-color", "#005c4b");
		$("button.button4").css("background-color", "#005c4b");

		document.getElementById("botonsillomodos").textContent = "Dark Mode";

		darkmode = true;
	}

If you don't understand anything at all, don't worry, because neither do I.

It really isn't that hard

It's been two days and now that I took my good 20 minutes of actually learning CSS and putting the minimum effort to understand how some DOM properties in JavaScript work, I now have learned that jQuery was not necessary at all.

To create a decent Light Theme feature, you must:
  • First, define a Class Selector in CSS, its name could be "light-mode"
  • Define a function in JavaScript, and by element.classList.toggle("lightmode") you can add that class to the element if it doesn't exist, and delete that class from the element if it does.
  • Optionally, you can save the CSS color codes in variables, so you can just change a single variable and it will automatically apply to the rest of the code.
It really isn't that hard, but for a CSS illiterate like me, it kind of was.
Let's get to work.

I will start by deleting the 50 lines of absolute nonsense code that I wrote in the past because I didn't want to take my time to actually learn something new (deleting inadequate lines of code gives out the same satisfaction as cleaning your room, I'm not kidding).
Then, I will define variable colors, so I don't have to change everything every time the colors change. You can define variables in CSS this way:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
:root {
  --obscure: #202c33;
  --dark-green: #005c4b;
  --chatbox-background: #00a884 ;
  --almost-black: #0b141a;
  --very-obscure-green: #182229;
  --fingwhite: white;
  --textofmessages: #e9edef;
  --button-background: #06cf9c;
}

Now, I make some live color tests on the browser with chrome developer tools, here, I can change the colors instantly without changing the original file.

For knowing which colors to use so I can simulate the real WhatsApp, I use a tool called CSS Pepper, you just click on DOM elements and it shows all its CSS properties. In fact, that very tool helped me realize that I wasn't using a font for the message divs, so I added Segoe UI to the font-family property, and now it almost looks identical.

Little bit of trouble

I'm having some problems, the toggle("lightmode") function works apart from the function that changes the color of the buttons in CSS; and the background doesn't change colors automatically, but only in the developer tools when the variable color is changed. Also, the background color variable only get recognized when declared in the :root selector, hence the background doesn't changing colors automatically.
I have really been working really hard to get to this point, I had to change a lot of things for reasons I didn't even expect, for example, the colors in JavaScript don't work with HEX, but with RGB. And also I got the Light Mode button to work partially, although with some bugs.
It's really late and I think I did some advancements, we'll call it a day.
Tomorrow, I'll have to:
  • Rework the function that changes the color of the buttons
  • Figure out why some variables don't change automatically in CSS
Good night!

The next day

Good afternoon!
I was taking a look at the background color design, and found that it was not exactly identical to the original WhatsApp Web one, so I made some small adjustments, like changing the background color a little bit, and setting the opacity to 0.4 instead of 0.06; and using just one image for the background pattern.

To know which exact opacity to use, I used chrome developer tools to search for the opacity property in the original WhatsApp Web:


And yes, as you can see, another monitor would really come in handy when working with these things


Now, time to rework some color-changing functions!
First, I had to delete the old way of changing colors, which was this:
1
2
button1.style.backgroundColor(color1);
button2.style.backgroundColor(color2);

Now, I defined the following CSS variables and classes:
1
2
3
4
5
6
7
.selectedButton {
  --colorback: var(--selected-button-background);
}

.unSelectedButton {
  --colorback: var(--unselected-button-background);
}

The --selected-button-background variable is at the same time declared within the .dark-mode and .light-mode selector values. 
Then, inside the button selectors, I use the --colorback variable:
1
  background-color: var(--colorback);

(That for each user button).

Now, the JavaScript code that adds and removes classes looks like this:
1
2
3
4
select.classList.add("selectedButton");
select.classList.remove("unSelectedButton");
unselect.classList.add("unSelectedButton");
unselect.classList.remove("SelectedButton");

I was surprised to see that this worked right away. Also, now I don't have to mess around with RGB color codes.

Now, I will try to solve the background not changing color problem.

Turns out, that it was because the background, is part of the body property in html, so changing the class of the container to dark mode didn't affect the body itself, to fix this, I can also alter the body of the document, like this:
1
2
3
4
container.classList.toggle("lightmode");
container.classList.toggle("darkmode");
document.body.classList.toggle("lightmode");
document.body.classList.toggle("darkmode");

Now it works as expected.

A little mention on the things that I didn't explain

There were a lot of challenges and problem while working around this function that I didn't explain. But I will mention them a little bit on the following list:

  • I tried to optimize some stuff that didn't end up working in the function that creates the message divs.
  • I had to add back another two arguments to the onclick="botonejecutar()" function because there was a bug that involved the buttons' colors getting confused.
  • There were some tests to see if optimizing the code even more was a possibility, but most of the time there was not a viable option to do so.
  • The way the color variables are declared are not good practice.
  • This post and this code journey was not made in two days, but a little bit more.
So yes, there were a lot of work that I didn't register here, but I always try to keep a good balance between coding and blogging, so I don't make these posts too shallow, or lose flow state.

Now, the Light and Dark Mode button works completely well, thanks for reading!

Comments

Popular posts from this blog

An Audioguide about the Geology of Ecuador

Active Projects as of Today

Explaining Color-Driven Summation