From cb33b90236ec2b95f328bc19b9122fff03991462 Mon Sep 17 00:00:00 2001 From: Lamont Crook Date: Wed, 8 Jul 2026 11:36:02 -0600 Subject: [PATCH 1/2] Rebuild header to match Holland America Line MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Restructure the header block into HAL's layered layout and full-fidelity match: - header.js: map five nav-fragment regions (brand/logo, primary menu, utility, announcement, search widget) and keep mega-menu + mobile-drawer behavior. - header.css: navy layered header — logo, top utility bar with icons, primary menu (20px/600) with active orange underline, orange announcement bar, cruise-search widget row, full-width multi-column mega-menu panels, and a navy mobile drawer. - quasimoda: add --nav-font token and the Adobe Fonts kit link in head.html. - icons: add heart/globe/chat/user line icons for the utility bar. The matching nav content (logo image, mega-menus, utility, announcement, search widget) lives in the DA /fragments/nav source. Co-Authored-By: Claude Opus 4.8 --- blocks/header/header.css | 443 ++++++++++++++++++++++++++------------- blocks/header/header.js | 6 +- head.html | 3 + icons/chat.svg | 1 + icons/globe.svg | 1 + icons/heart.svg | 1 + icons/user.svg | 1 + styles/styles.css | 4 + 8 files changed, 311 insertions(+), 149 deletions(-) create mode 100644 icons/chat.svg create mode 100644 icons/globe.svg create mode 100644 icons/heart.svg create mode 100644 icons/user.svg diff --git a/blocks/header/header.css b/blocks/header/header.css index 349253e..64cacf1 100644 --- a/blocks/header/header.css +++ b/blocks/header/header.css @@ -1,11 +1,15 @@ -/* header and nav layout */ +/* ========================================================================== + Header / nav — styled to match hollandamerica.com + Layered layout: [brand | utility] / primary menu / announcement / search + ========================================================================== */ + header .nav-wrapper { background-color: var(--nav-bg-color); color: var(--nav-text-color); width: 100%; z-index: 10; position: fixed; - border-bottom: 3px solid var(--cta-color); + font-family: var(--nav-font); } header nav { @@ -15,43 +19,23 @@ header nav { 'hamburger brand tools' var(--nav-height) 'sections sections sections' 1fr / auto 1fr auto; align-items: center; - gap: 0 24px; + gap: 0 16px; margin: auto; - max-width: 1248px; + max-width: 1264px; height: var(--nav-height); padding: 0 24px; - font-family: var(--body-font-family); - color: var(--nav-text-color); + font-family: var(--nav-font); } header nav[aria-expanded='true'] { grid-template: 'hamburger brand' var(--nav-height) 'sections sections' 1fr - 'tools tools' var(--nav-height) / auto 1fr; + 'tools tools' auto / auto 1fr; overflow-y: auto; min-height: 100dvh; } -@media (width >= 900px) { - header .nav-wrapper { - position: relative; - } - - header nav { - display: flex; - justify-content: space-between; - gap: 0 32px; - max-width: 1264px; - padding: 0 32px; - } - - header nav[aria-expanded='true'] { - min-height: 0; - overflow: visible; - } -} - header nav p { margin: 0; line-height: 1; @@ -62,7 +46,7 @@ header nav a:any-link { text-decoration: none; } -/* hamburger */ +/* ---- hamburger (mobile) ---- */ header nav .nav-hamburger { grid-area: hamburger; height: 22px; @@ -78,9 +62,6 @@ header nav .nav-hamburger button { padding: 0; background-color: transparent; color: inherit; - overflow: initial; - text-overflow: initial; - white-space: initial; } header nav .nav-hamburger-icon, @@ -107,17 +88,9 @@ header nav[aria-expanded='false'] .nav-hamburger-icon::after { background: currentcolor; } -header nav[aria-expanded='false'] .nav-hamburger-icon::before { - top: -6px; -} - -header nav[aria-expanded='false'] .nav-hamburger-icon::after { - top: 6px; -} - -header nav[aria-expanded='true'] .nav-hamburger-icon { - height: 22px; -} +header nav[aria-expanded='false'] .nav-hamburger-icon::before { top: -6px; } +header nav[aria-expanded='false'] .nav-hamburger-icon::after { top: 6px; } +header nav[aria-expanded='true'] .nav-hamburger-icon { height: 22px; } header nav[aria-expanded='true'] .nav-hamburger-icon::before, header nav[aria-expanded='true'] .nav-hamburger-icon::after { @@ -136,34 +109,29 @@ header nav[aria-expanded='true'] .nav-hamburger-icon::after { transform: rotate(-45deg); } -@media (width >= 900px) { - header nav .nav-hamburger { - display: none; - visibility: hidden; - } -} - -/* brand */ +/* ---- brand (logo) ---- */ header .nav-brand { grid-area: brand; - flex-basis: auto; - font-family: var(--heading-font-family); - font-size: var(--heading-font-size-s); - font-weight: 700; - letter-spacing: 0.02em; - line-height: 1; + display: flex; + align-items: center; } -header .nav-brand a:any-link { - color: var(--nav-text-color); -} +header .nav-brand a:any-link { color: var(--nav-text-color); } header nav .nav-brand img { width: 200px; height: auto; + display: block; } -/* sections */ +header nav .nav-brand p:not(:has(img)) { + font-family: var(--nav-font); + font-size: var(--heading-font-size-s); + font-weight: 700; + letter-spacing: 0.02em; +} + +/* ---- primary menu (sections) ---- */ header nav .nav-sections { grid-area: sections; flex: 1 1 auto; @@ -183,21 +151,13 @@ header nav .nav-sections ul { font-size: var(--body-font-size-s); } -header nav .nav-sections ul > li { - font-weight: 600; -} +header nav .nav-sections ul > li { font-weight: 600; } +header nav .nav-sections ul > li > ul { margin-top: 0; } +header nav .nav-sections ul > li > ul > li { font-weight: 400; } -header nav .nav-sections ul > li > ul { - margin-top: 0; -} - -header nav .nav-sections ul > li > ul > li { - font-weight: 400; -} - -/* mobile: nested links indented on the navy panel */ +/* mobile drawer nesting */ header nav .nav-sections .default-content-wrapper > ul > li { - padding: 12px 0; + padding: 14px 0; border-bottom: 1px solid rgb(255 255 255 / 15%); } @@ -210,55 +170,153 @@ header nav .nav-sections .default-content-wrapper > ul > li > ul > li { opacity: 0.85; } +/* ---- utility (tools) ---- */ +header nav .nav-tools { grid-area: tools; } + +header nav .nav-tools, +header nav .nav-tools .default-content-wrapper { + display: flex; + align-items: center; + gap: 22px; +} + +/* stylelint-disable-next-line no-descending-specificity */ +header nav .nav-tools p { + display: flex; + align-items: center; + gap: 6px; +} + +header nav .nav-tools a:any-link { + color: var(--nav-text-color); + font-size: var(--body-font-size-xs); + font-weight: 500; + white-space: nowrap; + display: inline-flex; + align-items: center; + gap: 6px; +} + +header nav .nav-tools a:hover { color: var(--cta-color); } + +header nav .nav-tools .icon { + width: 20px; + height: 20px; +} + +header nav .nav-tools .icon img { + width: 20px; + height: 20px; + filter: brightness(0) invert(1); +} + +/* ---- announcement bar ---- */ +header nav .nav-announcement { + grid-area: announcement; + display: none; + visibility: hidden; +} + +header nav .nav-announcement .default-content-wrapper { width: 100%; } + +/* ---- search widget ---- */ +header nav .nav-search { + grid-area: search; + display: none; + visibility: hidden; +} + +/* ========================================================================== + Desktop (>= 900px) + ========================================================================== */ @media (width >= 900px) { - header nav .nav-sections { - display: block; - visibility: visible; - white-space: nowrap; + header .nav-wrapper { position: fixed; } + + header nav { + display: grid; + grid-template: + 'brand tools' auto + 'sections sections' auto + 'announcement announcement' auto + 'search search' auto / auto 1fr; + align-items: center; + gap: 0; + height: auto; + max-width: none; + padding: 0; } - header nav[aria-expanded='true'] .nav-sections { - align-self: unset; + header nav, + header nav[aria-expanded='true'] { + grid-template: + 'brand tools' auto + 'sections sections' auto + 'announcement announcement' auto + 'search search' auto / auto 1fr; + min-height: 0; + overflow: visible; } - header nav .nav-sections .nav-drop { - position: relative; - padding-right: 16px; - cursor: pointer; + header nav .nav-hamburger { + display: none; + visibility: hidden; } - header nav .nav-sections .nav-drop::after { - content: ''; - display: inline-block; - position: absolute; - top: 0.5em; - right: 2px; - transform: rotate(135deg); - width: 6px; - height: 6px; - border: 2px solid currentcolor; - border-radius: 0 1px 0 0; - border-width: 2px 2px 0 0; + /* top bar: brand + utility, centered container */ + header nav .nav-brand, + header nav .nav-tools { + padding-block: 14px; + max-width: 1264px; + width: 100%; + margin-inline: auto; + padding-inline: 32px; + box-sizing: border-box; } - header nav .nav-sections .nav-drop[aria-expanded='true']::after { - top: unset; - bottom: 0.5em; - transform: rotate(315deg); + header nav .nav-brand { + grid-area: brand; + justify-content: flex-start; + padding-right: 0; } - header nav .nav-sections ul { + header nav .nav-tools { + grid-area: tools; + justify-content: flex-end; + padding-left: 0; + } + + /* primary menu bar */ + header nav .nav-sections { + grid-area: sections; + display: block; + visibility: visible; + white-space: nowrap; + width: 100%; + } + + header nav[aria-expanded='true'] .nav-sections { align-self: unset; } + + header nav .nav-sections .default-content-wrapper { + max-width: 1264px; + margin-inline: auto; + padding: 0 32px 14px; + } + + header nav .nav-sections .default-content-wrapper > ul { display: flex; - gap: 28px; + gap: 32px; margin: 0; + font-size: 20px; } header nav .nav-sections .default-content-wrapper > ul > li { flex: 0 1 auto; - position: relative; - padding: 0 0 4px; + position: static; + padding: 0 0 6px; border-bottom: 3px solid transparent; - transition: border-color 0.15s ease, color 0.15s ease; + font-weight: 600; + letter-spacing: 0.01em; + transition: border-color 0.15s ease; } header nav .nav-sections .default-content-wrapper > ul > li:hover, @@ -266,82 +324,173 @@ header nav .nav-sections .default-content-wrapper > ul > li > ul > li { border-bottom-color: var(--cta-color); } - header nav .nav-sections .default-content-wrapper > ul > li.nav-drop { + /* dropdown caret */ + header nav .nav-sections .nav-drop { + position: static; padding-right: 18px; + cursor: pointer; + } + + header nav .nav-sections .nav-drop > p, + header nav .nav-sections .nav-drop { + position: relative; + } + + header nav .nav-sections .nav-drop::after { + content: ''; + display: inline-block; + position: absolute; + top: 0.45em; + right: 2px; + transform: rotate(135deg); + width: 7px; + height: 7px; + border: 2px solid currentcolor; + border-width: 2px 2px 0 0; } + header nav .nav-sections .nav-drop[aria-expanded='true']::after { + top: unset; + bottom: 0.45em; + transform: rotate(315deg); + } + + /* ---- mega-menu dropdown panel ---- */ header nav .nav-sections .default-content-wrapper > ul > li > ul { display: none; - position: relative; } header nav .nav-sections .default-content-wrapper > ul > li[aria-expanded='true'] > ul { display: block; position: absolute; - left: -16px; - width: 250px; - top: calc(100% + 3px); - padding: 8px 0; + left: 0; + right: 0; + top: 100%; + margin: 0 auto; + max-width: 1264px; + padding: 24px 32px; + columns: 3; + column-gap: 24px; background-color: #fff; color: var(--text-color); border-top: 3px solid var(--cta-color); - border-radius: 0 0 6px 6px; - box-shadow: 0 8px 24px rgb(0 34 68 / 20%); - white-space: initial; + box-shadow: 0 12px 28px rgb(0 34 68 / 22%); } /* stylelint-disable-next-line no-descending-specificity */ header nav .nav-sections .default-content-wrapper > ul > li > ul > li { - padding: 10px 20px; + padding: 8px 0; font-weight: 500; + font-size: var(--body-font-size-xs); + break-inside: avoid; opacity: 1; border-bottom: 0; } - header nav .nav-sections .default-content-wrapper > ul > li > ul > li:hover { - background-color: var(--light-color); - } - header nav .nav-sections .default-content-wrapper > ul > li > ul a:any-link { color: var(--nav-bg-color); } - header nav .nav-sections .default-content-wrapper > ul > li > ul > li:hover a:any-link { + header nav .nav-sections .default-content-wrapper > ul > li > ul a:hover { color: var(--cta-color); + text-decoration: underline; } -} -/* tools */ -header nav .nav-tools { - grid-area: tools; -} + /* ---- announcement bar ---- */ + header nav .nav-announcement { + grid-area: announcement; + display: block; + visibility: visible; + background-color: var(--cta-color); + color: #fff; + font-weight: 600; + } -header nav .nav-tools, -header nav .nav-tools .default-content-wrapper { - display: flex; - align-items: center; - gap: 20px; -} + header nav .nav-announcement .default-content-wrapper { + max-width: 1264px; + margin-inline: auto; + padding: 8px 32px; + display: flex; + align-items: center; + justify-content: center; + gap: 16px; + font-size: var(--body-font-size-xs); + } -header nav .nav-tools p { - display: flex; - align-items: center; -} + /* stylelint-disable-next-line no-descending-specificity */ + header nav .nav-announcement a:any-link { + color: #fff; + text-decoration: underline; + text-underline-offset: 3px; + font-weight: 700; + } -header nav .nav-tools a:any-link { - color: var(--nav-text-color); - font-size: var(--body-font-size-xs); - font-weight: 500; - white-space: nowrap; -} + /* ---- search widget ---- */ + header nav .nav-search { + grid-area: search; + display: block; + visibility: visible; + background-color: var(--nav-bg-hover-color); + } -header nav .nav-tools a:hover { - color: var(--cta-color); -} + header nav .nav-search .default-content-wrapper { + max-width: 1264px; + margin-inline: auto; + padding: 12px 32px; + } -/* stylelint-disable-next-line no-descending-specificity */ -header nav .nav-tools img { - width: 20px; - height: 20px; - filter: brightness(0) invert(1); + /* stylelint-disable-next-line no-descending-specificity */ + header nav .nav-search .default-content-wrapper > ul { + list-style: none; + display: flex; + gap: 12px; + margin: 0; + padding: 0; + align-items: stretch; + } + + /* stylelint-disable-next-line no-descending-specificity */ + header nav .nav-search .default-content-wrapper > ul > li { + flex: 1 1 auto; + background: #fff; + color: var(--text-color); + border-radius: 4px; + padding: 10px 16px; + font-size: var(--body-font-size-xs); + font-weight: 500; + display: flex; + align-items: center; + justify-content: space-between; + } + + header nav .nav-search .default-content-wrapper > ul > li::after { + content: ''; + width: 8px; + height: 8px; + border: 2px solid var(--nav-bg-color); + border-width: 0 2px 2px 0; + transform: rotate(45deg) translateY(-2px); + margin-left: 8px; + } + + /* last item = Find Your Cruise button */ + header nav .nav-search .default-content-wrapper > ul > li:last-child { + flex: 0 0 auto; + background: var(--cta-color); + padding: 0; + } + + header nav .nav-search .default-content-wrapper > ul > li:last-child::after { display: none; } + + header nav .nav-search .default-content-wrapper > ul > li:last-child a:any-link { + color: #fff; + font-weight: 700; + padding: 12px 28px; + display: block; + white-space: nowrap; + } + + header nav .nav-search .default-content-wrapper > ul > li:last-child:hover { + background: var(--cta-hover-color); + } } diff --git a/blocks/header/header.js b/blocks/header/header.js index c7d6ea2..d604409 100644 --- a/blocks/header/header.js +++ b/blocks/header/header.js @@ -124,14 +124,16 @@ export default async function decorate(block) { nav.id = 'nav'; while (fragment.firstElementChild) nav.append(fragment.firstElementChild); - const classes = ['brand', 'sections', 'tools']; + // Region classes, in fragment section order: + // 1 brand, 2 sections (primary menu), 3 tools (utility), 4 announcement, 5 search + const classes = ['brand', 'sections', 'tools', 'announcement', 'search']; classes.forEach((c, i) => { const section = nav.children[i]; if (section) section.classList.add(`nav-${c}`); }); const navBrand = nav.querySelector('.nav-brand'); - const brandLink = navBrand.querySelector('.button'); + const brandLink = navBrand?.querySelector('.button'); if (brandLink) { brandLink.className = ''; brandLink.closest('.button-container').className = ''; diff --git a/head.html b/head.html index f55175f..8ee3445 100644 --- a/head.html +++ b/head.html @@ -7,3 +7,6 @@ + + + diff --git a/icons/chat.svg b/icons/chat.svg new file mode 100644 index 0000000..38ee760 --- /dev/null +++ b/icons/chat.svg @@ -0,0 +1 @@ + diff --git a/icons/globe.svg b/icons/globe.svg new file mode 100644 index 0000000..e550ec4 --- /dev/null +++ b/icons/globe.svg @@ -0,0 +1 @@ + diff --git a/icons/heart.svg b/icons/heart.svg new file mode 100644 index 0000000..973f2d9 --- /dev/null +++ b/icons/heart.svg @@ -0,0 +1 @@ + diff --git a/icons/user.svg b/icons/user.svg new file mode 100644 index 0000000..4088583 --- /dev/null +++ b/icons/user.svg @@ -0,0 +1 @@ + diff --git a/styles/styles.css b/styles/styles.css index d05d190..595e64b 100644 --- a/styles/styles.css +++ b/styles/styles.css @@ -31,6 +31,10 @@ --body-font-family: roboto, roboto-fallback, sans-serif; --heading-font-family: roboto-condensed, roboto-condensed-fallback, sans-serif; + /* nav font — matches hollandamerica.com; upgrades to quasimoda once the + Adobe Fonts kit is added to head.html (see placeholder there) */ + --nav-font: quasimoda, var(--body-font-family); + /* body sizes */ --body-font-size-m: 22px; --body-font-size-s: 19px; From d9c3d793b06ee1d231b6bba1ead7a192362f4276 Mon Sep 17 00:00:00 2001 From: Lamont Crook Date: Wed, 8 Jul 2026 12:23:39 -0600 Subject: [PATCH 2/2] Remove cruise-search form from header The cruise-search widget doesn't belong in the header. Drop the search region from header.js region mapping and header.css (grid rows + widget styles); the matching section was also removed from the DA /fragments/nav source. Co-Authored-By: Claude Opus 4.8 --- blocks/header/header.css | 84 ++-------------------------------------- blocks/header/header.js | 4 +- 2 files changed, 5 insertions(+), 83 deletions(-) diff --git a/blocks/header/header.css b/blocks/header/header.css index 64cacf1..80e8c29 100644 --- a/blocks/header/header.css +++ b/blocks/header/header.css @@ -1,6 +1,6 @@ /* ========================================================================== Header / nav — styled to match hollandamerica.com - Layered layout: [brand | utility] / primary menu / announcement / search + Layered layout: [brand | utility] / primary menu / announcement ========================================================================== */ header .nav-wrapper { @@ -219,13 +219,6 @@ header nav .nav-announcement { header nav .nav-announcement .default-content-wrapper { width: 100%; } -/* ---- search widget ---- */ -header nav .nav-search { - grid-area: search; - display: none; - visibility: hidden; -} - /* ========================================================================== Desktop (>= 900px) ========================================================================== */ @@ -237,8 +230,7 @@ header nav .nav-search { grid-template: 'brand tools' auto 'sections sections' auto - 'announcement announcement' auto - 'search search' auto / auto 1fr; + 'announcement announcement' auto / auto 1fr; align-items: center; gap: 0; height: auto; @@ -251,8 +243,7 @@ header nav .nav-search { grid-template: 'brand tools' auto 'sections sections' auto - 'announcement announcement' auto - 'search search' auto / auto 1fr; + 'announcement announcement' auto / auto 1fr; min-height: 0; overflow: visible; } @@ -424,73 +415,4 @@ header nav .nav-search { text-underline-offset: 3px; font-weight: 700; } - - /* ---- search widget ---- */ - header nav .nav-search { - grid-area: search; - display: block; - visibility: visible; - background-color: var(--nav-bg-hover-color); - } - - header nav .nav-search .default-content-wrapper { - max-width: 1264px; - margin-inline: auto; - padding: 12px 32px; - } - - /* stylelint-disable-next-line no-descending-specificity */ - header nav .nav-search .default-content-wrapper > ul { - list-style: none; - display: flex; - gap: 12px; - margin: 0; - padding: 0; - align-items: stretch; - } - - /* stylelint-disable-next-line no-descending-specificity */ - header nav .nav-search .default-content-wrapper > ul > li { - flex: 1 1 auto; - background: #fff; - color: var(--text-color); - border-radius: 4px; - padding: 10px 16px; - font-size: var(--body-font-size-xs); - font-weight: 500; - display: flex; - align-items: center; - justify-content: space-between; - } - - header nav .nav-search .default-content-wrapper > ul > li::after { - content: ''; - width: 8px; - height: 8px; - border: 2px solid var(--nav-bg-color); - border-width: 0 2px 2px 0; - transform: rotate(45deg) translateY(-2px); - margin-left: 8px; - } - - /* last item = Find Your Cruise button */ - header nav .nav-search .default-content-wrapper > ul > li:last-child { - flex: 0 0 auto; - background: var(--cta-color); - padding: 0; - } - - header nav .nav-search .default-content-wrapper > ul > li:last-child::after { display: none; } - - header nav .nav-search .default-content-wrapper > ul > li:last-child a:any-link { - color: #fff; - font-weight: 700; - padding: 12px 28px; - display: block; - white-space: nowrap; - } - - header nav .nav-search .default-content-wrapper > ul > li:last-child:hover { - background: var(--cta-hover-color); - } } diff --git a/blocks/header/header.js b/blocks/header/header.js index d604409..3b8f036 100644 --- a/blocks/header/header.js +++ b/blocks/header/header.js @@ -125,8 +125,8 @@ export default async function decorate(block) { while (fragment.firstElementChild) nav.append(fragment.firstElementChild); // Region classes, in fragment section order: - // 1 brand, 2 sections (primary menu), 3 tools (utility), 4 announcement, 5 search - const classes = ['brand', 'sections', 'tools', 'announcement', 'search']; + // 1 brand, 2 sections (primary menu), 3 tools (utility), 4 announcement + const classes = ['brand', 'sections', 'tools', 'announcement']; classes.forEach((c, i) => { const section = nav.children[i]; if (section) section.classList.add(`nav-${c}`);