feat: implement responsive hamburger menu and enhance header layout
This commit is contained in:
51
src/app.js
51
src/app.js
@@ -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
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
261
src/main.css
261
src/main.css
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user