Skip to content

Commit 809f350

Browse files
committed
feat: implement mobile navigation toggle and enhance CV download link
1 parent 09b64c5 commit 809f350

3 files changed

Lines changed: 142 additions & 5 deletions

File tree

index.html

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,13 @@
7272
<header class="site-header">
7373
<div class="header-inner">
7474
<a href="#home" class="brand">Shafi</a>
75-
<nav class="nav" aria-label="Primary Navigation">
75+
<a class="nav-download mobile-download" href="assets/CV-Shafi.pdf" download="Fozle-Rabbi-Shafi-CV.pdf">Download CV</a>
76+
<button class="menu-toggle" type="button" aria-expanded="false" aria-controls="primary-nav" aria-label="Toggle navigation menu">
77+
<span></span>
78+
<span></span>
79+
<span></span>
80+
</button>
81+
<nav id="primary-nav" class="nav" aria-label="Primary Navigation">
7682
<div class="nav-links">
7783
<a class="nav-link" href="#about">About</a>
7884
<a class="nav-link" href="#education">Education</a>
@@ -107,7 +113,7 @@
107113
<section id="home" class="hero section">
108114
<div class="hero-layout">
109115
<div>
110-
<p class="kicker"> PhD Student | Cybersecurity Researcher</p>
116+
<p class="kicker">PhD Student | Cybersecurity Researcher</p>
111117
<h1>Fozle Rabbi Shafi</h1>
112118
<p class="hero-text">
113119
PhD student in Computing at Queen&rsquo;s University, researching AI-driven cybersecurity

script.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
const reveals = document.querySelectorAll('.reveal');
22
const navLinks = document.querySelectorAll('.nav-link');
33
const sections = [...document.querySelectorAll('main section[id]')];
4+
const menuToggle = document.querySelector('.menu-toggle');
5+
const headerInner = document.querySelector('.header-inner');
46

57
const revealObserver = new IntersectionObserver(
68
(entries) => {
@@ -35,3 +37,26 @@ window.addEventListener('scroll', activateNav);
3537
window.addEventListener('load', activateNav);
3638

3739
document.getElementById('year').textContent = new Date().getFullYear();
40+
41+
if (menuToggle && headerInner) {
42+
menuToggle.addEventListener('click', () => {
43+
const isOpen = headerInner.classList.toggle('menu-open');
44+
menuToggle.setAttribute('aria-expanded', String(isOpen));
45+
});
46+
47+
navLinks.forEach((link) => {
48+
link.addEventListener('click', () => {
49+
if (window.innerWidth <= 760) {
50+
headerInner.classList.remove('menu-open');
51+
menuToggle.setAttribute('aria-expanded', 'false');
52+
}
53+
});
54+
});
55+
56+
window.addEventListener('resize', () => {
57+
if (window.innerWidth > 760) {
58+
headerInner.classList.remove('menu-open');
59+
menuToggle.setAttribute('aria-expanded', 'false');
60+
}
61+
});
62+
}

styles.css

Lines changed: 109 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,29 @@ ul {
8383
gap: 1rem;
8484
}
8585

86+
.menu-toggle {
87+
display: none;
88+
width: 38px;
89+
height: 38px;
90+
border: 1px solid var(--stroke);
91+
border-radius: 10px;
92+
background: #f8fbff;
93+
padding: 0;
94+
align-items: center;
95+
justify-content: center;
96+
flex-direction: column;
97+
gap: 4px;
98+
cursor: pointer;
99+
}
100+
101+
.menu-toggle span {
102+
width: 16px;
103+
height: 2px;
104+
border-radius: 999px;
105+
background: #1c2d42;
106+
transition: transform 180ms ease, opacity 180ms ease;
107+
}
108+
86109
.brand {
87110
text-decoration: none;
88111
font-family: "Space Grotesk", sans-serif;
@@ -142,6 +165,10 @@ ul {
142165
box-shadow: 0 10px 20px rgba(15, 138, 85, 0.32);
143166
}
144167

168+
.mobile-download {
169+
display: none;
170+
}
171+
145172
.nav-socials {
146173
display: flex;
147174
align-items: center;
@@ -486,8 +513,59 @@ article.card {
486513
padding: 0.7rem 0.8rem;
487514
}
488515

516+
.header-inner {
517+
position: relative;
518+
align-items: center;
519+
}
520+
521+
.menu-toggle {
522+
display: inline-flex;
523+
margin-left: auto;
524+
}
525+
526+
.header-inner.menu-open .menu-toggle span:nth-child(1) {
527+
transform: translateY(6px) rotate(45deg);
528+
}
529+
530+
.header-inner.menu-open .menu-toggle span:nth-child(2) {
531+
opacity: 0;
532+
}
533+
534+
.header-inner.menu-open .menu-toggle span:nth-child(3) {
535+
transform: translateY(-6px) rotate(-45deg);
536+
}
537+
489538
.nav {
490-
gap: 0.45rem;
539+
position: absolute;
540+
top: calc(100% + 0.5rem);
541+
left: 0;
542+
right: 0;
543+
z-index: 20;
544+
gap: 0.65rem;
545+
flex-direction: column;
546+
align-items: stretch;
547+
justify-content: flex-start;
548+
background: #ffffff;
549+
border: 1px solid var(--stroke);
550+
border-radius: 14px;
551+
box-shadow: 0 14px 28px rgba(15, 40, 75, 0.14);
552+
padding: 0.75rem;
553+
opacity: 0;
554+
transform: translateY(-6px);
555+
pointer-events: none;
556+
transition: opacity 180ms ease, transform 180ms ease;
557+
}
558+
559+
.header-inner.menu-open .nav {
560+
opacity: 1;
561+
transform: translateY(0);
562+
pointer-events: auto;
563+
}
564+
565+
.nav-links {
566+
flex-direction: column;
567+
align-items: flex-start;
568+
gap: 0.2rem;
491569
}
492570

493571
.nav-link {
@@ -497,7 +575,35 @@ article.card {
497575

498576
.nav-download {
499577
font-size: 0.78rem;
500-
padding: 0.38rem 0.62rem;
578+
padding: 0.45rem 0.7rem;
579+
align-self: flex-start;
580+
}
581+
582+
.mobile-download {
583+
display: inline-flex;
584+
margin-left: 0.55rem;
585+
font-size: 0.78rem;
586+
padding: 0 0.62rem;
587+
height: 34px;
588+
line-height: 1.15;
589+
align-items: center;
590+
justify-content: center;
591+
text-align: center;
592+
}
593+
594+
.brand {
595+
display: inline-flex;
596+
align-items: center;
597+
justify-content: center;
598+
min-height: 34px;
599+
}
600+
601+
.nav .nav-download {
602+
display: none;
603+
}
604+
605+
.nav-socials {
606+
justify-content: flex-start;
501607
}
502608

503609
.nav-socials a {
@@ -506,7 +612,7 @@ article.card {
506612
}
507613

508614
main {
509-
margin-top: 8.2rem;
615+
margin-top: 6.3rem;
510616
}
511617

512618
.hero-layout {

0 commit comments

Comments
 (0)