Skip to content

Commit 9e58a86

Browse files
authored
Merge pull request #22 from Netcentric/7-menu
Updates menu
2 parents 8aa01ea + 37d1bb1 commit 9e58a86

File tree

3 files changed

+224
-48
lines changed

3 files changed

+224
-48
lines changed

blocks/header/header.css

+176-33
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,64 @@
11
/* header and nav layout */
22
header {
3-
border-bottom: 2px solid var(--col-neutral20);
3+
--header-border-bottom-size: 2px;
4+
5+
display: flex;
6+
align-items: center;
7+
border-bottom: var(--header-border-bottom-size) solid var(--col-neutral20);
8+
9+
@media (min-width: 1280px) {
10+
align-items: flex-end;
11+
}
412
}
513

6-
.nav-wrapper {
7-
--nav-wrapper-padding-block: 26px;
14+
.header {
15+
flex: 1;
16+
}
817

9-
padding-block: var(--nav-wrapper-padding-block);
18+
.nav-wrapper {
19+
position: relative;
1020
background-color: var(--background-color);
11-
width: 100%;
12-
13-
@media (min-width: 768px) {
14-
--nav-wrapper-padding-block: 10px;
15-
}
1621
}
1722

1823
.nav {
24+
--nav-gap: 0 26px;
25+
1926
display: grid;
2027
grid-template:
21-
'hamburger brand tools' var(--nav-height)
22-
'sections sections sections' 1fr / auto 1fr auto;
28+
'brand tools hamburger' 1fr / auto 1fr auto;
2329
align-items: center;
24-
gap: 0 24px;
30+
gap: var(--nav-gap);
2531
margin: auto;
2632
max-width: var(--content-max-width);
27-
height: var(--nav-height);
2833
padding-inline: var(--content-padding-inline);
2934
font-family: var(--body-font-family);
3035

31-
@media (min-width: 1280px) {
32-
display: flex;
33-
justify-content: space-between;
34-
gap: 0 32px;
35-
}
36-
3736
&[aria-expanded='true'] {
3837
grid-template:
39-
'hamburger brand' var(--nav-height)
40-
'sections sections' 1fr
41-
'tools tools' var(--nav-height) / auto 1fr;
38+
'brand hamburger' var(--nav-height)
39+
'sections sections' auto
40+
'tools tools' 1fr / 1fr auto;
4241
overflow-y: auto;
4342
min-height: 100dvh;
43+
44+
@media (min-width: 768px) {
45+
grid-template:
46+
'brand tools hamburger' var(--nav-height) / auto 1fr auto;
47+
min-height: auto;
48+
}
4449

4550
@media (min-width: 1280px) {
46-
min-height: 0;
51+
--nav-gap: 16px;
52+
53+
grid-template:
54+
'brand tools' auto
55+
'sections sections' 1fr / 1fr auto;
4756
overflow: visible;
4857
}
4958
}
5059

5160
p {
5261
margin: 0;
53-
line-height: 1;
54-
}
55-
56-
a:any-link {
57-
color: currentcolor;
5862
}
5963
}
6064

@@ -157,19 +161,21 @@ header {
157161

158162
.nav-brand__logo {
159163
img {
164+
display: block;
160165
width: 83px;
161166
height: auto;
162167
}
163168
}
164169

165170
.nav-brand__title {
166-
font-size: var(--txt151-font-size);
167-
line-height: var(--txt151-line-height);
171+
font-size: var(--txt155-font-size);
172+
line-height: var(--txt155-line-height);
168173
}
169174

170175

171176
/* sections */
172177
.nav-sections {
178+
box-sizing: border-box;
173179
grid-area: sections;
174180
flex: 1 1 auto;
175181
display: none;
@@ -182,29 +188,94 @@ header {
182188
}
183189

184190
nav[aria-expanded='true'] & {
191+
--nav-sections-margin-inline: calc(var(--content-padding-inline) * -1);
192+
--nav-sections-padding: 20px var(--content-padding-inline);
193+
--nav-sections-inset: calc(100% + var(--header-border-bottom-size)) 0 auto auto;
194+
--nav-sections-border-top: var(--header-border-bottom-size) solid var(--col-neutral20);
195+
185196
display: block;
186197
visibility: visible;
187198
align-self: start;
199+
margin-inline: var(--nav-sections-margin-inline);
200+
padding: var(--nav-sections-padding);
201+
border-radius: 0 0 2px 2px;
202+
border-top: var(--nav-sections-border-top);
203+
border-bottom: 1px solid var(--col-neutral20);
204+
background-color: var(--col-white);
205+
206+
@media (min-width: 768px) {
207+
--nav-sections-margin-inline: 0;
208+
--nav-sections-border-top: 0;
209+
--nav-sections-padding: 20px 40px;
210+
211+
align-self: unset;
212+
position: absolute;
213+
inset: calc(100% + var(--header-border-bottom-size)) 0 auto auto;
214+
min-width: 300px;
215+
box-shadow: var(--box-shadow);
216+
}
188217

189218
@media (min-width: 1280px) {
219+
--nav-sections-padding: 0;
220+
190221
align-self: unset;
222+
position: static;
223+
box-shadow: none;
191224
}
192225
}
193226

194227
ul {
228+
--nav-sections-list-gap: 12px;
229+
230+
display: flex;
231+
flex-direction: column;
232+
gap: var(--nav-sections-list-gap);
195233
list-style: none;
234+
margin: 0;
196235
padding-left: 0;
197236
font-size: var(--txt154-font-size);
198237
line-height: var(--txt154-line-height);
199238

200239
@media (min-width: 1280px) {
201-
display: flex;
202-
gap: 24px;
240+
--nav-sections-list-gap: 40px;
241+
242+
flex-direction: row;
203243
margin: 0;
204244
}
205245

246+
a:any-link {
247+
color: currentcolor;
248+
}
249+
206250
> li {
207-
font-weight: 500;
251+
font-size: var(--txt159-font-size);
252+
line-height: var(--txt159-line-height);
253+
254+
a:any-link {
255+
--nav-section-link-active-color: transparent;
256+
257+
position: relative;
258+
display: inline-flex;
259+
flex-direction: column;
260+
gap: 4px;
261+
text-decoration: none;
262+
263+
&::after {
264+
content: '';
265+
display: block;
266+
height: 2px;
267+
margin-block-end: -2px;
268+
background-color: var(--nav-section-link-active-color);
269+
}
270+
271+
&.active,
272+
&:hover,
273+
&:focus-visible {
274+
&::after {
275+
--nav-section-link-active-color: var(--col-brand30);
276+
}
277+
}
278+
}
208279

209280
> ul {
210281
margin-top: 0;
@@ -300,5 +371,77 @@ header {
300371

301372
/* tools */
302373
.nav-tools {
374+
--nav-tools-gap: 12px;
375+
--nav-tools-padding-block: 20px;
376+
377+
display: none;
303378
grid-area: tools;
379+
padding-block: var(--nav-tools-padding-block);
380+
381+
@media (min-width: 768px) {
382+
--nav-tools-padding-block: 0;
383+
384+
display: block;
385+
}
386+
387+
.default-content-wrapper {
388+
display: flex;
389+
flex-direction: column;
390+
gap: var(--nav-tools-gap);
391+
392+
@media (min-width: 768px) {
393+
--nav-tools-gap: 20px;
394+
395+
flex-direction: row;
396+
justify-content: flex-end;
397+
gap: 20px;
398+
}
399+
}
400+
401+
a.button:any-link,
402+
button {
403+
margin: 0;
404+
405+
@media (max-width: 768px) {
406+
--button-height: auto;
407+
408+
min-height: auto;
409+
padding: 0;
410+
border: 0;
411+
background: none;
412+
font-size: var(--txt159-font-size);
413+
line-height: var(--txt159-line-height);
414+
font-weight: 400;
415+
color: var(--text-color);
416+
}
417+
418+
@media (min-width: 768px) {
419+
--button-horizontal-padding: 12px;
420+
421+
font-size: var(--txt171-font-size);
422+
line-height: var(--txt171-line-height);
423+
424+
&:not(.button--tertiary) {
425+
--button-height: 32px;
426+
}
427+
}
428+
429+
&.button--secondary {
430+
&:hover,
431+
&:focus {
432+
@media (min-width: 768px) {
433+
--button-horizontal-padding: 11px;
434+
}
435+
}
436+
}
437+
}
438+
439+
nav[aria-expanded='true'] & {
440+
display: block;
441+
align-self: flex-start;
442+
443+
@media (min-width: 768px) {
444+
align-self: auto;
445+
}
446+
}
304447
}

blocks/header/header.js

+29-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import { loadFragment } from '../fragment/fragment.js';
33

44
// media query match that indicates desktop width
55
const isDesktop = window.matchMedia('(min-width: 1280px)');
6+
// media query match that indicates tablet width
7+
const isTablet = window.matchMedia('(min-width: 768px)');
68

79
function closeOnEscape(e) {
810
if (e.code === 'Escape') {
@@ -71,7 +73,7 @@ function toggleAllNavSections(sections, expanded = false) {
7173
function toggleMenu(nav, navSections, forceExpanded = null) {
7274
const expanded = forceExpanded !== null ? !forceExpanded : nav.getAttribute('aria-expanded') === 'true';
7375
const button = nav.querySelector('.nav-hamburger button');
74-
document.body.style.overflowY = (expanded || isDesktop.matches) ? '' : 'hidden';
76+
document.body.style.overflowY = (expanded || isTablet.matches) ? '' : 'hidden';
7577
nav.setAttribute('aria-expanded', expanded ? 'false' : 'true');
7678
toggleAllNavSections(navSections, expanded || isDesktop.matches ? 'false' : 'true');
7779
button.setAttribute('aria-label', expanded ? 'Open navigation' : 'Close navigation');
@@ -103,6 +105,29 @@ function toggleMenu(nav, navSections, forceExpanded = null) {
103105
}
104106
}
105107

108+
/**
109+
* Add a dedicated class to the active nav link
110+
*
111+
* @param {array} links - nav links
112+
*/
113+
function setActiveLink(links) {
114+
const removeTrailingSlash = (url) => url.replace(/\/$/, '');
115+
116+
links.forEach((link) => {
117+
const navUrlObject = new URL(link.href);
118+
119+
// exclude external links
120+
if (navUrlObject.origin !== window.location.origin) return;
121+
122+
const currentPathWithoutTrailingSlash = removeTrailingSlash(window.location.pathname);
123+
const linkPathWithoutTrailingSlash = removeTrailingSlash(navUrlObject.pathname);
124+
125+
if (currentPathWithoutTrailingSlash === linkPathWithoutTrailingSlash) {
126+
link.classList.add('active');
127+
}
128+
});
129+
}
130+
106131
/**
107132
* loads and decorates the header, mainly the nav
108133
* @param {Element} block The header block element
@@ -151,6 +176,9 @@ export default async function decorate(block) {
151176
});
152177
}
153178

179+
const navLinks = navSections.querySelectorAll(':scope .default-content-wrapper > ul > li > a');
180+
setActiveLink(navLinks);
181+
154182
// hamburger for mobile
155183
const hamburger = document.createElement('div');
156184
hamburger.classList.add('nav-hamburger');

0 commit comments

Comments
 (0)