feat: add header level pill on desktop, use native details/summary for sidebar

- Add lesson indicator pill to header (visible on desktop only)
- Logo stays centered, pill on left with burger menu
- Replace emoji arrows with CSS triangles for iOS compatibility
- Use native <details>/<summary> for expand/collapse
- Update tests for new implementation
This commit is contained in:
2026-01-14 17:51:34 +01:00
parent 954f82b27c
commit 72362de88b
5 changed files with 106 additions and 63 deletions

View File

@@ -32,30 +32,21 @@ export function renderModuleList(container, modules, onSelectModule, onSelectLes
// Create list items for each module
modules.forEach((module) => {
// Create module container
const moduleContainer = document.createElement("div");
// Use native <details>/<summary> for expand/collapse
const moduleContainer = document.createElement("details");
moduleContainer.classList.add("module-container");
moduleContainer.setAttribute("role", "treeitem");
moduleContainer.dataset.moduleId = module.id;
// Create module header item (clickable to expand/collapse)
const moduleHeader = document.createElement("button");
moduleHeader.type = "button";
// Create module header using <summary>
const moduleHeader = document.createElement("summary");
moduleHeader.classList.add("module-list-item", "module-header");
moduleHeader.dataset.moduleId = module.id;
moduleHeader.setAttribute("aria-expanded", "false");
moduleHeader.setAttribute("aria-controls", `lessons-${module.id}`);
// Create module title with expand/collapse indicator
// Create module title
const moduleTitle = document.createElement("span");
moduleTitle.classList.add("module-title");
moduleTitle.textContent = module.title;
// Create expand/collapse icon
const expandIcon = document.createElement("span");
expandIcon.classList.add("expand-icon");
expandIcon.setAttribute("aria-hidden", "true");
expandIcon.innerHTML = "▶"; // Right-pointing triangle
moduleHeader.appendChild(expandIcon);
moduleHeader.appendChild(moduleTitle);
// Check if the module is completed
@@ -63,13 +54,10 @@ export function renderModuleList(container, modules, onSelectModule, onSelectLes
moduleHeader.classList.add("completed");
}
// Lessons container (initially hidden)
// Lessons container
const lessonsContainer = document.createElement("div");
lessonsContainer.classList.add("lessons-container");
lessonsContainer.id = `lessons-${module.id}`;
lessonsContainer.setAttribute("role", "group");
lessonsContainer.setAttribute("aria-label", `${module.title} lessons`);
lessonsContainer.style.display = "none"; // Initially collapsed
// Create list items for each lesson in this module
module.lessons.forEach((lesson, index) => {
@@ -105,17 +93,6 @@ export function renderModuleList(container, modules, onSelectModule, onSelectLes
lessonsContainer.appendChild(lessonItem);
});
// Toggle expand/collapse when clicking on module header
moduleHeader.addEventListener("click", () => {
// Toggle visibility of lessons container
const isExpanded = lessonsContainer.style.display !== "none";
lessonsContainer.style.display = isExpanded ? "none" : "block";
// Update expand/collapse icon and ARIA state
expandIcon.innerHTML = isExpanded ? "▶" : "▼";
moduleHeader.setAttribute("aria-expanded", String(!isExpanded));
});
// Add module header and lessons container to module container
moduleContainer.appendChild(moduleHeader);
moduleContainer.appendChild(lessonsContainer);
@@ -233,20 +210,10 @@ export function updateActiveLessonInSidebar(moduleId, lessonIndex) {
if (currentLessonItem) {
currentLessonItem.classList.add("active");
// Make sure parent module is expanded
const parentLessonsContainer = currentLessonItem.parentElement;
if (parentLessonsContainer && parentLessonsContainer.classList.contains("lessons-container")) {
parentLessonsContainer.style.display = "block";
// Update expand icon and ARIA state
const moduleHeader = parentLessonsContainer.previousElementSibling;
if (moduleHeader) {
moduleHeader.setAttribute("aria-expanded", "true");
const expandIcon = moduleHeader.querySelector(".expand-icon");
if (expandIcon) {
expandIcon.innerHTML = "▼"; // Down arrow when expanded
}
}
// Make sure parent module is expanded (native <details> element)
const parentDetails = currentLessonItem.closest("details.module-container");
if (parentDetails) {
parentDetails.open = true;
// Scroll to the top of the page
document.querySelector("html").scrollTop = 0;