Skip to content
Snippets Groups Projects
site-header.tsx 4.03 KiB
Newer Older
  • Learn to ignore specific revisions
  • export interface DonateLink {
      url: string;
      label: string;
    }
    
    import {Component, Element, Prop, State, h, Listen} from '@stencil/core';
    import ResizeObserver from 'resize-observer-polyfill';
    
    @Component({
      tag: 'hy-site-header',
      styleUrl: 'site-header.scss',
      shadow: true
    })
    export class SiteHeader {
      @Element() el: HTMLElement;
      @State() isMobile: boolean;
      @State() isMenuOpen: boolean = false;
      @Prop() dataMenuLanguage: string;
      @Prop() dataMenuDonate: string;
      @Prop() logoUrl?: string;
      @Prop() logoLabel?: string;
      @Prop() searchButtonLabel?: string;
      @Prop() menuButtonLabel?: string;
      @Prop({reflect: true}) menuType: string;
      private ro: ResizeObserver;
      private donateLink: DonateLink[];
    
      @Listen('mobileMenuToggle') mobileMenuToggle() {
        this.isMenuOpen = !this.isMenuOpen;
      }
    
      componentDidLoad() {
        this.ro = new ResizeObserver((entries) => {
          for (const entry of entries) {
            this.applySizeClasses(entry.contentRect.width);
          }
        });
        this.ro.observe(this.el);
        this.el.children[0].setAttribute('data-menu-language', this.dataMenuLanguage);
      }
    
      componentWillLoad() {
        this.donateLink = JSON.parse(this.dataMenuDonate);
      }
    
      componentWillUpdate() {
        this.el.children[0].setAttribute('open', this.isMenuOpen.toString());
        this.el.children[0].setAttribute('logo-label', this.logoLabel);
        this.el.children[0].setAttribute('logo-url', this.logoUrl);
      }
    
      componentDidUnload() {
        this.ro.disconnect();
      }
    
      applySizeClasses(size: number) {
        if (size < 768) {
          this.el.children[0].setAttribute('menu-type', 'mobile');
          this.menuType = 'mobile';
          this.isMobile = true;
        } else {
          this.el.children[0].setAttribute('menu-type', 'desktop');
          this.menuType = 'desktop';
          this.isMobile = false;
        }
      }
    
      render() {
        const black = 'var(--brand-main-nearly-black)';
        const white = 'var(--grayscale-white)';
        let classAttributes = ['hy-site-header', 'hy-site-header--' + this.menuType];
        return this.isMobile ? (
          // Mobile
          <header class={classAttributes.join(' ')}>
            <div class={{'hy-backdrop': true, 'is-active': this.isMenuOpen}} />
            <hy-site-logo menu-type={this.menuType} url={this.logoUrl} label={this.logoLabel} />
            <div class={'hy-site-header__menu-container'}>
              <hy-site-search menu-is-open={this.isMenuOpen} menu-type={this.menuType} label={this.searchButtonLabel} />
              <button
                onClick={() => this.mobileMenuToggle()}
                class={{
                  'hy-site-header__panel-toggle': true,
                  'is-open': this.isMenuOpen
                }}
              >
                {this.isMenuOpen ? (
                  <hy-icon icon={'hy-icon-remove'} size={20} fill={black} />
                ) : (
                  <hy-icon icon={'hy-icon-hamburger'} size={20} fill={white} />
                )}
              </button>
              <div
                class={{
                  'is-open': this.isMenuOpen,
                  'hy-site-header__panel': true
                }}
              >
                <slot name={'menu'} />
              </div>
            </div>
          </header>
        ) : (
          // Desktop
          <header class={classAttributes.join(' ')}>
            <hy-site-logo menu-type={this.menuType} url={this.logoUrl} label={this.logoLabel} />
            <slot name={'menu'} />
            <div class={'menu--secondary'}>
              <hy-menu-language
                class={'menu--secondary__item is-first'}
                is-mobile={false}
                data-menu-language={this.dataMenuLanguage}
              />
              <hy-site-search
                class={'menu--secondary__item'}
                menu-is-open={this.isMenuOpen}
                menu-type={this.menuType}
                label={this.searchButtonLabel}
              />
              {this.donateLink.map((i) => {
                return (
                  <a class={'menu--secondary__item hy-link__donate'} href={i.url}>
                    <hy-icon icon={'hy-icon-euro'} size={14} fill={black} />
                    <span class={'hy-link__donate__label'}>{i.label}</span>
                  </a>
                );
              })}
            </div>
          </header>
        );
      }
    }