weg-shared-layout 0.0.41 → 0.0.42

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6,7 +6,7 @@ var appGlobals = require('./app-globals-V2Kpy_OQ.js');
6
6
  const defineCustomElements = async (win, options) => {
7
7
  if (typeof window === 'undefined') return undefined;
8
8
  await appGlobals.globalScripts();
9
- return index.bootstrapLazy([["weg-footer_2.cjs",[[513,"weg-footer",{"layout":[1],"resolved":[32]},null,{"layout":[{"watchLayout":0}]}],[513,"weg-header",{"layout":[1],"signedIn":[516,"signed-in"],"userName":[1,"user-name"],"accountBaseUrl":[1,"account-base-url"],"currentPath":[1,"current-path"],"resolved":[32],"menuOpen":[32],"openDropdown":[32]},[[8,"keydown","handleKeyDown"]],{"layout":[{"watchLayout":0}]}]]]], options);
9
+ return index.bootstrapLazy([["weg-footer_2.cjs",[[513,"weg-footer",{"layout":[1],"resolved":[32]},null,{"layout":[{"watchLayout":0}]}],[513,"weg-header",{"layout":[1],"signedIn":[516,"signed-in"],"userName":[1,"user-name"],"accountBaseUrl":[1,"account-base-url"],"currentPath":[1,"current-path"],"resolved":[32],"menuOpen":[32],"openDropdown":[32],"headerHidden":[32]},[[8,"keydown","handleKeyDown"]],{"layout":[{"watchLayout":0}]}]]]], options);
10
10
  };
11
11
 
12
12
  exports.setNonce = index.setNonce;
@@ -377,13 +377,19 @@ const LOGO_SRC = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA4QAAAFcCAYAAACQ
377
377
 
378
378
  const sharedCss = () => `:host{--weg-breakpoint-sm:640px;--weg-breakpoint-md:960px;--weg-breakpoint-lg:1280px;--weg-breakpoint-xl:1440px}:root,:host{--weg-container-breakpoint-sm:40rem;--weg-container-breakpoint-md:48rem;--weg-container-breakpoint-lg:64rem;--weg-container-breakpoint-xl:80rem;--weg-container-breakpoint-2xl:86rem;--weg-container-max-vw:95vw;--weg-container-padding-inline:1rem}@media (width >= 48rem){:root,:host{--weg-container-padding-inline:2rem}}.container{width:100%;max-width:var(--weg-container-max-vw);margin-inline:auto;padding-inline:var(--weg-container-padding-inline)}@media (width >= 40rem){.container{max-width:min(var(--weg-container-breakpoint-sm), var(--weg-container-max-vw))}}@media (width >= 48rem){.container{max-width:min(var(--weg-container-breakpoint-md), var(--weg-container-max-vw))}}@media (width >= 64rem){.container{max-width:min(var(--weg-container-breakpoint-lg), var(--weg-container-max-vw))}}@media (width >= 80rem){.container{max-width:min(var(--weg-container-breakpoint-xl), var(--weg-container-max-vw))}}@media (width >= 86rem){.container{max-width:min(var(--weg-container-breakpoint-xl), var(--weg-container-max-vw))}}*,*::before,*::after{box-sizing:border-box}:host{display:block;--weg-font-family:ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, 'Apple Color Emoji', 'Segoe UI Emoji';--weg-color-accent:#948eeb;--weg-purple-200:#cdcff8}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);white-space:nowrap;border:0}`;
379
379
 
