feat: implement responsive hamburger menu and enhance header layout

This commit is contained in:
Michael Czechowski
2025-05-20 00:52:23 +02:00
parent 371ff7bafa
commit 593faacf4c
3 changed files with 316 additions and 4 deletions

View File

@@ -611,6 +611,57 @@ function init() {
e.preventDefault(); e.preventDefault();
} }
}); });
// Add this to your app.js file
// Mobile Menu Functionality
document.addEventListener("DOMContentLoaded", function () {
// Create hamburger menu button
const hamburger = document.createElement("button");
hamburger.className = "hamburger";
hamburger.setAttribute("aria-label", "Toggle menu");
hamburger.innerHTML = `
<span class="hamburger-line"></span>
<span class="hamburger-line"></span>
<span class="hamburger-line"></span>
`;
// Get the header and nav elements
const header = document.querySelector(".header");
const logo = document.querySelector(".logo");
const nav = document.querySelector(".main-nav");
// Insert hamburger button after the logo
header.insertBefore(hamburger, logo.nextSibling);
// Toggle menu on hamburger click
hamburger.addEventListener("click", function () {
nav.classList.toggle("open");
hamburger.classList.toggle("open");
// Set aria-expanded attribute for accessibility
const isExpanded = nav.classList.contains("open");
hamburger.setAttribute("aria-expanded", isExpanded);
});
// Close menu when clicking outside
document.addEventListener("click", function (event) {
if (!nav.contains(event.target) && !hamburger.contains(event.target) && nav.classList.contains("open")) {
nav.classList.remove("open");
hamburger.classList.remove("open");
hamburger.setAttribute("aria-expanded", false);
}
});
// Close menu when window is resized to desktop size
window.addEventListener("resize", function () {
if (window.innerWidth > 768 && nav.classList.contains("open")) {
nav.classList.remove("open");
hamburger.classList.remove("open");
hamburger.setAttribute("aria-expanded", false);
}
});
});
} }
// Start the application // Start the application

View File

@@ -17,10 +17,10 @@ import responsiveConfig from "../../lessons/08-responsive.json";
// Module store // Module store
const moduleStore = [ const moduleStore = [
// basicsConfig, // basicsConfig,
basicSelectorsConfig basicSelectorsConfig,
// boxModelConfig, boxModelConfig,
// selectorsConfig, selectorsConfig,
// colorsConfig, colorsConfig
// typographyConfig, // typographyConfig,
// unitVariablesConfig, // unitVariablesConfig,
// transitionsAnimationsConfig, // transitionsAnimationsConfig,

View File

@@ -708,3 +708,264 @@ input:checked + .toggle-slider:before {
font-size: 14px; font-size: 14px;
color: var(--text-color); color: var(--text-color);
} }
/* Hamburger Menu Icon */
.hamburger {
display: none;
cursor: pointer;
flex-direction: column;
justify-content: space-around;
width: 30px;
height: 21px;
background: transparent;
border: none;
padding: 0;
}
.hamburger-line {
display: block;
width: 100%;
height: 3px;
background-color: var(--text-color);
border-radius: 10px;
transition: all 0.3s ease;
}
/* Responsive Header Adjustments */
@media (max-width: 768px) {
.header {
flex-wrap: wrap;
padding: var(--spacing-md);
}
.logo {
flex: 1;
}
.hamburger {
display: flex;
order: 2;
}
.main-nav {
width: 100%;
order: 3;
height: 0;
overflow: hidden;
transition: height 0.3s ease;
}
.main-nav.open {
height: auto;
margin-top: var(--spacing-md);
}
.main-nav ul {
flex-direction: column;
width: 100%;
align-items: flex-start;
gap: var(--spacing-sm);
}
.main-nav ul li {
width: 100%;
}
.main-nav ul li .btn {
width: 100%;
text-align: left;
}
.toggle-container {
margin: var(--spacing-sm) 0;
}
/* Hamburger animation when open */
.hamburger.open .hamburger-line:nth-child(1) {
transform: translateY(9px) rotate(45deg);
}
.hamburger.open .hamburger-line:nth-child(2) {
opacity: 0;
}
.hamburger.open .hamburger-line:nth-child(3) {
transform: translateY(-9px) rotate(-45deg);
}
}
/* ================= RESPONSIVE DESIGN ================= */
/* Base responsive layout */
@media (max-width: 1024px) {
.main-content {
flex-direction: column;
}
.sidebar {
width: 100%;
height: auto;
position: static;
padding: var(--spacing-md);
border-right: none;
border-bottom: 1px solid var(--border-color);
}
.content-area {
max-width: 100%;
padding: var(--spacing-md);
}
.module-list {
}
.module-list-item {
}
}
/* Header responsiveness */
@media (max-width: 768px) {
.header {
position: static;
height: auto;
padding: var(--spacing-md) var(--spacing-md);
gap: var(--spacing-md);
}
.main-nav ul {
flex-wrap: wrap;
justify-content: center;
}
.main-content {
min-height: calc(100vh - 120px);
}
}
/* Challenge container */
@media (max-width: 1024px) {
.challenge-container {
flex-direction: column;
}
.preview-area,
.editor-container {
width: 100%;
}
.preview-area {
min-height: 200px;
}
}
/* Text and other element responsiveness */
@media (max-width: 768px) {
.lesson-description {
width: 100%;
font-size: 1rem;
}
.lesson-container {
padding: var(--spacing-md);
}
#lesson-title {
font-size: 1.5rem;
}
.code-input {
font-size: 13px;
}
.controls {
flex-wrap: wrap;
gap: var(--spacing-sm);
}
.btn {
padding: var(--spacing-xs) var(--spacing-sm);
font-size: 0.85rem;
}
}
/* Small screens */
@media (max-width: 480px) {
.logo {
flex-direction: column;
align-items: center;
text-align: center;
}
.logo h1 {
font-size: 1rem;
}
.main-nav ul {
gap: var(--spacing-sm);
}
.toggle-label {
font-size: 12px;
}
.lesson-description pre {
padding: var(--spacing-md);
font-size: 0.8rem;
}
.task-instruction {
font-size: 0.9rem;
}
.modal {
width: 95%;
}
}
/* Ensure code editor has minimum height */
.code-editor {
min-height: 200px;
}
/* Better spacing for lesson progress in mobile */
@media (max-width: 1024px) {
.lesson-progress {
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: var(--spacing-xs);
margin-top: var(--spacing-md);
}
}
/* Improve validation indicators visibility */
@media (max-width: 768px) {
.validation-indicators-container {
justify-content: flex-end;
flex: 1;
}
.editor-header {
flex-wrap: wrap;
}
}
@media (max-width: 480px) {
.header {
padding: var(--spacing-sm);
gap: var(--spacing-sm);
}
.logo {
flex-direction: row;
gap: 0.4rem;
}
.logo img {
width: 40px;
}
.logo h1 {
font-size: 0.9rem;
}
}