Skip to content

Commit 593faac

Browse files
committed
feat: implement responsive hamburger menu and enhance header layout
1 parent 371ff7b commit 593faac

File tree

3 files changed

+316
-4
lines changed

3 files changed

+316
-4
lines changed

src/app.js

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -611,6 +611,57 @@ function init() {
611611
e.preventDefault();
612612
}
613613
});
614+
615+
// Add this to your app.js file
616+
617+
// Mobile Menu Functionality
618+
document.addEventListener("DOMContentLoaded", function () {
619+
// Create hamburger menu button
620+
const hamburger = document.createElement("button");
621+
hamburger.className = "hamburger";
622+
hamburger.setAttribute("aria-label", "Toggle menu");
623+
hamburger.innerHTML = `
624+
<span class="hamburger-line"></span>
625+
<span class="hamburger-line"></span>
626+
<span class="hamburger-line"></span>
627+
`;
628+
629+
// Get the header and nav elements
630+
const header = document.querySelector(".header");
631+
const logo = document.querySelector(".logo");
632+
const nav = document.querySelector(".main-nav");
633+
634+
// Insert hamburger button after the logo
635+
header.insertBefore(hamburger, logo.nextSibling);
636+
637+
// Toggle menu on hamburger click
638+
hamburger.addEventListener("click", function () {
639+
nav.classList.toggle("open");
640+
hamburger.classList.toggle("open");
641+
642+
// Set aria-expanded attribute for accessibility
643+
const isExpanded = nav.classList.contains("open");
644+
hamburger.setAttribute("aria-expanded", isExpanded);
645+
});
646+
647+
// Close menu when clicking outside
648+
document.addEventListener("click", function (event) {
649+
if (!nav.contains(event.target) && !hamburger.contains(event.target) && nav.classList.contains("open")) {
650+
nav.classList.remove("open");
651+
hamburger.classList.remove("open");
652+
hamburger.setAttribute("aria-expanded", false);
653+
}
654+
});
655+
656+
// Close menu when window is resized to desktop size
657+
window.addEventListener("resize", function () {
658+
if (window.innerWidth > 768 && nav.classList.contains("open")) {
659+
nav.classList.remove("open");
660+
hamburger.classList.remove("open");
661+
hamburger.setAttribute("aria-expanded", false);
662+
}
663+
});
664+
});
614665
}
615666

616667
// Start the application

