Skip to content

Commit 7cbe9e1

Browse files
Add mobile hamburger menu for product mode
1 parent a4a2f70 commit 7cbe9e1

2 files changed

Lines changed: 157 additions & 0 deletions

File tree

themes/purple-haze/sass/components/_navigation.scss

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -935,3 +935,101 @@
935935
height: 20px;
936936
}
937937
}
938+
939+
// -----------------------------------------------------------------------------
940+
// Product Mode Mobile Menu
941+
// -----------------------------------------------------------------------------
942+
943+
.header__mobile-toggle {
944+
display: none;
945+
align-items: center;
946+
justify-content: center;
947+
width: 40px;
948+
height: 40px;
949+
color: var(--color-text-secondary);
950+
background: transparent;
951+
border: 1px solid var(--color-border);
952+
border-radius: 8px;
953+
cursor: pointer;
954+
transition: all 0.2s ease;
955+
956+
@media (max-width: 767px) {
957+
display: flex;
958+
}
959+
960+
&:hover {
961+
color: var(--color-text);
962+
background: var(--color-bg-surface);
963+
border-color: var(--color-accent);
964+
}
965+
966+
.header__mobile-icon--close {
967+
display: none;
968+
}
969+
}
970+
971+
.header--mobile-open .header__mobile-toggle {
972+
.header__mobile-icon--menu {
973+
display: none;
974+
}
975+
.header__mobile-icon--close {
976+
display: block;
977+
}
978+
}
979+
980+
.header__mobile-nav {
981+
display: none;
982+
position: absolute;
983+
top: 100%;
984+
left: 0;
985+
right: 0;
986+
background: var(--color-bg);
987+
border-bottom: 1px solid var(--color-border);
988+
max-height: 0;
989+
overflow: hidden;
990+
transition: max-height 0.3s ease;
991+
992+
@media (max-width: 767px) {
993+
display: block;
994+
}
995+
}
996+
997+
.header--mobile-open .header__mobile-nav {
998+
max-height: 500px;
999+
}
1000+
1001+
.header__mobile-nav-inner {
1002+
display: flex;
1003+
flex-direction: column;
1004+
padding: 1rem;
1005+
gap: 0.25rem;
1006+
}
1007+
1008+
.header__mobile-link {
1009+
display: flex;
1010+
align-items: center;
1011+
gap: 0.75rem;
1012+
padding: 0.875rem 1rem;
1013+
font-size: var(--text-base);
1014+
font-weight: var(--font-medium);
1015+
color: var(--color-text-secondary);
1016+
text-decoration: none;
1017+
border-radius: 8px;
1018+
transition: all 0.2s ease;
1019+
1020+
svg {
1021+
flex-shrink: 0;
1022+
width: 18px;
1023+
height: 18px;
1024+
}
1025+
1026+
&:hover {
1027+
color: var(--color-text);
1028+
background: var(--color-bg-surface);
1029+
}
1030+
}
1031+
1032+
// Prevent body scroll when mobile menu is open
1033+
body.mobile-menu-open {
1034+
overflow: hidden;
1035+
}

themes/purple-haze/templates/partials/header.html

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,66 @@ <h2 id="search-title" class="sr-only">Search</h2>
279279
<a href="{{ config.extra.github }}" class="header__icon-link" aria-label="View project on GitHub (opens in new tab)" target="_blank" rel="noopener noreferrer" title="GitHub"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/></svg></a>
280280
{% endif %}
281281
</div>
282+
283+
{# Mobile menu toggle #}
284+
<button class="header__mobile-toggle" type="button" aria-label="Toggle menu" aria-expanded="false">
285+
<svg class="header__mobile-icon header__mobile-icon--menu" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
286+
<line x1="3" y1="6" x2="21" y2="6"/>
287+
<line x1="3" y1="12" x2="21" y2="12"/>
288+
<line x1="3" y1="18" x2="21" y2="18"/>
289+
</svg>
290+
<svg class="header__mobile-icon header__mobile-icon--close" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
291+
<line x1="18" y1="6" x2="6" y2="18"/>
292+
<line x1="6" y1="6" x2="18" y2="18"/>
293+
</svg>
294+
</button>
282295
</div>
283296
</div>
297+
298+
{# Mobile navigation dropdown #}
299+
<nav class="header__mobile-nav" role="navigation" aria-label="Mobile navigation">
300+
<div class="header__mobile-nav-inner">
301+
{% if config.extra.nav %}
302+
{% for link in config.extra.nav %}
303+
<a href="{{ link.url | safe }}" class="header__mobile-link">{{ link.name }}</a>
304+
{% endfor %}
305+
{% elif config.extra.nav_links %}
306+
{% for link in config.extra.nav_links %}
307+
<a href="{{ link.url | safe }}" class="header__mobile-link">{{ link.name }}</a>
308+
{% endfor %}
309+
{% endif %}
310+
{% if config.extra.github %}
311+
<a href="{{ config.extra.github }}" class="header__mobile-link" target="_blank" rel="noopener noreferrer">
312+
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/></svg>
313+
<span>GitHub</span>
314+
</a>
315+
{% endif %}
316+
</div>
317+
</nav>
284318
</header>
319+
320+
<script>
321+
(function() {
322+
const header = document.querySelector('.header');
323+
const toggle = document.querySelector('.header__mobile-toggle');
324+
const mobileNav = document.querySelector('.header__mobile-nav');
325+
326+
if (toggle && mobileNav && header) {
327+
toggle.addEventListener('click', function() {
328+
const isOpen = header.classList.toggle('header--mobile-open');
329+
toggle.setAttribute('aria-expanded', isOpen);
330+
document.body.classList.toggle('mobile-menu-open', isOpen);
331+
});
332+
333+
// Close menu when clicking a link
334+
mobileNav.querySelectorAll('a').forEach(link => {
335+
link.addEventListener('click', () => {
336+
header.classList.remove('header--mobile-open');
337+
toggle.setAttribute('aria-expanded', 'false');
338+
document.body.classList.remove('mobile-menu-open');
339+
});
340+
});
341+
}
342+
})();
343+
</script>
285344
{% endif %}

0 commit comments

Comments
 (0)