380
- const wegHeaderCss = () => `:host{--weg-breakpoint-sm:640px;--weg-breakpoint-md:960px;--weg-breakpoint-lg:1280px;--weg-breakpoint-xl:1440px}.header{width:100%;border-bottom:2px solid var(--weg-color-accent);background:#ffffff;color:#0f172a;font-family:var(--weg-font-family)}@media (width >= 960px){.header{border-bottom-width:0.25rem}}:host{position:relative;z-index:20}.header--menu-open{position:fixed;inset:0;z-index:1000;display:flex;flex-direction:column;overflow:hidden}.header--menu-open .header-inner{flex:1 1 auto;flex-wrap:wrap;align-content:flex-start;min-height:0}.header--menu-open .main-nav-panel{display:block;flex:1 1 100%;width:100%;min-height:0;overflow-y:auto;border-top:1px solid #d8d4f7}@media (width >= 960px){.header--menu-open{position:static;inset:auto;z-index:auto;display:block;overflow:visible}.header--menu-open .header-inner{flex:unset;flex-wrap:nowrap;align-content:unset;min-height:unset}}.logo-link{display:inline-flex;align-items:center;text-decoration:none;outline:none}.logo-link:focus-visible{outline:2px solid var(--weg-color-accent);outline-offset:4px;border-radius:4px}.logo{height:2.5rem;width:auto}@media (width >= 960px){.logo{height:3rem}}@media (width >= 1280px){.logo{height:5rem}}.header-inner{display:flex;width:100%;min-width:0;align-items:center;justify-content:space-between;gap:0.75rem;padding-block:0.75rem;padding-inline:var(--weg-container-padding-inline)}@media (width >= 960px){.header-inner{flex-wrap:nowrap;gap:1.5rem;padding-block:1.25rem}}@media (width >= 1440px){.header-inner{padding-block:1.75rem}}.header-inner .logo-link{flex:1 1 auto;min-width:0;justify-content:center}@media (width >= 960px){.header-inner .logo-link{flex:0 0 auto;justify-content:flex-start}}.header-inner .logo{max-width:100%}.header-actions{display:flex;align-items:center;flex-shrink:0}@media (width >= 960px){.header-actions{display:none}}.main-nav-panel{display:none;margin-inline:-0.5rem}@media (width >= 960px){.main-nav-panel{display:flex;flex:1 1 auto;width:auto;min-width:0;justify-content:flex-end;overflow:visible;border-top:none}}.main-nav{padding:0 1rem 1.5rem}@media (width >= 960px){.main-nav{display:flex;align-items:center;justify-content:flex-end;flex-wrap:wrap;gap:1rem;padding:0}}.main-nav__list{list-style:none;margin:0;padding:0}@media (width >= 960px){.main-nav__list{display:flex;align-items:center;flex-wrap:wrap;gap:0.5rem}}@media (width >= 1280px){.main-nav__list{gap:1.5rem}}.main-nav__item{border-bottom:1px solid #d8d4f7}@media (width >= 960px){.main-nav__item{border-bottom:none}}.main-nav__item--dropdown{position:static}.nav-dropdown{position:relative}.nav-link{display:block;width:100%;padding:1rem 0;font-weight:600;color:inherit;text-decoration:none;outline:none}.nav-link:hover{opacity:0.85}.nav-link:focus-visible{outline:2px solid var(--weg-color-accent);outline-offset:2px;border-radius:4px}.nav-link--active{background:var(--weg-purple-200)}.nav-dropdown__trigger{display:flex;align-items:center;justify-content:space-between;gap:0.75rem;width:100%;padding:1rem 0;border:none;background:transparent;font:inherit;font-weight:600;color:inherit;text-align:left;cursor:pointer;outline:none}.nav-dropdown__trigger:hover{opacity:0.85}.nav-dropdown__trigger:focus-visible{outline:2px solid var(--weg-color-accent);outline-offset:2px;border-radius:4px}.nav-dropdown__trigger--open{background:transparent}.nav-dropdown__trigger--active{background:var(--weg-purple-200)}.toggle-icon{display:inline-flex;align-items:center;justify-content:center;width:1.5rem;height:1.5rem;border-radius:999rem;background:#312e81;color:#ffffff;flex-shrink:0}.nav-dropdown__panel{padding:0 0 0.75rem}@media (width >= 960px){.nav-dropdown__panel{position:absolute;top:calc(100% + 0.5rem);left:0;z-index:500;min-width:17.5rem;padding:0.75rem 0 0.75rem 0.75rem;border:1px solid #e2e8f0;border-radius:0.5rem;background:#f8fafc;box-shadow:0 0.25rem 1rem rgba(15, 23, 42, 0.08)}.nav-dropdown__panel::before{content:'';position:absolute;top:-0.5rem;left:0;right:0;height:0.5rem}}.nav-dropdown__accent{border-left:0.25rem solid var(--weg-color-accent);padding-left:0.75rem}.nav-dropdown__links{display:flex;flex-direction:column;gap:0.25rem}.nav-dropdown__link{display:block;padding:0.625rem 0;font-weight:400;color:inherit;text-decoration:none;outline:none}.nav-dropdown__link:hover{opacity:0.85}.nav-dropdown__link:focus-visible{outline:0.125rem solid var(--weg-color-accent);outline-offset:0.125rem;border-radius:0.25rem}.nav-dropdown__link--active{background:var(--weg-purple-200)}@media (width >= 960px){.nav-dropdown__link{padding:0.5rem;margin-right:0.75rem;border-radius:0.5rem;font-weight:600}.nav-dropdown__link:hover,.nav-dropdown__link:focus-visible{background:var(--weg-purple-200);opacity:1}.nav-dropdown__link--active{opacity:1}}@media (width >= 1280px){.nav-dropdown__link{padding:0.5rem 0.75rem}}.main-nav__item--auth>a{display:flex;align-items:center;gap:0.5rem;width:100%;padding:1rem 0}@media (width >= 960px){.nav-link,.nav-dropdown__trigger,.main-nav__item--auth>a{display:inline-flex;align-items:center;width:auto;padding:0.5rem;border-radius:0.5rem}.nav-link--active,.main-nav__item--auth>a.nav-link--active{background:var(--weg-purple-200)}.nav-dropdown__trigger{gap:0.5rem;cursor:pointer}.nav-dropdown__trigger--open{background:#f1f5f9}.nav-dropdown__trigger--active{background:var(--weg-purple-200)}}@media (width >= 1280px){.main-nav{font-size:1.25rem}.main-nav__item--auth>a{padding:0.5rem 0.75rem}}.sign-in-link,.sign-out-link,.auth-button{display:inline-flex;align-items:center;gap:0.5rem;font-weight:600;color:inherit;text-decoration:none;outline:none}.auth-button{padding:0;border:none;background:transparent;font:inherit;cursor:pointer}.sign-in-link:hover,.sign-out-link:hover,.auth-button:hover{opacity:0.85}.sign-in-link:focus-visible,.sign-out-link:focus-visible,.auth-button:focus-visible{outline:2px solid var(--weg-color-accent);outline-offset:4px;border-radius:4px}.icon-button{display:inline-flex;align-items:center;justify-content:center;width:2.5rem;height:2.5rem;padding:0;border:none;border-radius:0.5rem;background:transparent;color:inherit;cursor:pointer;text-decoration:none;outline:none}.icon-button:hover{background:#f1f5f9}.icon-button:focus-visible{outline:2px solid var(--weg-color-accent);outline-offset:2px}.menu-toggle{flex-shrink:0}@media (width >= 960px){.menu-toggle{display:none}}`;
380
+ const wegHeaderCss = () => `:host{--weg-breakpoint-sm:640px;--weg-breakpoint-md:960px;--weg-breakpoint-lg:1280px;--weg-breakpoint-xl:1440px}.header{width:100%;border-bottom:2px solid var(--weg-color-accent);background:#ffffff;color:#0f172a;font-family:var(--weg-font-family)}@media (width >= 960px){.header{border-bottom-width:0.25rem}}:host{position:relative;z-index:20;display:block;height:var(--weg-header-height, auto)}.header--fixed{position:fixed;top:0;left:0;right:0;z-index:20;transform:translateY(0);transition:transform 0.25s ease}.header--fixed.header--hidden{transform:translateY(-100%)}@media (prefers-reduced-motion: reduce){.header--fixed{transition:none}}.header--menu-open{position:fixed;inset:0;z-index:1000;display:flex;flex-direction:column;overflow:hidden}.header--menu-open .header-inner{flex:1 1 auto;flex-wrap:wrap;align-content:flex-start;min-height:0}.header--menu-open .main-nav-panel{display:block;flex:1 1 100%;width:100%;min-height:0;overflow-y:auto;border-top:1px solid #d8d4f7}@media (width >= 960px){.header--menu-open{position:static;inset:auto;z-index:auto;display:block;overflow:visible}.header--menu-open .header-inner{flex:unset;flex-wrap:nowrap;align-content:unset;min-height:unset}}.logo-link{display:inline-flex;align-items:center;text-decoration:none;outline:none}.logo-link:focus-visible{outline:2px solid var(--weg-color-accent);outline-offset:4px;border-radius:4px}.logo{height:2.5rem;width:auto}@media (width >= 960px){.logo{height:3rem}}@media (width >= 1280px){.logo{height:5rem}}.header-inner{display:flex;width:100%;min-width:0;align-items:center;justify-content:space-between;gap:0.75rem;padding-block:0.75rem;padding-inline:var(--weg-container-padding-inline)}@media (width >= 960px){.header-inner{flex-wrap:nowrap;gap:1.5rem;padding-block:1.25rem}}@media (width >= 1440px){.header-inner{padding-block:1.75rem}}.header-inner .logo-link{flex:1 1 auto;min-width:0;justify-content:center}@media (width >= 960px){.header-inner .logo-link{flex:0 0 auto;justify-content:flex-start}}.header-inner .logo{max-width:100%}.header-actions{display:flex;align-items:center;flex-shrink:0}@media (width >= 960px){.header-actions{display:none}}.main-nav-panel{display:none;margin-inline:-0.5rem}@media (width >= 960px){.main-nav-panel{display:flex;flex:1 1 auto;width:auto;min-width:0;justify-content:flex-end;overflow:visible;border-top:none}}.main-nav{padding:0 1rem 1.5rem}@media (width >= 960px){.main-nav{display:flex;align-items:center;justify-content:flex-end;flex-wrap:wrap;gap:1rem;padding:0}}.main-nav__list{list-style:none;margin:0;padding:0}@media (width >= 960px){.main-nav__list{display:flex;align-items:center;flex-wrap:wrap;gap:0.5rem}}@media (width >= 1280px){.main-nav__list{gap:1.5rem}}.main-nav__item{border-bottom:1px solid #d8d4f7}@media (width >= 960px){.main-nav__item{border-bottom:none}}.main-nav__item--dropdown{position:static}.nav-dropdown{position:relative}.nav-link{display:block;width:100%;padding:1rem 0;font-weight:600;color:inherit;text-decoration:none;outline:none}.nav-link:hover{opacity:0.85}.nav-link:focus-visible{outline:2px solid var(--weg-color-accent);outline-offset:2px;border-radius:4px}.nav-link--active{background:var(--weg-purple-200)}.nav-dropdown__trigger{display:flex;align-items:center;justify-content:space-between;gap:0.75rem;width:100%;padding:1rem 0;border:none;background:transparent;font:inherit;font-weight:600;color:inherit;text-align:left;cursor:pointer;outline:none}.nav-dropdown__trigger:hover{opacity:0.85}.nav-dropdown__trigger:focus-visible{outline:2px solid var(--weg-color-accent);outline-offset:2px;border-radius:4px}.nav-dropdown__trigger--open{background:transparent}.nav-dropdown__trigger--active{background:var(--weg-purple-200)}.toggle-icon{display:inline-flex;align-items:center;justify-content:center;width:1.5rem;height:1.5rem;border-radius:999rem;background:#312e81;color:#ffffff;flex-shrink:0}.nav-dropdown__panel{padding:0 0 0.75rem}@media (width >= 960px){.nav-dropdown__panel{position:absolute;top:calc(100% + 0.5rem);left:0;z-index:500;min-width:17.5rem;padding:0.75rem 0 0.75rem 0.75rem;border:1px solid #e2e8f0;border-radius:0.5rem;background:#f8fafc;box-shadow:0 0.25rem 1rem rgba(15, 23, 42, 0.08)}.nav-dropdown__panel::before{content:'';position:absolute;top:-0.5rem;left:0;right:0;height:0.5rem}}.nav-dropdown__accent{border-left:0.25rem solid var(--weg-color-accent);padding-left:0.75rem}.nav-dropdown__links{display:flex;flex-direction:column;gap:0.25rem;list-style:none;margin:0;padding:0}.nav-dropdown__link{display:block;padding:0.625rem 0;font-weight:400;color:inherit;text-decoration:none;outline:none}.nav-dropdown__link:hover{opacity:0.85}.nav-dropdown__link:focus-visible{outline:0.125rem solid var(--weg-color-accent);outline-offset:0.125rem;border-radius:0.25rem}.nav-dropdown__link--active{background:var(--weg-purple-200)}@media (width >= 960px){.nav-dropdown__link{padding:0.5rem;margin-right:0.75rem;border-radius:0.5rem;font-weight:600}.nav-dropdown__link:hover,.nav-dropdown__link:focus-visible{background:var(--weg-purple-200);opacity:1}.nav-dropdown__link--active{opacity:1}}@media (width >= 1280px){.nav-dropdown__link{padding:0.5rem 0.75rem}}.main-nav__item--auth>a{display:flex;align-items:center;gap:0.5rem;width:100%;padding:1rem 0}@media (width >= 960px){.nav-link,.nav-dropdown__trigger,.main-nav__item--auth>a{display:inline-flex;align-items:center;width:auto;padding:0.5rem;border-radius:0.5rem}.nav-link--active,.main-nav__item--auth>a.nav-link--active{background:var(--weg-purple-200)}.nav-dropdown__trigger{gap:0.5rem;cursor:pointer}.nav-dropdown__trigger--open{background:#f1f5f9}.nav-dropdown__trigger--active{background:var(--weg-purple-200)}}@media (width >= 1280px){.main-nav{font-size:1.25rem}.main-nav__item--auth>a{padding:0.5rem 0.75rem}}.sign-in-link,.sign-out-link,.auth-button{display:inline-flex;align-items:center;gap:0.5rem;font-weight:600;color:inherit;text-decoration:none;outline:none}.auth-button{padding:0;border:none;background:transparent;font:inherit;cursor:pointer}.sign-in-link:hover,.sign-out-link:hover,.auth-button:hover{opacity:0.85}.sign-in-link:focus-visible,.sign-out-link:focus-visible,.auth-button:focus-visible{outline:2px solid var(--weg-color-accent);outline-offset:4px;border-radius:4px}.icon-button{display:inline-flex;align-items:center;justify-content:center;width:2.5rem;height:2.5rem;padding:0;border:none;border-radius:0.5rem;background:transparent;color:inherit;cursor:pointer;text-decoration:none;outline:none}.icon-button:hover{background:#f1f5f9}.icon-button:focus-visible{outline:2px solid var(--weg-color-accent);outline-offset:2px}.menu-toggle{flex-shrink:0}@media (width >= 960px){.menu-toggle{display:none}}`;
381
381
 
