<div class="squad-navbar" data-behaviour="squad-navbar" aria-label="Current player squad">
    <div class="squad-navbar__wrapper">
        <nav class="squad-navbar__nav-list" data-behavior="squad-navbar--nav-list" aria-label="Current player squad">
            <a href="#" data-nav-to="squad-block-goalkeepers" class="squad-block-goalkeepers">
                Goalkeepers
            </a>
            <a href="#" data-nav-to="squad-block-defenders" class="squad-block-defenders">
                Defenders
            </a>
            <a href="#" data-nav-to="squad-block-midfielders" class="squad-block-midfielders">
                Midfielders
            </a>
            <a href="#" data-nav-to="squad-block-forwards" class="squad-block-forwards">
                Forwards
            </a>
            <a href="#" data-nav-to="squad-block-staff" class="squad-block-staff">
                Staff
            </a>
        </nav>
    </div>
</div>

Squad navbar

  • Same page navigation navbar
  • [EF-512]

Fixed navbar on scroll:

  1. Navbar gets fixed (along side of header) once scroll pasts navbar element.
  2. Use the same logic of navigation initFixedHeader to be in sync otherwise there would be race condition in positioning elements at the top.
  3. TBD - Animate navlinks when scrolled to particular part of the screen.
  4. Scroll performance issues to addressed.
    • off/on scroll when scrollIntoView happens
    • less scroll event fire and more focus on logic.
    • can we combine certain conditions while scroll?
    • how to avoid scroll event not getting bounded in smaller device?
{
  "data": [
    {
      "title": "Goalkeepers",
      "id": "squad-block-goalkeepers",
      "additionalClasses": ""
    },
    {
      "title": "Defenders",
      "id": "squad-block-defenders",
      "additionalClasses": ""
    },
    {
      "title": "Midfielders",
      "id": "squad-block-midfielders",
      "additionalClasses": ""
    },
    {
      "title": "Forwards",
      "id": "squad-block-forwards",
      "additionalClasses": ""
    },
    {
      "title": "Staff",
      "id": "squad-block-staff",
      "additionalClasses": ""
    }
  ]
}
  • Content:
    export default parentElement => {
      const sections = document.querySelectorAll('.player-profile-list');
      const navLinks = parentElement.querySelectorAll('a');
      const stickyEl = parentElement.querySelector('.squad-navbar__wrapper');
      const stickyPosition = stickyEl.getBoundingClientRect().top;
      const offset = -10;
      const MOBILE_BREAKPOINT = 500;
    
      if (window.innerWidth > MOBILE_BREAKPOINT) {
        window.addEventListener('scroll', () => {
          let current = '';
    
          sections.forEach(section => {
            const sectionTop = section.offsetTop;
            const sectionHeight = section.clientHeight;
            const currentScrollPos = window.pageYOffset;
    
            if (currentScrollPos >= sectionTop + 600 - sectionHeight / 3) {
              current = section.getAttribute('id');
            }
          });
    
          navLinks.forEach(link => {
            link.classList.remove('active');
            if (link.classList.contains(current)) {
              link.classList.add('active');
            }
            link.addEventListener('click', event => {
              event.preventDefault();
              const targetId = event.target.getAttribute('data-nav-to');
              const tagetElm = document.querySelector(`#${targetId}`).offsetTop;
              let initial = 0;
    
              if (parentElement.querySelector('a.active')) {
                const currentElm = parentElement
                  .querySelector('a.active')
                  .getAttribute('data-nav-to');
    
                initial = document.querySelector(`#${currentElm}`).offsetTop;
              }
              if (initial < tagetElm) {
                window.scrollTo(0, tagetElm + 600);
              } else {
                const sctollTo =
                  tagetElm -
                  document.querySelector('.global-fixed-header').clientHeight;
    
                window.scrollTo(0, sctollTo + 600);
              }
            });
          });
    
          if (window.pageYOffset >= stickyPosition + offset) {
            const headerMargin = document.querySelector('.global-fixed-header')
              .style.top;
    
            if (headerMargin.replace('px', '') === '0') {
              stickyEl.style.top = `
                ${document.querySelector('.global-fixed-header').clientHeight}px`;
            } else {
              stickyEl.style.top = '';
            }
            parentElement.classList.add('nav-sticky');
          } else {
            parentElement.classList.remove('nav-sticky');
          }
        });
      }
    };
    
  • URL: /components/raw/squad-navbar/squad-navbar.js
  • Filesystem Path: src/library/components/squad-navbar/squad-navbar.js
  • Size: 2.3 KB
  • Content:
    .squad-navbar {
      display: flex;
      justify-content: center;
      width: 100%;
      background-color: $white;
      transition: all 0.4s ease-out 0s;
      left: 0;
      z-index: 9;
      min-height: 4.2rem;
    
      &__nav-list {
        display: none;
      }
    
      @media screen and (min-width: $mq-small) {
        &__nav-list {
          display: flex;
          width: 100%;
    
          a {
            @include text-s;
    
            font-size: 1.8rem;
            font-weight: 400;
            line-height: 4.4rem;
            text-decoration: none;
            text-transform: uppercase;
            color: $color-interface-light;
            border-bottom: 2px solid $light-blue;
            width: 100%;
            text-align: center;
    
            &:not(:last-child) {
              padding-right: 1rem;
            }
    
            &:hover {
              color: var(--brand-primary);
              border-bottom: 2px solid var(--brand-primary);
            }
    
            &.active {
              color: var(--brand-primary);
              border-color: var(--brand-primary);
            }
          }
        }
        &__wrapper {
          width: 100%;
          transition: position 0.4s ease-in-out 0s, top 0.4s ease-in-out 0s;
        }
        &.nav-sticky {
          .squad-navbar__wrapper {
            position: fixed;
            background: $white;
            z-index: 10;
            top: 0;
          }
        }
      }
    }
    
    @media screen and (min-width: $mq-medium) {
      .squad-navbar {
        padding: 0 6rem;
      }
    }
    
  • URL: /components/raw/squad-navbar/squad-navbar.scss
  • Filesystem Path: src/library/components/squad-navbar/squad-navbar.scss
  • Size: 1.3 KB
<div class="squad-navbar" data-behaviour="squad-navbar" aria-label="Current player squad">
  <div class="squad-navbar__wrapper">
    <nav class="squad-navbar__nav-list" data-behavior="squad-navbar--nav-list" aria-label="Current player squad">
      {{#each data}}
        <a href="#" data-nav-to="{{id}}" class="{{id}}">
          {{title}}
        </a>
      {{/each}}
    </nav>
  </div>
</div>