From 8790d3c19e0c28d030e2ebc12d6a473411e03512 Mon Sep 17 00:00:00 2001 From: Michael Czechowski Date: Fri, 16 Jan 2026 03:50:01 +0100 Subject: [PATCH] feat: implement section-based color coding - Add CSS variables for section colors (CSS violet, HTML raspberry, Tailwind cyan) - Set data-section attribute on body based on current route - Color code header nav links, logo, reference nav, topic links - Color code CodeMirror editor cursor/selection - Color code task instruction bubble - Add reference page footer - Section pages, lessons, and references all use matching colors --- src/app.js | 26 +++++++ src/index.html | 3 + src/main.css | 205 ++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 230 insertions(+), 4 deletions(-) diff --git a/src/app.js b/src/app.js index 1c1392d..b417b56 100644 --- a/src/app.js +++ b/src/app.js @@ -1982,6 +1982,18 @@ function hideAllPages() { elements.gameLayout?.classList.add("hidden"); } +/** + * Update section color coding on body + * @param {string|null} sectionId - Section ID (css, html, tailwind) or null to reset + */ +function updateSectionColor(sectionId) { + if (sectionId) { + document.body.setAttribute("data-section", sectionId); + } else { + document.body.removeAttribute("data-section"); + } +} + /** * Show home landing page */ @@ -1990,6 +2002,9 @@ function showLandingPage() { elements.landingPage?.classList.remove("hidden"); window.scrollTo(0, 0); + // Reset section color on landing page + updateSectionColor(null); + // Update section progress on landing page updateLandingProgress(); @@ -2062,6 +2077,9 @@ function showSectionPage(sectionId) { elements.sectionPage?.classList.remove("hidden"); window.scrollTo(0, 0); + // Update section color + updateSectionColor(sectionId); + // Track section page view track("section_view", { section: sectionId }); @@ -2113,6 +2131,10 @@ function showReferencePage(refId) { // Default to CSS if no refId const activeRef = refId || "css"; + // Map reference to section for color coding + const refToSection = { css: "css", selectors: "css", flexbox: "css", grid: "css", html: "html" }; + updateSectionColor(refToSection[activeRef] || "css"); + // Track reference page view track("reference_view", { ref: activeRef }); @@ -2256,10 +2278,14 @@ function navigateToLesson(moduleId, lessonIndex, shouldUpdateUrl = true) { lessonEngine.setLessonByIndex(0); loadCurrentLesson(); updateModuleHighlight(fallbackModule.id); + updateSectionColor(getModuleSection(fallbackModule)); } return; } + // Update section color based on module + updateSectionColor(getModuleSection(module)); + // Validate lessonIndex is in bounds if (lessonIndex < 0 || lessonIndex >= module.lessons.length) { // Invalid lesson - go to first lesson of module diff --git a/src/index.html b/src/index.html index 5d2ecf9..173e00f 100644 --- a/src/index.html +++ b/src/index.html @@ -243,6 +243,9 @@ +
diff --git a/src/main.css b/src/main.css index 5ff2762..b876cdf 100644 --- a/src/main.css +++ b/src/main.css @@ -5,6 +5,12 @@ --primary-light: #8a77b5; --primary-dark: #3b2e63; + /* Section colors (default to primary) */ + --section-color: var(--primary-color); + --section-color-light: var(--primary-light); + --section-color-dark: var(--primary-dark); + --section-color-rgb: 94, 75, 139; + /* Secondary colors */ --secondary-color: #444444; --secondary-dark: #222222; @@ -2149,7 +2155,7 @@ input:checked + .toggle-slider::before { gap: 0.5rem; margin-top: 1.25rem; padding: 0.75rem 1.5rem; - background: var(--primary-color); + background: var(--section-color, var(--primary-color)); color: white; text-decoration: none; border-radius: var(--border-radius-md); @@ -2163,7 +2169,7 @@ input:checked + .toggle-slider::before { } .topic-link:hover { - background: var(--primary-dark); + background: var(--section-color-dark, var(--primary-dark)); transform: translateY(-1px); box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15); } @@ -2187,7 +2193,7 @@ input:checked + .toggle-slider::before { } .topic-ref:hover { - color: var(--primary-color); + color: var(--section-color, var(--primary-color)); text-decoration: underline; } @@ -2199,7 +2205,7 @@ input:checked + .toggle-slider::before { } .section-see-also a { - color: var(--primary-color); + color: var(--section-color, var(--primary-color)); text-decoration: none; } @@ -2840,3 +2846,194 @@ input:checked + .toggle-slider::before { direction: ltr; text-align: left; } + +/* ================= SECTION COLOR CODING ================= */ +/* CSS Section - Violet */ +[data-section="css"] { + --section-color: #7c4dff; + --section-color-light: #a47fff; + --section-color-dark: #5c35cc; + --section-color-rgb: 124, 77, 255; +} + +/* HTML Section - Raspberry */ +[data-section="html"] { + --section-color: #e91e63; + --section-color-light: #f06292; + --section-color-dark: #c2185b; + --section-color-rgb: 233, 30, 99; +} + +/* Tailwind Section - Cyan */ +[data-section="tailwind"] { + --section-color: #00bcd4; + --section-color-light: #4dd0e1; + --section-color-dark: #0097a7; + --section-color-rgb: 0, 188, 212; +} + +/* Apply section colors to nav links */ +.nav-link[data-section="css"] { + color: #7c4dff; +} + +.nav-link[data-section="html"] { + color: #e91e63; +} + +.nav-link[data-section="tailwind"] { + color: #00bcd4; +} + +.nav-link[data-section="css"]:hover, +.nav-link[data-section="css"].active { + background: rgba(124, 77, 255, 0.1); + color: #5c35cc; +} + +.nav-link[data-section="html"]:hover, +.nav-link[data-section="html"].active { + background: rgba(233, 30, 99, 0.1); + color: #c2185b; +} + +.nav-link[data-section="tailwind"]:hover, +.nav-link[data-section="tailwind"].active { + background: rgba(0, 188, 212, 0.1); + color: #0097a7; +} + +/* Logo color coding based on section */ +[data-section="css"] .code-text { + color: #7c4dff; +} + +[data-section="html"] .code-text { + color: #e91e63; +} + +[data-section="tailwind"] .code-text { + color: #00bcd4; +} + +/* Reference nav link colors */ +.ref-nav-link[data-ref="css"], +.ref-nav-link[data-ref="selectors"], +.ref-nav-link[data-ref="flexbox"], +.ref-nav-link[data-ref="grid"] { + color: #7c4dff; +} + +.ref-nav-link[data-ref="css"]:hover, +.ref-nav-link[data-ref="css"].active, +.ref-nav-link[data-ref="selectors"]:hover, +.ref-nav-link[data-ref="selectors"].active, +.ref-nav-link[data-ref="flexbox"]:hover, +.ref-nav-link[data-ref="flexbox"].active, +.ref-nav-link[data-ref="grid"]:hover, +.ref-nav-link[data-ref="grid"].active { + background: rgba(124, 77, 255, 0.15); + color: #5c35cc; +} + +.ref-nav-link[data-ref="html"] { + color: #e91e63; +} + +.ref-nav-link[data-ref="html"]:hover, +.ref-nav-link[data-ref="html"].active { + background: rgba(233, 30, 99, 0.15); + color: #c2185b; +} + +/* CodeMirror section color overrides */ +[data-section="css"] .cm-content { + caret-color: #7c4dff; +} + +[data-section="css"] .cm-cursor, +[data-section="css"] .cm-dropCursor { + border-left-color: #7c4dff !important; +} + +[data-section="css"] .cm-searchMatch { + outline-color: #7c4dff; +} + +[data-section="css"] .cm-searchMatch.cm-searchMatch-selected { + background-color: rgba(124, 77, 255, 0.3); +} + +[data-section="html"] .cm-content { + caret-color: #e91e63; +} + +[data-section="html"] .cm-cursor, +[data-section="html"] .cm-dropCursor { + border-left-color: #e91e63 !important; +} + +[data-section="html"] .cm-searchMatch { + outline-color: #e91e63; +} + +[data-section="html"] .cm-searchMatch.cm-searchMatch-selected { + background-color: rgba(233, 30, 99, 0.3); +} + +[data-section="tailwind"] .cm-content { + caret-color: #00bcd4; +} + +[data-section="tailwind"] .cm-cursor, +[data-section="tailwind"] .cm-dropCursor { + border-left-color: #00bcd4 !important; +} + +[data-section="tailwind"] .cm-searchMatch { + outline-color: #00bcd4; +} + +[data-section="tailwind"] .cm-searchMatch.cm-searchMatch-selected { + background-color: rgba(0, 188, 212, 0.3); +} + +/* Task instruction bubble section colors */ +[data-section="css"] .task-instruction { + background: rgba(124, 77, 255, 0.9); +} + +[data-section="html"] .task-instruction { + background: rgba(233, 30, 99, 0.9); +} + +[data-section="tailwind"] .task-instruction { + background: rgba(0, 188, 212, 0.9); +} + +/* Section page header colors */ +[data-section="css"] .section-hero h1 { + color: #7c4dff; +} + +[data-section="html"] .section-hero h1 { + color: #e91e63; +} + +[data-section="tailwind"] .section-hero h1 { + color: #00bcd4; +} + +/* Reference footer */ +.reference-footer { + text-align: center; + padding: 2rem 1rem; + margin-top: 3rem; + border-top: 1px solid var(--border-color); + color: var(--light-text); + font-size: 0.9rem; +} + +.reference-footer a { + color: var(--section-color, var(--primary-color)); +}