Skip to content
Snippets Groups Projects
link-box.tsx 4.69 KiB
Newer Older
druid's avatar
druid committed
import {Component, ComponentInterface, Element, Prop, h, Listen} from '@stencil/core';
import {LinkBoxVariants} from '../../utils/utils';
druid's avatar
druid committed
let keys = {
  enter: 'Enter',
};

@Component({
  tag: 'hy-link-box',
  styleUrl: 'link-box.scss',
})
export class LinkBox implements ComponentInterface {
  @Prop() variant: LinkBoxVariants = LinkBoxVariants.default;
  @Prop() imageUrl: string = null;
  @Prop() imageAlt: string = null;
  @Prop() textTitle?: string;
  @Prop() textDescription: string = null;
  @Prop() url?: string;
  @Prop() isExternal: boolean = false;
  @Prop() scLabel?: string;
  @Prop() headerstyle: string = 'common';
  @Element() el: HTMLElement;

  componentDidLoad() {
    let hyMainDiv = this.el.closest('.hy-main');
    if (hyMainDiv) {
      if (!hyMainDiv.classList.contains('with-sidebar')) {
        this.headerstyle = 'large';
      }
    }
  }
druid's avatar
druid committed
  @Listen('click')
  handleClick(event) {
    this.openLink(event.currentTarget);
  }

  @Listen('keydown')
  handleKeyDown(event) {
    const key = (event as KeyboardEvent).code;
    if (key == keys.enter) {
      this.openLink(event.currentTarget);
    }
  }

  openLink(linkbox) {
    let card = linkbox.shadowRoot.querySelector('.hy-link-box-container');
    window.open(card.dataset.location, card.dataset.target);
  }

druid's avatar
druid committed
  @Listen('mouseenter')
  handleMouseEnter(event) {
    this.manageHoverEffect(event.currentTarget);
  }

  @Listen('mouseleave')
  handleMouseLeave(event) {
    this.manageHoverEffect(event.currentTarget, false);
  }

  @Listen('focusin')
  handleOnFocusIn(event) {
    this.manageHoverEffect(event.currentTarget);
  }

  @Listen('focusout')
  handleOnFocusOut(event) {
    this.manageHoverEffect(event.currentTarget, false);
  }

  manageHoverEffect(linkbox, hoverOn = true) {
    let title = linkbox.shadowRoot.querySelector('h3.hy-link-box__text-container__title');
    let boxLink = linkbox.shadowRoot.querySelector('.hy-icon-wrapper');
druid's avatar
druid committed
    if (hoverOn) {
      (title as HTMLElement).classList.add('hy-link-box__text-container__title__hover');
      (boxLink as HTMLElement).classList.add('hy-icon-wrapper__hover');
druid's avatar
druid committed
    } else {
      (title as HTMLElement).classList.remove('hy-link-box__text-container__title__hover');
      (boxLink as HTMLElement).classList.remove('hy-icon-wrapper__hover');
druid's avatar
druid committed
    }
  }

druid's avatar
druid committed
    const classContainerAttributes = ['hy-link-box-container'].join(' ');

    const classAttributes = [
      'hy-link-box',
      this.variant,
druid's avatar
druid committed
      `hy-link-box__${this.variant}`,
druid's avatar
druid committed
      `hy-link-box__${this.headerstyle}`,
      this.imageUrl ? 'hy-link-box--with-image' : null,
    ].join(' ');

druid's avatar
druid committed
    const classLinkAttributes = [
      'hy-link-box-link',
      `hy-link-box-link__${this.variant}`,
      `hy-link-box-link__${this.headerstyle}`,
      this.headerstyle,
      this.isExternal ? 'hy-link-box-link__external' : null,
druid's avatar
druid committed
    ].join(' ');
    const classTextContainer = ['hy-link-box__text-container', this.imageUrl ? 'hy-link-box--with-image' : null].join(
      ' '
    );
druid's avatar
druid committed
    const classTitle = [
      'hy-link-box__text-container__title',
      `hy-link-box__text-container__title__${this.variant}`,
      `hy-link-box__text-container__title__${this.headerstyle}`,
      this.imageUrl ? 'hy-link-box__text-container__title__image' : '',
      this.imageUrl ? 'image' : '',
    ].join(' ');

    const classDescription = [
      'hy-link-box__text-container__description',
      `hy-link-box__text-container__description__${this.variant}`,
      `hy-link-box__text-container__description__${this.headerstyle}`,
    ].join(' ');

    const aspectRatioWidth = 16;
    const aspectRatioHeight = 10;
    const aspect = (aspectRatioHeight / aspectRatioWidth) * 100;
    const aspectRatio = {
      '--aspectRatio': `${aspect}%` as 'aspectRatio',
Ekaterina Kondareva's avatar
Ekaterina Kondareva committed
    return [
druid's avatar
druid committed
      <article class={classContainerAttributes} tabindex="0" data-target={target} data-location={this.url}>
        <div class={classAttributes} aria-label={this.scLabel}>
          {this.imageUrl && (
            <div class="hy-link-box__image-container" style={aspectRatio}>
              <img aria-hidden="true" src={this.imageUrl} alt={this.imageAlt} />
            </div>
          )}
druid's avatar
druid committed
            <h3 class={classTitle}>{this.textTitle}</h3>
            {this.textDescription && <div class={classDescription}>{this.textDescription}</div>}
          </div>
druid's avatar
druid committed
        </div>
        <span class={'hy-icon-wrapper'}>
          <a class={classLinkAttributes} href={this.url} target={target} aria-label={this.scLabel} tabindex="-1">
            <hy-icon icon={'hy-icon-arrow-to-right'} size={32} />
          </a>
        </span>
Ekaterina Kondareva's avatar
Ekaterina Kondareva committed
      </article>,
    ];