src/config/lessons.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ import responsiveConfig from "../../lessons/08-responsive.json";
1717
// Module store
1818
const moduleStore = [
1919
// basicsConfig,
20-
basicSelectorsConfig
21-
// boxModelConfig,
22-
// selectorsConfig,
23-
// colorsConfig,
20+
basicSelectorsConfig,
21+
boxModelConfig,
22+
selectorsConfig,
23+
colorsConfig
2424
// typographyConfig,
2525
// unitVariablesConfig,
2626
// transitionsAnimationsConfig,

src/main.css

Lines changed: 261 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -708,3 +708,264 @@ input:checked + .toggle-slider:before {
708708
font-size: 14px;
709709
color: var(--text-color);
710710
}
711+
712+
/* Hamburger Menu Icon */
713+
.hamburger {
714+
display: none;
715+
cursor: pointer;
716+
flex-direction: column;
717+
justify-content: space-around;
718+
width: 30px;
719+
height: 21px;
720+
background: transparent;
721+
border: none;
722+
padding: 0;
723+
}
724+
725+
.hamburger-line {
726+
display: block;
727+
width: 100%;
728+
height: 3px;
729+
background-color: var(--text-color);
730+
border-radius: 10px;
731+
transition: all 0.3s ease;
732+
}
733+
734+
/* Responsive Header Adjustments */
735+
@media (max-width: 768px) {
736+
.header {
737+
flex-wrap: wrap;
738+
padding: var(--spacing-md);
739+
}
740+
741+
.logo {
742+
flex: 1;
743+
}
744+
745+
.hamburger {
746+
display: flex;
747+
order: 2;
748+
}
749+
750+
.main-nav {
751+
width: 100%;
752+
order: 3;
753+
height: 0;
754+
overflow: hidden;
755+
transition: height 0.3s ease;
756+
}
757+
758+
.main-nav.open {
759+
height: auto;
760+
margin-top: var(--spacing-md);
761+
}
762+
763+
.main-nav ul {
764+
flex-direction: column;
765+
width: 100%;
766+
align-items: flex-start;
767+
gap: var(--spacing-sm);
768+
}
769+
770+
.main-nav ul li {
771+
width: 100%;
772+
}
773+
774+
.main-nav ul li .btn {
775+
width: 100%;
776+
text-align: left;
777+
}
778+
779+
.toggle-container {
780+
margin: var(--spacing-sm) 0;
781+
}
782+
783+
/* Hamburger animation when open */
784+
.hamburger.open .hamburger-line:nth-child(1) {
785+
transform: translateY(9px) rotate(45deg);
786+
}
787+
788+
.hamburger.open .hamburger-line:nth-child(2) {
789+
opacity: 0;
790+
}
791+
792+
.hamburger.open .hamburger-line:nth-child(3) {
793+
transform: translateY(-9px) rotate(-45deg);
794+
}
795+
}
796+
797+
/* ================= RESPONSIVE DESIGN ================= */
798+
799+
/* Base responsive layout */
800+
@media (max-width: 1024px) {
801+
.main-content {
802+
flex-direction: column;
803+
}
804+
805+
.sidebar {
806+
width: 100%;
807+
height: auto;
808+
position: static;
809+
padding: var(--spacing-md);
810+
border-right: none;
811+
border-bottom: 1px solid var(--border-color);
812+
}
813+
814+
.content-area {
815+
max-width: 100%;
816+
padding: var(--spacing-md);
817+
}
818+
819+
.module-list {
820+
}
821+
822+
.module-list-item {
823+
}
824+
}
825+
826+
/* Header responsiveness */
827+
@media (max-width: 768px) {
828+
.header {
829+
position: static;
830+
height: auto;
831+
padding: var(--spacing-md) var(--spacing-md);
832+
gap: var(--spacing-md);
833+
}
834+
835+
.main-nav ul {
836+
flex-wrap: wrap;
837+
justify-content: center;
838+
}
839+
840+
.main-content {
841+
min-height: calc(100vh - 120px);
842+
}
843+
}
844+
845+
/* Challenge container */
846+
@media (max-width: 1024px) {
847+
.challenge-container {
848+
flex-direction: column;
849+
}
850+
851+
.preview-area,
852+
.editor-container {
853+
width: 100%;
854+
}
855+
856+
.preview-area {
857+
min-height: 200px;
858+
}
859+
}
860+
861+
/* Text and other element responsiveness */
862+
@media (max-width: 768px) {
863+
.lesson-description {
864+
width: 100%;
865+
font-size: 1rem;
866+
}
867+
868+
.lesson-container {
869+
padding: var(--spacing-md);
870+
}
871+
872+
#lesson-title {
873+
font-size: 1.5rem;
874+
}
875+
876+
.code-input {
877+
font-size: 13px;
878+
}
879+
880+
.controls {
881+
flex-wrap: wrap;
882+
gap: var(--spacing-sm);
883+
}
884+
885+
.btn {
886+
padding: var(--spacing-xs) var(--spacing-sm);
887+
font-size: 0.85rem;
888+
}
889+
}
890+
891+
/* Small screens */
892+
@media (max-width: 480px) {
893+
.logo {
894+
flex-direction: column;
895+
align-items: center;
896+
text-align: center;
897+
}
898+
899+
.logo h1 {
900+
font-size: 1rem;
901+
}
902+
903+
.main-nav ul {
904+
gap: var(--spacing-sm);
905+
}
906+
907+
.toggle-label {
908+
font-size: 12px;
909+
}
910+
911+
.lesson-description pre {
912+
padding: var(--spacing-md);
913+
font-size: 0.8rem;
914+
}
915+
916+
.task-instruction {
917+
font-size: 0.9rem;
918+
}
919+
920+
.modal {
921+
width: 95%;
922+
}
923+
}
924+
925+
/* Ensure code editor has minimum height */
926+
.code-editor {
927+
min-height: 200px;
928+
}
929+
930+
/* Better spacing for lesson progress in mobile */
931+
@media (max-width: 1024px) {
932+
.lesson-progress {
933+
display: flex;
934+
flex-wrap: wrap;
935+
justify-content: center;
936+
gap: var(--spacing-xs);
937+
margin-top: var(--spacing-md);
938+
}
939+
}
940+
941+
/* Improve validation indicators visibility */
942+
@media (max-width: 768px) {
943+
.validation-indicators-container {
944+
justify-content: flex-end;
945+
flex: 1;
946+
}
947+
948+
.editor-header {
949+
flex-wrap: wrap;
950+
}
951+
}
952+
953+
@media (max-width: 480px) {
954+
.header {
955+
padding: var(--spacing-sm);
956+
gap: var(--spacing-sm);
957+
}
958+
959+
.logo {
960+
flex-direction: row;
961+
gap: 0.4rem;
962+
}
963+
964+
.logo img {
965+
width: 40px;
966+
}
967+
968+
.logo h1 {
969+
font-size: 0.9rem;
970+
}
971+
}

0 commit comments

Comments
 (0)