382
382
  const WEG_HOME = 'https://www.warwickemploymentgroup.com';
383
383
  const DEFAULT_ACCOUNT_HOME = 'https://account.warwickemploymentgroup.com';
384
+ /** Stay visible while scrolling down through the first half of the viewport. */
385
+ const HEADER_SCROLL_HIDE_THRESHOLD_VH = 0.5;
386
+ const HEADER_SCROLL_DIRECTION_DELTA = 5;
384
387
  const DEFAULT_LOGO_HREF = `${WEG_HOME}/`;
385
388
  /** Placeholder href — sign-out is handled via `wegAuthClick`, not navigation. */
386
389
  const SIGN_OUT_HREF = '#';
390
+ const MAIN_NAV_LABEL = 'Main navigation';
391
+ const OPEN_MAIN_NAV_LABEL = 'Open main navigation';
392
+ const CLOSE_MAIN_NAV_LABEL = 'Close main navigation';
387
393
  function normalizeAccountBase(input) {
388
394
  const base = input?.trim() || DEFAULT_ACCOUNT_HOME;
389
395
  return base.replace(/\/$/, '');
@@ -519,9 +525,16 @@ const WegHeader = class {
519
525
  resolved = EMPTY_HEADER;
520
526
  menuOpen = false;
521
527
  openDropdown = null;
528
+ headerHidden = false;
522
529
  boundHandleDocumentClick = this.handleDocumentClick.bind(this);
523
530
  boundHandleViewportChange = this.handleViewportChange.bind(this);
524
531
  boundHandleHoverCapabilityChange = this.handleHoverCapabilityChange.bind(this);
532
+ boundHandleScroll = this.handleScroll.bind(this);
533
+ headerResizeObserver;
534
+ lastScrollY = 0;
535
+ scrollTicking = false;
536
+ bodyScrollLocked = false;
537
+ bodyScrollLockY = 0;
525
538
  hoverCloseTimer = null;
526
539
  hoverOpenEnabled = false;
527
540
  desktopMediaQuery;
@@ -542,15 +555,69 @@ const WegHeader = class {
542
555
  this.updateHoverDropdownEnabled();
543
556
  this.handleViewportChange();
544
557
  }
558
+ componentDidLoad() {
559
+ const header = this.el.shadowRoot?.querySelector('.header');
560
+ if (!header)
561
+ return;
562
+ this.headerResizeObserver = new ResizeObserver(() => this.syncHeaderHeight());
563
+ this.headerResizeObserver.observe(header);
564
+ this.syncHeaderHeight();
565
+ this.lastScrollY = window.scrollY;
566
+ this.updateHeaderVisibility();
567
+ }
545
568
  connectedCallback() {
546
569
  document.addEventListener('click', this.boundHandleDocumentClick);
570
+ window.addEventListener('scroll', this.boundHandleScroll, { passive: true });
547
571
  }
548
572
  disconnectedCallback() {
549
573
  document.removeEventListener('click', this.boundHandleDocumentClick);
574
+ window.removeEventListener('scroll', this.boundHandleScroll);
575
+ this.unlockBodyScroll();
576
+ this.headerResizeObserver?.disconnect();
550
577
  this.desktopMediaQuery?.removeEventListener('change', this.boundHandleViewportChange);
551
578
  this.hoverCapableMediaQuery?.removeEventListener('change', this.boundHandleHoverCapabilityChange);
552
579
  this.cancelScheduledDropdownClose();
553
580
  }
581
+ syncHeaderHeight() {
582
+ if (this.isMobileMenuActive())
583
+ return;
584
+ const header = this.el.shadowRoot?.querySelector('.header');
585
+ if (!header)
586
+ return;
587
+ this.el.style.setProperty('--weg-header-height', `${header.offsetHeight}px`);
588
+ }
589
+ handleScroll() {
590
+ if (this.scrollTicking)
591
+ return;
592
+ this.scrollTicking = true;
593
+ requestAnimationFrame(() => {
594
+ this.scrollTicking = false;
595
+ this.updateHeaderVisibility();
596
+ });
597
+ }
598
+ updateHeaderVisibility() {
599
+ if (this.isMobileMenuActive()) {
600
+ if (this.headerHidden)
601
+ this.headerHidden = false;
602
+ return;
603
+ }
604
+ const scrollY = window.scrollY;
605
+ const delta = scrollY - this.lastScrollY;
606
+ const threshold = window.innerHeight * HEADER_SCROLL_HIDE_THRESHOLD_VH;
607
+ let nextHidden = this.headerHidden;
608
+ if (scrollY <= threshold) {
609
+ nextHidden = false;
610
+ }
611
+ else if (Math.abs(delta) >= HEADER_SCROLL_DIRECTION_DELTA) {
612
+ nextHidden = delta > 0;
613
+ }
614
+ this.lastScrollY = scrollY;
615
+ if (nextHidden === this.headerHidden)
616
+ return;
617
+ if (nextHidden)
618
+ this.closeDropdown();
619
+ this.headerHidden = nextHidden;
620
+ }
554
621
  /**
555
622
  * Desktop dropdowns open on hover when viewport is md+ and the device reports hover support.
556
623
  * Uses (hover: hover) only — not (pointer: fine), which breaks in DevTools and hybrid devices.
@@ -568,10 +635,74 @@ const WegHeader = class {
568
635
  }
569
636
  handleViewportChange() {
570
637
  if (this.desktopMediaQuery?.matches) {
571
- this.closeMenu();
638
+ this.closeMenu({ announce: false, focusToggle: false });
572
639
  }
573
640
  this.updateHoverDropdownEnabled();
574
641
  }
642
+ announceToScreenReader(message) {
643
+ const region = this.el.shadowRoot?.querySelector('[data-weg-sr-live]');
644
+ if (!region)
645
+ return;
646
+ region.textContent = '';
647
+ requestAnimationFrame(() => {
648
+ region.textContent = message;
649
+ });
650
+ }
651
+ getMenuToggleButton() {
652
+ return this.el.shadowRoot?.querySelector('.menu-toggle');
653
+ }
654
+ getFirstNavFocusable() {
655
+ const panel = this.el.shadowRoot?.querySelector('#weg-header-main-nav');
656
+ if (!panel)
657
+ return null;
658
+ const focusables = panel.querySelectorAll('a[href], button:not([disabled])');
659
+ return focusables[0] ?? null;
660
+ }
661
+ focusFirstNavItem() {
662
+ setTimeout(() => {
663
+ const attemptFocus = (retries = 8) => {
664
+ const target = this.getFirstNavFocusable();
665
+ if (target) {
666
+ target.focus();
667
+ return;
668
+ }
669
+ if (retries > 0) {
670
+ requestAnimationFrame(() => attemptFocus(retries - 1));
671
+ }
672
+ };
673
+ attemptFocus();
674
+ }, 0);
675
+ }
676
+ focusMenuToggle() {
677
+ const attemptFocus = (retries = 8) => {
678
+ const toggle = this.getMenuToggleButton();
679
+ if (toggle) {
680
+ toggle.focus();
681
+ return;
682
+ }
683
+ if (retries > 0) {
684
+ requestAnimationFrame(() => attemptFocus(retries - 1));
685
+ }
686
+ };
687
+ attemptFocus();
688
+ }
689
+ getMenuGroupLinkCount(label) {
690
+ const group = this.getActiveMenu().find((item) => isMenuGroup(item) && item.label === label);
691
+ return group?.items?.length ?? 0;
692
+ }
693
+ formatLinkCount(count) {
694
+ return count === 1 ? '1 link' : `${count} links`;
695
+ }
696
+ formatItemCount(count) {
697
+ return count === 1 ? '1 item' : `${count} items`;
698
+ }
699
+ announceSubmenuExpanded(label) {
700
+ const linkCount = this.getMenuGroupLinkCount(label);
701
+ this.announceToScreenReader(`${label} submenu expanded. ${this.formatLinkCount(linkCount)}.`);
702
+ }
703
+ announceSubmenuCollapsed(label) {
704
+ this.announceToScreenReader(`${label} submenu collapsed.`);
705
+ }
575
706
  isMobileMenuActive() {
576
707
  return this.menuOpen && !this.desktopMediaQuery?.matches;
577
708
  }
@@ -581,8 +712,39 @@ const WegHeader = class {
581
712
  handleKeyDown(event) {
582
713
  if (event.key !== 'Escape')
583
714
  return;
584
- this.menuOpen = false;
585
- this.closeDropdown();
715
+ if (this.openDropdown) {
716
+ event.preventDefault();
717
+ this.closeDropdownAndFocusTrigger(this.openDropdown);
718
+ return;
719
+ }
720
+ if (this.menuOpen) {
721
+ event.preventDefault();
722
+ this.closeMenu({ focusToggle: true });
723
+ }
724
+ }
725
+ lockBodyScroll() {
726
+ if (this.bodyScrollLocked)
727
+ return;
728
+ this.bodyScrollLockY = window.scrollY;
729
+ document.body.style.overflow = 'hidden';
730
+ document.body.style.position = 'fixed';
731
+ document.body.style.top = `-${this.bodyScrollLockY}px`;
732
+ document.body.style.left = '0';
733
+ document.body.style.right = '0';
734
+ document.body.style.width = '100%';
735
+ this.bodyScrollLocked = true;
736
+ }
737
+ unlockBodyScroll() {
738
+ if (!this.bodyScrollLocked)
739
+ return;
740
+ document.body.style.overflow = '';
741
+ document.body.style.position = '';
742
+ document.body.style.top = '';
743
+ document.body.style.left = '';
744
+ document.body.style.right = '';
745
+ document.body.style.width = '';
746
+ window.scrollTo(0, this.bodyScrollLockY);
747
+ this.bodyScrollLocked = false;
586
748
  }
587
749
  handleDocumentClick(event) {
588
750
  const target = event.target;
@@ -613,10 +775,12 @@ const WegHeader = class {
613
775
  }
614
776
  toggleDropdown(label) {
615
777
  if (this.openDropdown === label) {
778
+ this.announceSubmenuCollapsed(label);
616
779
  this.closeDropdown();
617
780
  return;
618
781
  }
619
782
  this.openDropdownMenu(label);
783
+ this.announceSubmenuExpanded(label);
620
784
  }
621
785
  getDropdownPanelId(label) {
622
786
  return `weg-header-dropdown-${label.trim().toLowerCase().replace(/\s+/g, '-')}`;
@@ -669,29 +833,111 @@ const WegHeader = class {
669
833
  if (event.key !== 'ArrowDown')
670
834
  return;
671
835
  event.preventDefault();
672
- this.openDropdownMenu(label);
836
+ if (this.openDropdown !== label) {
837
+ this.openDropdownMenu(label);
838
+ this.announceSubmenuExpanded(label);
839
+ }
673
840
  this.focusFirstDropdownLink(itemEl);
674
841
  }
842
+ getDropdownLinks(container) {
843
+ return Array.from(container.querySelectorAll('.nav-dropdown__link'));
844
+ }
845
+ focusDropdownLink(container, index) {
846
+ const attemptFocus = (retries = 8) => {
847
+ const links = this.getDropdownLinks(container);
848
+ if (links[index]) {
849
+ links[index].focus();
850
+ return;
851
+ }
852
+ if (retries > 0) {
853
+ requestAnimationFrame(() => attemptFocus(retries - 1));
854
+ }
855
+ };
856
+ attemptFocus();
857
+ }
675
858
  focusFirstDropdownLink(itemEl) {
676
- setTimeout(() => {
677
- const firstLink = itemEl.querySelector('.nav-dropdown__link');
678
- firstLink?.focus();
679
- }, 0);
859
+ this.focusDropdownLink(itemEl, 0);
860
+ }
861
+ getDropdownContainer(label) {
862
+ const panelId = this.getDropdownPanelId(label);
863
+ return this.el.shadowRoot?.querySelector(`#${panelId}-trigger`)?.closest('.nav-dropdown') ?? null;
864
+ }
865
+ closeDropdownAndFocusTrigger(labelOrContainer) {
866
+ const container = typeof labelOrContainer === 'string'
867
+ ? this.getDropdownContainer(labelOrContainer)
868
+ : labelOrContainer;
869
+ const trigger = container?.querySelector('.nav-dropdown__trigger');
870
+ const label = typeof labelOrContainer === 'string'
871
+ ? labelOrContainer
872
+ : (trigger?.querySelector('.nav-dropdown__label')?.textContent?.trim() ?? '');
873
+ if (label && this.openDropdown === label) {
874
+ this.announceSubmenuCollapsed(label);
875
+ }
876
+ this.closeDropdown();
877
+ const attemptFocus = (retries = 8) => {
878
+ if (trigger && this.el.shadowRoot?.contains(trigger)) {
879
+ trigger.focus();
880
+ return;
881
+ }
882
+ if (retries > 0) {
883
+ requestAnimationFrame(() => attemptFocus(retries - 1));
884
+ }
885
+ };
886
+ attemptFocus();
887
+ }
888
+ handleDropdownLinkKeyDown(event, container) {
889
+ const links = this.getDropdownLinks(container);
890
+ const currentIndex = links.indexOf(event.currentTarget);
891
+ if (currentIndex === -1)
892
+ return;
893
+ if (event.key === 'ArrowDown') {
894
+ event.preventDefault();
895
+ links[(currentIndex + 1) % links.length]?.focus();
896
+ return;
897
+ }
898
+ if (event.key === 'ArrowUp') {
899
+ event.preventDefault();
900
+ links[(currentIndex - 1 + links.length) % links.length]?.focus();
901
+ return;
902
+ }
903
+ if (event.key === 'Escape') {
904
+ event.preventDefault();
905
+ event.stopPropagation();
906
+ this.closeDropdownAndFocusTrigger(container);
907
+ }
680
908
  }
681
909
  toggleMenu() {
682
910
  if (this.menuOpen) {
683
- this.closeMenu();
911
+ this.closeMenu({ focusToggle: false });
684
912
  return;
685
913
  }
686
914
  this.openMenu();
687
915
  }
688
916
  openMenu() {
689
917
  this.menuOpen = true;
918
+ this.headerHidden = false;
690
919
  this.closeDropdown();
920
+ if (!this.desktopMediaQuery?.matches) {
921
+ this.lockBodyScroll();
922
+ const itemCount = this.getActiveMenu().length;
923
+ this.announceToScreenReader(`${MAIN_NAV_LABEL} opened. ${this.formatItemCount(itemCount)}.`);
924
+ this.focusFirstNavItem();
925
+ }
691
926
  }
692
- closeMenu() {
927
+ closeMenu(options = {}) {
928
+ const { announce = true, focusToggle = false } = options;
929
+ const wasMobileActive = this.isMobileMenuActive();
693
930
  this.menuOpen = false;
694
931
  this.closeDropdown();
932
+ this.unlockBodyScroll();
933
+ this.syncHeaderHeight();
934
+ this.updateHeaderVisibility();
935
+ if (announce && wasMobileActive) {
936
+ this.announceToScreenReader(`${MAIN_NAV_LABEL} closed.`);
937
+ }
938
+ if (focusToggle) {
939
+ this.focusMenuToggle();
940
+ }
695
941
  }
696
942
  getAccountHome() {
697
943
  return normalizeAccountBase(this.accountBaseUrl);
@@ -762,13 +1008,17 @@ const WegHeader = class {
762
1008
  }, "aria-expanded": isOpen ? 'true' : 'false', "aria-haspopup": "true", "aria-controls": panelId, id: `${panelId}-trigger`, onClick: (event) => this.handleDropdownTriggerClick(event, item.label), onKeyDown: (event) => {
763
1009
  const container = event.currentTarget.closest('.nav-dropdown');
764
1010
  this.handleDropdownTriggerKeyDown(event, item.label, container);
765
- } }, index.h("span", { class: "nav-dropdown__label" }, item.label), index.h(ToggleIcon, { expanded: isOpen })), isOpen ? (index.h("div", { class: "nav-dropdown__panel", id: panelId, role: "region", "aria-labelledby": `${panelId}-trigger`, onMouseEnter: () => this.handleDropdownPanelPointerEnter(item.label), onMouseLeave: (event) => this.handleDropdownPanelPointerLeave(event) }, index.h("div", { class: "nav-dropdown__accent" }, index.h("div", { class: "nav-dropdown__links" }, items.map((child) => {
1011
+ } }, index.h("span", { class: "nav-dropdown__label" }, item.label), index.h(ToggleIcon, { expanded: isOpen })), isOpen ? (index.h("div", { class: "nav-dropdown__panel", id: panelId, role: "region", "aria-labelledby": `${panelId}-trigger`, onMouseEnter: () => this.handleDropdownPanelPointerEnter(item.label), onMouseLeave: (event) => this.handleDropdownPanelPointerLeave(event) }, index.h("div", { class: "nav-dropdown__accent" }, index.h("ul", { class: "nav-dropdown__links" }, items.map((child, index$1) => {
766
1012
  const childActive = this.isNavItemActive(child.href, 'exact');
767
1013
  const ariaCurrent = this.isAriaCurrentHref(child.href, ariaCurrentHref);
768
- return (index.h("a", { class: {
1014
+ const positionLabel = `${child.label}, link ${index$1 + 1} of ${items.length}`;
1015
+ return (index.h("li", { key: `${item.label}:${child.label}` }, index.h("a", { class: {
769
1016
  'nav-dropdown__link': true,
770
1017
  'nav-dropdown__link--active': childActive,
771
- }, href: child.href, key: `${item.label}:${child.label}`, "aria-current": ariaCurrent ? 'page' : undefined, onClick: () => onNavigate?.() }, child.label));
1018
+ }, href: child.href, "aria-label": positionLabel, "aria-current": ariaCurrent ? 'page' : undefined, onClick: () => onNavigate?.(), onKeyDown: (event) => {
1019
+ const dropdownContainer = event.currentTarget.closest('.nav-dropdown');
1020
+ this.handleDropdownLinkKeyDown(event, dropdownContainer);
1021
+ } }, child.label)));
772
1022
  }))))) : null)));
773
1023
  }
774
1024
  handleAuthClick(event, action, _href, onNavigate) {
@@ -831,7 +1081,7 @@ const WegHeader = class {
831
1081
  }
832
1082
  renderNav(onNavigate) {
833
1083
  const ariaCurrentHref = this.resolveAriaCurrentHref();
834
- return (index.h("nav", { class: "main-nav", "aria-label": "Main" }, index.h("ul", { class: "main-nav__list" }, this.getActiveMenu().map((item) => this.renderNavItem(item, onNavigate, ariaCurrentHref)))));
1084
+ return (index.h("nav", { class: "main-nav", "aria-label": MAIN_NAV_LABEL }, index.h("ul", { class: "main-nav__list" }, this.getActiveMenu().map((item) => this.renderNavItem(item, onNavigate, ariaCurrentHref)))));
835
1085
  }
836
1086
  renderCompactAuth(onNavigate) {
837
1087
  if (this.signedIn) {
@@ -852,10 +1102,12 @@ const WegHeader = class {
852
1102
  const logoSrc = this.getLogoSrc();
853
1103
  const closeMenu = () => this.closeMenu();
854
1104
  const mobileMenuActive = this.isMobileMenuActive();
855
- return (index.h("header", { key: '6b932d0c3dc20b53292b61fa3403e26e35182d05', class: {
1105
+ return (index.h("header", { key: '429d9af0996fa37484ebeea36f1e071fe0ba0789', class: {
856
1106
  header: true,
1107
+ 'header--fixed': !mobileMenuActive,
1108
+ 'header--hidden': this.headerHidden && !mobileMenuActive,
857
1109
  'header--menu-open': mobileMenuActive,
858
- } }, index.h("div", { key: '426395d6e1245188bc103c8a2f72ccfc3819ba7d', class: "header-inner" }, index.h("button", { key: 'fe6128407500f5b1a1899aa9e7fdd00222f177b3', type: "button", class: "menu-toggle icon-button", "aria-label": mobileMenuActive ? 'Close menu' : 'Open menu', "aria-expanded": mobileMenuActive ? 'true' : 'false', "aria-controls": "weg-header-main-nav", onClick: () => this.toggleMenu() }, mobileMenuActive ? index.h(CloseIcon, null) : index.h(HamburgerIcon, null)), index.h(Logo, { key: 'bb19f9430217686834c4aec615bd7306d276a969', href: logoHref, src: logoSrc }), index.h("div", { key: 'cebab248840b8412479a90a83c5fc3d0a601476b', class: "header-actions" }, this.renderCompactAuth(mobileMenuActive ? closeMenu : undefined)), index.h("div", { key: 'c029db0bcd71a9940d93bef5b32e59625f94b76c', class: "main-nav-panel", id: "weg-header-main-nav", role: mobileMenuActive ? 'dialog' : undefined, "aria-modal": mobileMenuActive ? 'true' : undefined, "aria-label": mobileMenuActive ? 'Menu' : undefined }, this.renderNav(mobileMenuActive ? closeMenu : undefined)))));
1110
+ } }, index.h("div", { key: '2c088a3e602ac2c8751d21376872536e35a0ab7d', class: "header-inner" }, index.h("div", { key: '91089bfc45b2b3274df00b032cad0adaba79b937', class: "sr-only", "aria-live": "polite", "aria-atomic": "true", "data-weg-sr-live": true }), index.h("button", { key: 'a66e0f0564014f5041a9fa80b39f74ce177f7125', type: "button", class: "menu-toggle icon-button", "aria-label": mobileMenuActive ? CLOSE_MAIN_NAV_LABEL : OPEN_MAIN_NAV_LABEL, "aria-expanded": mobileMenuActive ? 'true' : 'false', "aria-controls": "weg-header-main-nav", onClick: () => this.toggleMenu() }, mobileMenuActive ? index.h(CloseIcon, null) : index.h(HamburgerIcon, null)), index.h(Logo, { key: '917d134565c899e9a25557bafd62bf8b0de75e32', href: logoHref, src: logoSrc }), index.h("div", { key: '7b6bcd11271e00ddf0ca7d34bc1c8d2ad8342ed4', class: "header-actions" }, this.renderCompactAuth(mobileMenuActive ? closeMenu : undefined)), index.h("div", { key: '1a6779e99be4704b6f9093501dd230a891b81c17', class: "main-nav-panel", id: "weg-header-main-nav", role: mobileMenuActive ? 'dialog' : undefined, "aria-modal": mobileMenuActive ? 'true' : undefined, "aria-label": mobileMenuActive ? MAIN_NAV_LABEL : undefined }, this.renderNav(mobileMenuActive ? closeMenu : undefined)))));
859
1111
  }
860
1112
  static get watchers() { return {
861
1113
  "layout": [{
@@ -19,7 +19,7 @@ var patchBrowser = () => {
19
19
 
20
20
  patchBrowser().then(async (options) => {
21
21
  await appGlobals.globalScripts();
22
- return index.bootstrapLazy([["weg-footer_2.cjs",[[513,"weg-footer",{"layout":[1],"resolved":[32]},null,{"layout":[{"watchLayout":0}]}],[513,"weg-header",{"layout":[1],"signedIn":[516,"signed-in"],"userName":[1,"user-name"],"accountBaseUrl":[1,"account-base-url"],"currentPath":[1,"current-path"],"resolved":[32],"menuOpen":[32],"openDropdown":[32]},[[8,"keydown","handleKeyDown"]],{"layout":[{"watchLayout":0}]}]]]], options);
22
+ return index.bootstrapLazy([["weg-footer_2.cjs",[[513,"weg-footer",{"layout":[1],"resolved":[32]},null,{"layout":[{"watchLayout":0}]}],[513,"weg-header",{"layout":[1],"signedIn":[516,"signed-in"],"userName":[1,"user-name"],"accountBaseUrl":[1,"account-base-url"],"currentPath":[1,"current-path"],"resolved":[32],"menuOpen":[32],"openDropdown":[32],"headerHidden":[32]},[[8,"keydown","handleKeyDown"]],{"layout":[{"watchLayout":0}]}]]]], options);
23
23
  });
24
24
 
25
25
  exports.setNonce = index.setNonce;
@@ -33,6 +33,28 @@
33
33
  :host {
34
34
  position: relative;
35
35
  z-index: 20;
36
+ display: block;
37
+ height: var(--weg-header-height, auto);
38
+ }
39
+
40
+ .header--fixed {
41
+ position: fixed;
42
+ top: 0;
43
+ left: 0;
44
+ right: 0;
45
+ z-index: 20;
46
+ transform: translateY(0);
47
+ transition: transform 0.25s ease;
48
+ }
49
+
50
+ .header--fixed.header--hidden {
51
+ transform: translateY(-100%);
52
+ }
53
+
54
+ @media (prefers-reduced-motion: reduce) {
55
+ .header--fixed {
56
+ transition: none;
57
+ }
36
58
  }
37
59
 
38
60
  .header--menu-open {
@@ -340,6 +362,9 @@
340
362
  display: flex;
341
363
  flex-direction: column;
342
364
  gap: 0.25rem;
365
+ list-style: none;
366
+ margin: 0;
367
+ padding: 0;
343
368
  }
344
369
 
345
370
  .nav-dropdown__link {