diff --git a/blocks/header/header.css b/blocks/header/header.css index 6ed67a1..c52ddfb 100644 --- a/blocks/header/header.css +++ b/blocks/header/header.css @@ -1,60 +1,64 @@ /* header and nav layout */ header { - border-bottom: 2px solid var(--col-neutral20); + --header-border-bottom-size: 2px; + + display: flex; + align-items: center; + border-bottom: var(--header-border-bottom-size) solid var(--col-neutral20); + + @media (min-width: 1280px) { + align-items: flex-end; + } } -.nav-wrapper { - --nav-wrapper-padding-block: 26px; +.header { + flex: 1; +} - padding-block: var(--nav-wrapper-padding-block); +.nav-wrapper { + position: relative; background-color: var(--background-color); - width: 100%; - - @media (min-width: 768px) { - --nav-wrapper-padding-block: 10px; - } } .nav { + --nav-gap: 0 26px; + display: grid; grid-template: - 'hamburger brand tools' var(--nav-height) - 'sections sections sections' 1fr / auto 1fr auto; + 'brand tools hamburger' 1fr / auto 1fr auto; align-items: center; - gap: 0 24px; + gap: var(--nav-gap); margin: auto; max-width: var(--content-max-width); - height: var(--nav-height); padding-inline: var(--content-padding-inline); font-family: var(--body-font-family); - @media (min-width: 1280px) { - display: flex; - justify-content: space-between; - gap: 0 32px; - } - &[aria-expanded='true'] { grid-template: - 'hamburger brand' var(--nav-height) - 'sections sections' 1fr - 'tools tools' var(--nav-height) / auto 1fr; + 'brand hamburger' var(--nav-height) + 'sections sections' auto + 'tools tools' 1fr / 1fr auto; overflow-y: auto; min-height: 100dvh; + + @media (min-width: 768px) { + grid-template: + 'brand tools hamburger' var(--nav-height) / auto 1fr auto; + min-height: auto; + } @media (min-width: 1280px) { - min-height: 0; + --nav-gap: 16px; + + grid-template: + 'brand tools' auto + 'sections sections' 1fr / 1fr auto; overflow: visible; } } p { margin: 0; - line-height: 1; - } - - a:any-link { - color: currentcolor; } } @@ -157,19 +161,21 @@ header { .nav-brand__logo { img { + display: block; width: 83px; height: auto; } } .nav-brand__title { - font-size: var(--txt151-font-size); - line-height: var(--txt151-line-height); + font-size: var(--txt155-font-size); + line-height: var(--txt155-line-height); } /* sections */ .nav-sections { + box-sizing: border-box; grid-area: sections; flex: 1 1 auto; display: none; @@ -182,29 +188,94 @@ header { } nav[aria-expanded='true'] & { + --nav-sections-margin-inline: calc(var(--content-padding-inline) * -1); + --nav-sections-padding: 20px var(--content-padding-inline); + --nav-sections-inset: calc(100% + var(--header-border-bottom-size)) 0 auto auto; + --nav-sections-border-top: var(--header-border-bottom-size) solid var(--col-neutral20); + display: block; visibility: visible; align-self: start; + margin-inline: var(--nav-sections-margin-inline); + padding: var(--nav-sections-padding); + border-radius: 0 0 2px 2px; + border-top: var(--nav-sections-border-top); + border-bottom: 1px solid var(--col-neutral20); + background-color: var(--col-white); + + @media (min-width: 768px) { + --nav-sections-margin-inline: 0; + --nav-sections-border-top: 0; + --nav-sections-padding: 20px 40px; + + align-self: unset; + position: absolute; + inset: calc(100% + var(--header-border-bottom-size)) 0 auto auto; + min-width: 300px; + box-shadow: var(--box-shadow); + } @media (min-width: 1280px) { + --nav-sections-padding: 0; + align-self: unset; + position: static; + box-shadow: none; } } ul { + --nav-sections-list-gap: 12px; + + display: flex; + flex-direction: column; + gap: var(--nav-sections-list-gap); list-style: none; + margin: 0; padding-left: 0; font-size: var(--txt154-font-size); line-height: var(--txt154-line-height); @media (min-width: 1280px) { - display: flex; - gap: 24px; + --nav-sections-list-gap: 40px; + + flex-direction: row; margin: 0; } + a:any-link { + color: currentcolor; + } + > li { - font-weight: 500; + font-size: var(--txt159-font-size); + line-height: var(--txt159-line-height); + + a:any-link { + --nav-section-link-active-color: transparent; + + position: relative; + display: inline-flex; + flex-direction: column; + gap: 4px; + text-decoration: none; + + &::after { + content: ''; + display: block; + height: 2px; + margin-block-end: -2px; + background-color: var(--nav-section-link-active-color); + } + + &.active, + &:hover, + &:focus-visible { + &::after { + --nav-section-link-active-color: var(--col-brand30); + } + } + } > ul { margin-top: 0; @@ -300,5 +371,77 @@ header { /* tools */ .nav-tools { + --nav-tools-gap: 12px; + --nav-tools-padding-block: 20px; + + display: none; grid-area: tools; + padding-block: var(--nav-tools-padding-block); + + @media (min-width: 768px) { + --nav-tools-padding-block: 0; + + display: block; + } + + .default-content-wrapper { + display: flex; + flex-direction: column; + gap: var(--nav-tools-gap); + + @media (min-width: 768px) { + --nav-tools-gap: 20px; + + flex-direction: row; + justify-content: flex-end; + gap: 20px; + } + } + + a.button:any-link, + button { + margin: 0; + + @media (max-width: 768px) { + --button-height: auto; + + min-height: auto; + padding: 0; + border: 0; + background: none; + font-size: var(--txt159-font-size); + line-height: var(--txt159-line-height); + font-weight: 400; + color: var(--text-color); + } + + @media (min-width: 768px) { + --button-horizontal-padding: 12px; + + font-size: var(--txt171-font-size); + line-height: var(--txt171-line-height); + + &:not(.button--tertiary) { + --button-height: 32px; + } + } + + &.button--secondary { + &:hover, + &:focus { + @media (min-width: 768px) { + --button-horizontal-padding: 11px; + } + } + } + } + + nav[aria-expanded='true'] & { + display: block; + align-self: flex-start; + + @media (min-width: 768px) { + align-self: auto; + } + } } diff --git a/blocks/header/header.js b/blocks/header/header.js index 461b906..b8e4807 100644 --- a/blocks/header/header.js +++ b/blocks/header/header.js @@ -3,6 +3,8 @@ import { loadFragment } from '../fragment/fragment.js'; // media query match that indicates desktop width const isDesktop = window.matchMedia('(min-width: 1280px)'); +// media query match that indicates tablet width +const isTablet = window.matchMedia('(min-width: 768px)'); function closeOnEscape(e) { if (e.code === 'Escape') { @@ -71,7 +73,7 @@ function toggleAllNavSections(sections, expanded = false) { function toggleMenu(nav, navSections, forceExpanded = null) { const expanded = forceExpanded !== null ? !forceExpanded : nav.getAttribute('aria-expanded') === 'true'; const button = nav.querySelector('.nav-hamburger button'); - document.body.style.overflowY = (expanded || isDesktop.matches) ? '' : 'hidden'; + document.body.style.overflowY = (expanded || isTablet.matches) ? '' : 'hidden'; nav.setAttribute('aria-expanded', expanded ? 'false' : 'true'); toggleAllNavSections(navSections, expanded || isDesktop.matches ? 'false' : 'true'); button.setAttribute('aria-label', expanded ? 'Open navigation' : 'Close navigation'); @@ -103,6 +105,29 @@ function toggleMenu(nav, navSections, forceExpanded = null) { } } +/** + * Add a dedicated class to the active nav link + * + * @param {array} links - nav links + */ +function setActiveLink(links) { + const removeTrailingSlash = (url) => url.replace(/\/$/, ''); + + links.forEach((link) => { + const navUrlObject = new URL(link.href); + + // exclude external links + if (navUrlObject.origin !== window.location.origin) return; + + const currentPathWithoutTrailingSlash = removeTrailingSlash(window.location.pathname); + const linkPathWithoutTrailingSlash = removeTrailingSlash(navUrlObject.pathname); + + if (currentPathWithoutTrailingSlash === linkPathWithoutTrailingSlash) { + link.classList.add('active'); + } + }); +} + /** * loads and decorates the header, mainly the nav * @param {Element} block The header block element @@ -151,6 +176,9 @@ export default async function decorate(block) { }); } + const navLinks = navSections.querySelectorAll(':scope .default-content-wrapper > ul > li > a'); + setActiveLink(navLinks); + // hamburger for mobile const hamburger = document.createElement('div'); hamburger.classList.add('nav-hamburger'); diff --git a/styles/styles.css b/styles/styles.css index 9138232..5ecfff3 100644 --- a/styles/styles.css +++ b/styles/styles.css @@ -38,8 +38,12 @@ --txt150-font-size: 14px; --txt150-line-height: 114%; --txt150-font-weight: 700; - --txt151-font-size: 13px; - --txt151-line-height: 142%; + --txt155-font-size: 13px; + --txt155-line-height: 123%; + --txt159-font-size: 16px; + --txt159-line-height: 175%; + --txt171-font-size: 12px; + --txt171-line-height: 132%; --txt201-font-size: 16px; --txt201-line-height: 160%; --txt204-font-size: 14px; @@ -72,7 +76,7 @@ } /* nav height */ - --nav-height: auto; + --nav-height: 80px; /* DN Theme variables */ @@ -109,7 +113,7 @@ } /* Shadows */ - --box-shadow: 0 1px 2px 0 rgba(var(--col-neutral50), 0.34), 0 0 13px 0 var(var(--col-neutral10)); + --box-shadow: 0 1px 2px 0 rgb(145 145 145 / 34%), 0 0 13px 0 var(--col-neutral10); /* colors */ --background-color: var(--col-white); @@ -135,7 +139,11 @@ body.appear { } header { - height: var(--nav-height); + min-height: var(--nav-height); + + @media (min-width: 1280px) { + --nav-height: 105px; + } } header .header, @@ -280,8 +288,8 @@ button { --button-border-width: 1px; --button-text-color: var(--col-white); --button-icon-color: var(--button-text-color); - --button-vertical-padding: 12px; - --button-horitzontal-padding: 16px; + --button-horizontal-padding: 16px; + --button-height: 48px; box-sizing: border-box; display: inline-flex; @@ -320,9 +328,9 @@ a.button:any-link:not(.button--tertiary), button:not(.button--tertiary) { border-radius: 2px; border: var(--button-border-width) solid var(--button-border-color); - padding: var(--button-vertical-padding) var(--button-horitzontal-padding); + padding-inline: var(--button-horizontal-padding); background-color: var(--button-bg-color); - min-height: 48px; + height: var(--button-height); } button:disabled, @@ -344,8 +352,7 @@ button.button--secondary { &:hover, &:focus { --button-border-width: 2px; - --button-vertical-padding: 11px; - --button-horitzontal-padding: 15px; + --button-horizontal-padding: 15px; } } @@ -368,8 +375,7 @@ button.button--tertiary { &:hover, &:focus { - --button-vertical-padding: 11px; - --button-horitzontal-padding: 15px; + --button-horizontal-padding: 15px; border-width: 2px; text-decoration: underline; @@ -385,7 +391,6 @@ button.button--tertiary:disabled:hover { main img { max-width: 100%; - width: auto; height: auto; }