Build a Theme Switcher - Build a Theme Switcher

Tell us what’s happening:

Hi everyone !
I have an issue with this one. I can’t find what’s wrong. It seems fine when I run it.
Test 26 and test 27 do not pass.

Here is the challenge : Build a Theme Picker

Your code so far

<!-- file: index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Theme Switcher</title>
  <link rel="stylesheet" href="./styles.css">
</head>

<body>
  <button id="theme-switcher-button" class="dropdown-btn" aria-haspopup="true" aria-expanded="false" aria-controls="theme-dropdown">Switch Theme</button>
  <ul id="theme-dropdown" class="dropdown-content" role="menu"  aria-labelledby="theme-switcher-button" hidden>
    <li id="theme-light" class="dropdown-item" role="menuitem">Light</li>
    <li id="theme-dark" class="dropdown-item" role="menuitem">Dark</li>
    <li id="theme-ocean" class="dropdown-item" role="menuitem">Ocean</li>
    <li id="theme-nord" class="dropdown-item" role="menuitem">Nord</li>
  </ul>
  <div id="status" aria-live="polite">

  </div>
  <script src="./script.js"></script>
</body>

</html>
/* file: styles.css */
body {
  margin: 0;
  font-family: sans-serif;
  transition: background 0.3s, color 0.3s;
}

ul {
  margin: 0;
  padding: 0;
}

li {
  list-style-type: none;
}

.dropdown-btn {
  position: relative;
  padding: 10px 20px;
  border: none;
  cursor: pointer;
}

.dropdown-content {
  position: absolute;
  background-color: #ffffff;
  min-width: 160px;
  box-shadow: 0px 4px 8px rgba(0,0,0,0.2);
  z-index: 1;
}

.dropdown-item {
  width: 100%;
  padding: 12px;
  color: #000000;
  background-color: #ffffff;
  cursor: pointer;
}

.dropdown-item:hover {
  background-color: #f1f1f1;
}

#status {
  text-align: center;
  min-height: 20px;
}

/* Themes */
.theme-light {
  background-color: #ffffff;
  color: #000000;
}

.theme-light .dropdown-btn {
  background-color: #d3b3aa;
  color: #000000;
}

.theme-dark {
  background-color: #121212;
  color: #ffffff;
}

.theme-dark .dropdown-btn {
  background-color: #4f4f4f;
  color: #ffffff;
}

.theme-ocean {
  background-color: #0077be;
  color: #e0f7fa;
}

.theme-ocean .dropdown-btn {
  background-color: #193e51;
  color: #ffffff;
}

.theme-nord {
  background-color: #2e3440;
  color: #d8dee9;
}

.theme-nord .dropdown-btn {
  background-color: #596680;
  color: #ffffff;
}
/* file: script.js */
const themes = [
  {name: "light",
  message: "Hello sunshine — Light theme is on!"},
  {name: "dark",
  message: "The night is yours — Dark theme is on!"},
  {name: "ocean",
  message: "Blue skies and high tides — Ocean theme is on!"},
  {name: "nord",
  message: "The frost has settled - Nord theme is on!"}
];


const themeSwitcherButton = document.getElementById("theme-switcher-button");
const themeList = document.getElementById("theme-dropdown");
const body = document.body;
const statusArea = document.querySelector('[aria-live="polite"]');

themeSwitcherButton.addEventListener("click", () => {
  const isExpanded = themeSwitcherButton.getAttribute("aria-expanded") === "true";
  themeList.hidden = !themeList.hidden;
  themeSwitcherButton.setAttribute("aria-expanded", String(!isExpanded));
});

themeList.addEventListener("click", (event) => {
  const listItem = event.target.closest('li[role="menuitem"]');
    
    // Vérifie si le clic est bien sur un élément du menu
    if (!listItem) return;

    // Récupère le nom du thème 
    const newThemeClass = listItem.id;

    // Récupère les données complètes du thème
    const themeName = newThemeClass.replace("theme-", "");
    const selectedTheme = themes.find(theme => theme.name === themeName);
    
    if (selectedTheme) {
        // Récupère tous les noms de thèmes pour les retirer
        const allThemeNames = themes.map(theme => `theme-${theme.name}`); 
        
        // Enlève toutes les classes de thème
        body.classList.remove(...allThemeNames);

        // Applique le thème au body en lui ajoutant la classe
        body.classList.add(newThemeClass);

        // Affiche le message de statut
        statusArea.textContent = selectedTheme.message;

        // Ferme le menu
        themeList.hidden = true;
        themeSwitcherButton.setAttribute("aria-expanded", "false");
    }
})


Your browser information:

User Agent is: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36

Challenge Information:

Build a Theme Switcher - Build a Theme Switcher

There’s an error of sorts in the tester: It won’t pass those steps if you have the event listener (IMO correctly) on the parent element. Refactor to put separate listeners on each sub-element.

I submitted a Github issue about this a few weeks ago, and last I checked, someone had submitted a solution but it hadn’t yet been pulled into the main branch. I guess that must still be the case.

1 Like

Yes thank you. So I made the modifications as indicated with the forEach() method on eacj list item and it passed all the tests.

2 Likes