Build a Theme Switcher - Build a Theme Switcher

Tell us what’s happening:

i cant pass this what wrong?

  1. When a user clicks the #theme-switcher-button and selects a theme, a message related to the selected theme from the themes array should be displayed in the aria-live=“polite” element.

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>
  <div class="content">
    <h1>Accessible Theme Switcher Demo</h1>
    
    <div class="theme-switcher">
      <button 
        id="theme-switcher-button" 
        aria-haspopup="true" 
        aria-expanded="false" 
        aria-controls="theme-dropdown"
      >
        Switch Theme
      </button>
      
      <ul 
        id="theme-dropdown" 
        role="menu" 
        aria-labelledby="theme-switcher-button" 
        hidden
      >
      <li id="theme-light" role="menu-item" tabindex="0">Light</li>
<li id="theme-dark" role="menu-item" tabindex="0">Dark</li>
<li id="theme-blue" role="menu-item" tabindex="0">Blue</li>
<li id="theme-green" role="menu-item" tabindex="0">Green</li>

      </ul>
    </div>

    <div id="status" aria-live="polite"></div>

    <p>This is a sample paragraph to demonstrate the theme changes. Click the "Switch Theme" button above to try different themes. The theme switcher is fully accessible with proper ARIA attributes and keyboard navigation support.</p>
    
    <p>Each theme changes the background and text colors to provide a different visual experience while maintaining good contrast for readability.</p>
  </div>

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

body {
  margin: 0;
  font-family: sans-serif;
  transition: background 0.3s, color 0.3s;
  padding: 20px;
  min-height: 100vh;
}

body {
  background-color: #ffffff;
  color: #333333;
}

.theme-light {
  background-color: #ffffff;
  color: #333333;
}

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

.theme-blue {
  background-color: #1e3a8a;
  color: #dbeafe;
}

.theme-green {
  background-color: #166534;
  color: #dcfce7;
}

ul {
  margin: 0;
  padding: 0;
}

li {
  list-style-type: none;
}

#status {
  text-align: center;
  min-height: 20px;
  margin: 20px 0;
  font-weight: bold;
}

.theme-switcher {
  position: relative;
  display: inline-block;
  margin: 20px;
}

#theme-switcher-button {
  background: #007acc;
  color: white;
  border: none;
  padding: 10px 15px;
  border-radius: 5px;
  cursor: pointer;
  font-size: 16px;
  transition: background 0.2s;
}

#theme-switcher-button:hover {
  background: #005ea8;
}

#theme-switcher-button:focus {
  outline: 2px solid #ffd700;
  outline-offset: 2px;
}

#theme-dropdown {
  position: absolute;
  top: 100%;
  left: 0;
  background: white;
  border: 1px solid #ccc;
  border-radius: 5px;
  box-shadow: 0 2px 10px rgba(0,0,0,0.1);
  min-width: 150px;
  z-index: 1000;
}

#theme-dropdown[hidden] {
  display: none;
}

#theme-dropdown li {
  padding: 10px 15px;
  cursor: pointer;
  transition: background 0.2s;
}

#theme-dropdown li:hover {
  background: #f0f0f0;
}

#theme-dropdown li:focus {
  outline: 2px solid #007acc;
  outline-offset: -2px;
  background: #f0f0f0;
}

.theme-dark #theme-dropdown {
  background: #2a2a2a;
  border-color: #555;
  color: white;
}

.theme-dark #theme-dropdown li:hover,
.theme-dark #theme-dropdown li:focus {
  background: #3a3a3a;
}

.theme-blue #theme-dropdown {
  background: #1e40af;
  border-color: #3b82f6;
  color: #dbeafe;
}

.theme-blue #theme-dropdown li:hover,
.theme-blue #theme-dropdown li:focus {
  background: #1d4ed8;
}

.theme-green #theme-dropdown {
  background: #166534;
  border-color: #22c55e;
  color: #dcfce7;
}

.theme-green #theme-dropdown li:hover,
.theme-green #theme-dropdown li:focus {
  background: #15803d;
}

.content {
  max-width: 800px;
  margin: 0 auto;
  padding: 20px;
}

h1 {
  text-align: center;
}
/* file: script.js */
const themes = [
  { name: 'light', message: 'Light theme activated - bright and clean!' },
  { name: 'dark', message: 'Dark theme activated - easy on the eyes!' },
  { name: 'blue', message: 'Blue theme activated - calm and professional!' },
  { name: 'green', message: 'Green theme activated - natural and soothing!' }
];

const button = document.getElementById('theme-switcher-button');
const dropdown = document.getElementById('theme-dropdown');
const status = document.getElementById('status');
const menuItems = dropdown.querySelectorAll('li[role="menu-item"]');
const body = document.body;

function toggleDropdown() {
  const isHidden = dropdown.hasAttribute('hidden');
  
  if (isHidden) {
    dropdown.removeAttribute('hidden');
    button.setAttribute('aria-expanded', 'true');
  } else {
    dropdown.setAttribute('hidden', '');
    button.setAttribute('aria-expanded', 'false');
  }
}

function closeDropdown() {
  dropdown.setAttribute('hidden', '');
  button.setAttribute('aria-expanded', 'false');
}

function applyTheme(themeName) {
  themes.forEach(theme => {
    body.classList.remove(`theme-${theme.name}`);
  });
  
  body.classList.add(`theme-${themeName}`);
  for (let i = 0; i < themes.length; i++) {
    if (themes[i].name === themeName) {
      status.textContent = themes[i].message;
      break;
    }
  }
  closeDropdown();
}

button.addEventListener('click', (e) => {
  e.stopPropagation();
  toggleDropdown();
});

menuItems.forEach(item => {
  item.addEventListener('click', (e) => {
    e.preventDefault();
    e.stopPropagation();
    const themeName = item.id.replace('theme-', '');
    applyTheme(themeName);
  });

  item.addEventListener('keydown', (e) => {
    if (e.key === 'Enter' || e.key === ' ') {
      e.preventDefault();
      const themeName = item.id.replace('theme-', '');
      applyTheme(themeName);
    } else if (e.key === 'Escape') {
      closeDropdown();
      button.focus();
    }
  });
});

document.addEventListener('click', (e) => {
  if (!button.contains(e.target) && !dropdown.contains(e.target)) {
    closeDropdown();
  }
});

button.addEventListener('keydown', (e) => {
  if (e.key === 'Escape') {
    closeDropdown();
  }
});

applyTheme('light');

Your browser information:

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

Challenge Information:

Build a Theme Switcher - Build a Theme Switcher

https://www.freecodecamp.org/learn/full-stack-developer/lab-theme-switcher/lab-theme-switcher

have you tested by selecting a theme and checking the content of the element in dev tools? (it remains empty when I tried it)

Check the role on your items — it should be menuitem (no hyphen).
Also, make sure the aria-live=“polite” status actually updates with the message from the themes array when a theme is picked.
That small fix should do the trick :+1:

if you remove the hyphen you’ll fail test 13

Thanks a lot, I see the issue and fixed it. It worked!!

1 Like

What was the problem and can you shareon how you fixed?

The instructions indicate there should be a hyphen “menu-item”

that’s a bug with the lab, it’s going to be fixed soon