Skip to content
Snippets Groups Projects
site-search.tsx 5.05 KiB
Newer Older
druid's avatar
druid committed
export interface SearchSpecialTools {
  url: string;
  label: string;
}

import {Component, Prop, h, Watch, State, Listen, Host, Event, EventEmitter, Element} from '@stencil/core';
import {ComponentLabels} from '../site-header';
import {ColorVariant} from '../../../utils/utils';

@Component({
  tag: 'hy-site-search',
  styleUrl: 'site-search.scss',
})
export class SiteSearch {
druid's avatar
druid committed
  @Element() el: HTMLElement;

  @Prop() color: ColorVariant = ColorVariant.black;
  @Prop() isAlternative: boolean = false;
Markus Kalijärvi's avatar
Markus Kalijärvi committed
  @Prop() labels?: ComponentLabels[] | string;
  @Prop() showLabel: boolean = false;
druid's avatar
druid committed
  @Prop() dataSearchSpecialTools: string;
  private _dataSearchSpecialTools: SearchSpecialTools[];

  @State() isSearchPanelOpen: boolean = false;
  @Event() searchPanelToggled: EventEmitter;

Markus Kalijärvi's avatar
Markus Kalijärvi committed
  private _labels: ComponentLabels[];

  @Watch('labels') labelsWatcher(data: ComponentLabels[] | string) {
    this._labels = typeof data === 'string' ? JSON.parse(data) : data;
  }

druid's avatar
druid committed
  componentWillLoad() {
    if (this.dataSearchSpecialTools) {
      this._dataSearchSpecialTools = JSON.parse(this.dataSearchSpecialTools);
    }
  }

Markus Kalijärvi's avatar
Markus Kalijärvi committed
  componentWillRender() {
    this.labelsWatcher(this.labels);
  }
druid's avatar
druid committed
  // CLose the search panel if user opens the desktop menu panel.
  @Listen('menuDesktopToggled', {target: 'document'})
  desktopMenuToggled() {
    this.isSearchPanelOpen = false;
  }

  // CLose the search panel if user opens the language menu.
  @Listen('menuLanguageToggled', {target: 'document'})
  menuLanguageToggled() {
    this.isSearchPanelOpen = false;
  }

  // Close the search panel if user clicks anywhere outside the Search component.
  @Listen('click', {target: 'window'})
  handleWindowClick(event) {
    if (event.target.tagName.toLowerCase() !== 'hy-site-search') {
      this.isSearchPanelOpen = false;
    }
    event.stopPropagation();
  }

  handleSearchPanelToggle() {
    this.isSearchPanelOpen = !this.isSearchPanelOpen;

    if (this.isSearchPanelOpen) {
      //const searchPanelSelector = this.el as HTMLElement;

      // Close desktop menu panel and lang menu panel if they are open.
      this.searchPanelToggled.emit();

      let hyHeader = this.el.closest('.hy-site-header') as HTMLElement;
      let rectHeader = hyHeader.getBoundingClientRect();

      const headerHeight = `${rectHeader.bottom}px`;
      const searchPanel = this.el.shadowRoot.querySelectorAll(`.site-search__panel`)[0] as HTMLElement;
      searchPanel.style.top = headerHeight;
    }
    //event.stopPropagation();
  }

  handleSearchPanelClose() {
    this.isSearchPanelOpen = false;
  }

  render() {
    return (
druid's avatar
druid committed
      <Host
druid's avatar
druid committed
          'site-search': true,
          'site-search__is-open': this.isSearchPanelOpen,
druid's avatar
druid committed
        <button
          aria-label={this._labels['open']}
          class={{
            'button--search': true,
            'is-open--menu': this.isAlternative,
            'is-open': this.isSearchPanelOpen,
          }}
          onClick={() => this.handleSearchPanelToggle()}
        >
          {this.showLabel ? <span class={'button--search__label'}>{this._labels['label']}</span> : ''}
          <hy-icon icon={'hy-icon-search'} size={this.size} fill={this.color} />
        </button>
        <div
          class={{
            'site-search__panel': true,
            'site-search__panel__is-open': this.isSearchPanelOpen,
          }}
        >
          <div class="site-search__panel__title">
            <div class="site-search__panel__title__label">
              <h1>Search</h1>
              <div>web pages, study options, people, research groups, etc…</div>
            </div>
            <button
              onClick={() => this.handleSearchPanelClose()}
              class={{
                'site-search__panel__panel-toggle': true,
              }}
              aria-label="Exit Search"
            >
              <span class="site-search__panel__panel-toggle__label">
                <span class="site-search__panel__panel-toggle__label__title">Exit Search</span>
                <hy-icon icon={'hy-icon-remove'} size={20} fill={ColorVariant.black} />
              </span>
            </button>
          </div>
          <div class="site-search__panel__input">
            <hy-search-field input-id="search" label="Search degree programmes" />
          </div>
          <div class="site-search__panel__results">
            <div class="filters"></div>
            <div class="results"></div>
          </div>
          {this.dataSearchSpecialTools && this._dataSearchSpecialTools.length > 0 && (
            <div class="site-search__panel__tools">
              <div>Special Search tools</div>
              {this._dataSearchSpecialTools.map((i) => {
                return (
                  <a class={'search-special-tool'} href={i.url}>
                    <hy-icon icon={'hy-icon-arrow-to-right'} size={14} fill={ColorVariant.black} />
                    <span class={'search-special-tool__label'}>{i.label}</span>
                  </a>
                );
              })}
            </div>
          )}
        </div>
      </Host>