<section class="bux-hero bux-hero--scarlet bux-hero--card-right bux-hero--3x2">

    <div id="bux-hero__carousel-169990552-items" class="bux-hero__carousel-items">
        <div id="bux-hero__carousel-169990552-tab-1" class="bux-hero__container  showing">

            <div class="bux-hero__content">

                <h2 class="bux-hero__header">
                    <span>Headline lorem ipsum</span>
                </h2>

                <div class="bux-hero__subheader">
                    <span>Subhead lorem ipsum dolara met</span>
                </div>
                <a class="bux-button bux-button--alt" href="#">Call to Action</a>

            </div>
            <div class="bux-hero__image-container">

                <div class="bux-hero__image bux-hero__image--3x2 ">

                    <img class="bux-image " src="/images/placeholders/osu-bux-5.jpg" alt="Graduates performing the O-H-I-O pose" />

                </div>
            </div>

        </div>
    </div>

</section>
{#

Hero

Available variables:

- background:           Sets the Hero background color. 
                        Allowed values: null, gray, scarlet
- card_orientation:     Sets whether the card is on the left, right or bottom.
                        Allowerd values: card-left, card-right, card-full
- ratio:                Sets the hero's image ratio.
                        Allowed values: null, 16x9, 3x2
- hero_heading_level:   Integer. Sets the heading level of the header.
- cards:                Array containing the cards for the hero carousel.
- card.hero_header:     String for the header section of the hero.
- card.hero_subheader:  String for the header subheader content.
- card.hero_image:      URL for the hero image.
- card.hero_image_alt:  String for the alt text of the hero image.
- card.button_text:     String for the hero button text.
- card.button_url:      URL for the hero button.

If using a video, the hero will default to the 'card-full' orientation.

- card.hero_video_mp4:  URL for the hero video.
- card.hero_aria_label: String for the video's aria-label.

If using more than one card in a carousel:

- carousel_aria_label:  String for the carousel aria-label.
- carousel_id:          Unique ID for the carousel.

#}

{% set random_seed = random() %}
{% set carousel_uniqueid = carousel_id ~ "-" ~ random_seed %}

<section class="bux-hero {% if background %}bux-hero--{{background}}{% endif %} bux-hero--{{card_orientation}}{% if cards|length > 1 %} bux-hero--carousel{% endif %}{% if ratio %} bux-hero--{{ratio}}{% endif %}"{% if (cards|length > 1) %} aria-roledescription="carousel" aria-label="{{carousel_aria_label}}"{% endif %}>

    {% if (cards|length > 1) %}

        <button class="bux-hero__button bux-hero__button--left" type="button" aria-controls="{{carousel_uniqueid}}-items" aria-label="Previous Slide"><span class="icon icon-chevron-left" aria-hidden="true"></span></button>
        <button class="bux-hero__button bux-hero__button--right" type="button" aria-controls="{{carousel_uniqueid}}-items" aria-label="Next Slide"><span class="icon icon-chevron-right" aria-hidden="true"></span></button>

    {% endif %}

    {% if (cards|length > 1) %}
        <div class="bux-hero__tabs" role="tablist" aria-label="Slides">
            {% for card in cards %}
                <button id="{{carousel_uniqueid}}-tabbutton-{{ loop.index }}" class="bux-hero__tab {% if loop.index == 1 %}bux-hero__tab--active{% endif %}" type="button" role="tab" aria-label="Slide {{ loop.index }}" aria-controls="{{carousel_uniqueid}}-tab-{{ loop.index }}" tabindex="-1">
                    <span class="visually-hidden">Slide {{ loop.index }}</span>
                </button>
            {% endfor %}
        </div>
    {% endif %}
    <div id="{{carousel_uniqueid}}-items" class="bux-hero__carousel-items">
        {% for card in cards %}
        <div id="{{ carousel_uniqueid }}-tab-{{ loop.index }}" class="bux-hero__container {% if loop.index == 1 %} showing{% endif %}"{% if (cards|length > 1) %} role="tabpanel" aria-roledescription="slide" aria-label="{{ loop.index }} of {{ cards.length }}"{% endif %}>

            <div class="bux-hero__content">

                <h{{ hero_heading_level|default(2) }} class="bux-hero__header">
                    <span>{{ card.hero_header }}</span>
                </h{{ hero_heading_level|default(2) }}>

                {% if card_orientation != 'card-full' %}
                    <div class="bux-hero__subheader">
                        <span>{{ card.hero_subheader }}</span>
                    </div>
                    <a class="bux-button bux-button--alt" href="{{ card.button_url }}">{{ card.button_text }}</a>
                {% else %}
                    <a class="bux-hero__subheader bux-text-link" href="{{ card.button_url }}">{{ card.hero_subheader }}</a>
                {% endif %}

            </div>
            <div class="bux-hero__image-container">

                {% if card.hero_image %}

                <div class="bux-hero__image bux-hero__image--{{ratio}} ">

                    {% set image_url = card.hero_image %}
                    {% set image_alt_text = card.hero_image_alt %}

                    {% include '@image' %}

                    {% elseif card.hero_video_mp4 %}
                    <div class="bux-hero__image">
                        <video aria-label="{{card.hero_aria_label}}" tabindex="-1" loop="" autoplay="" playsinline="" muted="">
                            <source src="{{card.hero_video_mp4}}" type="video/mp4">
                        </video>
                        <button type="button" class="bux-hero__video-button">
                            <span class="visually-hidden">Pause video</span>
                            <div class="bux-hero__video-button-icon bux-hero__video-button-icon--play" aria-hidden="true">
                                <span class="bux-icon icon-play-fill" aria-hidden="true"></span>
                            </div>
                            <div class="bux-hero__video-button-icon bux-hero__video-button-icon--pause" aria-hidden="true">
                                <span class="bux-icon icon-pause-fill" aria-hidden="true"></span>
                            </div>
                        </button>
                        {% endif %}
                    </div>
                </div>

            </div>
            {% endfor %}
        </div>

</section>
site_name_prefix: Office of
site_name: Learning Relations Excellence
site_slogan: Additional text or site slogan
address_1: 100 Building Name
address_2: 1 Oval Mall
city: Columbus
state: OH
zip: '43210'
contact_email: email@osu.edu
contact_phone: 614-292-OHIO
contact_tty: 614-688-8605
carousel_aria_label: Highlighted stories
carousel_id: bux-hero__carousel
hero_header: Headline lorem ipsum
hero_subheader: Subhead lorem ipsum dolara met
hero_image: /images/placeholders/osu-bux-5.jpg
hero_image_alt: Graduates performing the O-H-I-O pose
card_orientation: card-right
ratio: 3x2
cards:
  - hero_header: Headline lorem ipsum
    hero_subheader: Subhead lorem ipsum dolara met
    hero_image: /images/placeholders/osu-bux-5.jpg
    hero_image_alt: Graduates performing the O-H-I-O pose
    card_orientation: card-left
    button_text: Call to Action
    button_url: '#'
background: scarlet
  • Content:
    @mixin hero (
      $bg-color: $gray-light-90,
      $title-color: $gray-dark-80,
      $text-color: $gray-dark-40,
    ) {
    
      .bux-hero__content {
        background-color: $bg-color;
        padding: $sp-24;
        @include breakpoint(lg) {
          padding: $sp-32 $sp-32 $sp-32 $sp-64;
        }
      }
    
      .bux-hero__header {
        display: block;
        font-family: $serif;
        font-size: 1.75rem;
        line-height: 2.25rem;
        font-weight: 900;
        color: $title-color;
        overflow: hidden;
        @include breakpoint(lg) {
          font-size: 2rem;
          line-height: 2.25rem;
        }
    
        span {
          display: block;
        }
      }
    
      .bux-hero__subheader {
        display: block;
        font-family: $sans;
        font-size: rem-calc(20);
        line-height: rem-calc(26);
        font-weight: 600;
        margin-bottom: $sp-24;
        color: $text-color;
        overflow: hidden;
        @include breakpoint(lg) {
          font-size: 1rem;
          line-height: 1.25rem;
        }
    
        span {
          display: block;
        }
      }
    }
    
    .bux-hero {
      @include hero();
      position: relative;
      display: flex;
    
      &__carousel-items {
        margin: 0;
        @include breakpoint(lg) {
          padding: 0 15px 0;
        }
        width: 100%;
      }
    
      &__content {
        width: 100%;
        order: 1;
      }
    
      &__container {
        display: flex;
        align-items: stretch;
        flex-direction: column;
        position: relative;
        transition: 1s;
        opacity: 0;
        z-index: 1;
        -webkit-transition: opacity 0.5s;
        -o-transition: opacity 0.5s;
        transition: opacity 0.5s;
        display: none;
      }
    
      &__image {
        order: 0;
        height: 0;
        position: relative;
        overflow: hidden;
    
        img {
          width: 100%;
          object-fit: cover;
          position: absolute;
          height: 100%;
          left: 0;
          top: 0;
          transform: none;
          width: 100%;
        }
        &--3x2 img {
          aspect-ratio: 3/2;
        }
    
        &--16x9 img {
          aspect-ratio: 16/9;
        }
      }
    
      &__button {
        width: rem-calc(44);
        height: rem-calc(44);
        position: absolute;
        background-color: $gray-light-80;
        border: solid 2px $gray-light-60;
        border-radius: 0;
        color: $gray-dark-60;
        font-size: $ts-28;
        cursor: pointer;
        z-index: 99;
    
        &:hover {
          background-color: $gray-dark-60;
          color: $white;
          border-color: $gray-dark-60;
        }
        &:focus {
          outline: 2px solid $focus;
          outline-offset: -2px;
        }
        .icon {
          display: block;
          padding-top: rem-calc(1);
        }
        &--left {
          left: 0;
        }
    
        &--right {
          right: 0;
        }
      }
    
      &__tabs {
        display: none;
    
        @include breakpoint(lg) {
          align-items: center;
          bottom: $sp-16;
          display: flex;
          justify-content: center;
          left: auto;
          position: absolute;
          right: auto;
          width: 100%;
          z-index: 99;
        }
      }
    
      &__tab {
        height: rem-calc(20);
        width: rem-calc(20);
        background: $white;
        border: 2px solid $gray-dark-40;
        border-radius: 100%;
        margin-left: 10px;
        cursor: pointer;
    
        &:first-child {
          margin-left: 0;
        }
    
        &:hover {
          background: $gray-dark-40;
          border: none;
        }
    
        &--active {
          background: $gray-dark-60;
          border: 2px solid $white;
          height: rem-calc(22);
          width: rem-calc(22);
        }
      }
    
    }
    
    .showing {
      opacity: 1;
      z-index: 2;
      display: flex;
    }
    
    @keyframes fadeInRight {
      0% {
        opacity: 0;
        left: 40px;
      }
      100% {
        opacity: 1;
        left: 0;
      }
    }
    @keyframes fadeInLeft {
      0% {
        opacity: 0;
        left: -40px;
      }
      100% {
        opacity: 1;
        left: 0;
      }
    }
    @keyframes slideUp {
      0% {
        opacity: 0;
        transform: translateY(25%);
      }
      100% {
        opacity: 1;
        transform: translateY(0%);
      }
    }
    
    .bux-hero-container {
      position: relative;
    }
    
    .bux-hero--scarlet {
      @include hero($scarlet, $white, $white)
    }
    
    .bux-hero--white {
      @include hero($white, $gray-dark-80, $gray-dark-40)
    }
    
    .bux-hero {
      @include breakpoint(lg) {
        flex-direction: row;
        align-items: stretch;
    
        &__container {
          flex-direction: row;
          overflow-y: hidden;
        }
    
        &__content {
          order: 0;
          flex-shrink: 2;
        }
    
        &__image {
          order: 1;
          padding-top: 100%;
    
          img {
            aspect-ratio: auto;
            height: 100%;
            width: 100%;
          }
        }
      }
      &--card-right {
        .bux-hero__content {
          display: flex;
          flex-direction: column;
          align-items: baseline;
          justify-content: center;
        }
        &.bux-hero--3x2 {
          .bux-hero__content {
            @include breakpoint(lg) {
              padding: $sp-32 $sp-64 $sp-32 $sp-32;
            }
          }
        }
        &.bux-hero--16x9 {
          .bux-hero__content {
            @include breakpoint(lg) {
              padding: $sp-16 $sp-64 $sp-16 $sp-16;
            }
          }
        }
      }
      &--card-left {
        .bux-hero__content {
          display: flex;
          flex-direction: column;
          align-items: baseline;
          justify-content: center;
        }
        &.bux-hero--3x2 {
          .bux-hero__content {
            @include breakpoint(lg) {
              padding: $sp-32 $sp-32 $sp-32 $sp-64;
            }
          }
        }
        &.bux-hero--16x9 {
          .bux-hero__content {
            @include breakpoint(lg) {
              padding: $sp-16 $sp-16 $sp-16 $sp-64;
            }
          }
        }
      }
      &--card-full {
        .bux-hero__content {
          max-width: 800px;
          padding: $sp-32;
          text-align: center;
        }
        .bux-text-link {
          cursor: pointer;
          display: inline;
    
          &::after {
            display: inline;
            font-size: rem-calc(20);
            font-weight: 400;
            position: absolute;
            top: auto;
          }
        }
        .bux-hero__header {
          font-size: rem-calc(28);
          line-height: rem-calc(34);
          @include breakpoint(lg) {
            font-size: 2rem;
            line-height: 2.25rem;
          }
        }
        .bux-hero__subheader {
          margin-bottom: 0;
        }
      }
      &--3x2 {
        .bux-hero__image {
          padding-top: 66.66%;
        }
        @include breakpoint(lg) {
          .bux-hero__content {
            width: 40%;
          }
          .bux-hero__image-container {
            width: 60%;
          }
        }
      }
    
      &--16x9 {
        .bux-hero__image {
          padding-top: 56.25%;
        }
        @include breakpoint(lg) {
          .bux-hero__content {
            width: 40%;
          }
          .bux-hero__image-container {
            width: 60%;
          }
        }
      }
    
      &--card-full {
        .bux-hero__container {
          align-items: center;
          flex-direction: column;
        }
        .bux-hero__content {
          z-index: 2;
          @include breakpoint(lg) {
            margin-top: -70px;
            order: 1;
            width: auto;
          }
        }
        .bux-hero__image-container {
          width: 100%;
        }
        .bux-hero__image {
          padding-top: 56.25%;
          position: relative;
          width: 100%;
          z-index: 1;
          @include breakpoint(lg) {
            order: 0;
          }
        }
        img {
          aspect-ratio:  16/9;
          left: 0;
          position: absolute;
          top: 0;
        }
        video {
          height: 100%;
          left: 0;
          position: absolute;
          top: 0;
          width: 100%;
        }
        .bux-hero__video-button {
          background: none;
          border: none;
          border-radius: 0;
          cursor: pointer;
          height: 100%;
          left: 0;
          position: absolute;
          top: 0;
          width: 100%;
          z-index: 3;
    
          &:focus {
            outline: 2px solid $focus;
            outline-offset: -2px;
          }
    
          &-icon {
            position: absolute;
            margin: 0 $sp-8 $sp-8 0;
            right: 0;
            bottom: 0;
            width: 50px;
            height: 50px;
            background: $white;
            color: $scarlet;
            border: $sp-4 solid $scarlet;
            border-radius: 50%;
            font-family: bux-icons !important;
            font-weight: 800;
            font-size: rem-calc(30);
            display: flex;
            align-items: center;
            justify-content: center;
    
            @include breakpoint(lg) {
              font-size: rem-calc(45);
              margin: 0 20px $sp-16 0;
              border: 5px solid $scarlet;
              height: 65px;
              width: 65px;
            }
            &--play, &--pause {
              visibility: hidden;
    
              .bux-icon {
                display: block;
                margin: 0;
              }
            }
    
            &--play {
              .bux-icon {
                transform: translateX(2px);
    
              @include breakpoint(lg) {
                transform: translateX(3px);
              }
              }
            }
          }
    
          &:hover,
          &:focus {
            .bux-hero__video-button-icon--play {
              visibility: hidden;
            }
            .bux-hero__video-button-icon--pause {
              line-height: rem-calc(35);
              visibility: visible;
              @include breakpoint(lg) {
                line-height: rem-calc(73);
              }
            }
          }
        }
        .bux-hero__video-play {
          &:hover,
          &:focus {
            .bux-hero__video-button-icon--play {
              visibility: visible;
            }
            .bux-hero__video-button-icon--pause {
              visibility: hidden;
            }
          }
        }
      }
    }
    @include breakpoint(lg) {
      .bux-hero--card-right {
    
        .bux-hero__image {
          order: 1;
        }
    
        .bux-hero__content {
          order: 2;
        }
      }
    }
    
  • URL: /components/raw/hero/_hero.scss
  • Filesystem Path: src/components/hero/_hero.scss
  • Size: 9 KB
  • Content:
    const heroes = Array.from(document.querySelectorAll(".bux-hero--carousel"));
    
    heroes.forEach((hero) => {
      let slides = Array.from(
        hero.querySelectorAll(".bux-hero--carousel .bux-hero__container")
      );
      let tabs = Array.from(
        hero.querySelectorAll(".bux-hero--carousel .bux-hero__tab")
      );
      let currentIndex = 0;
      const tablistNode = hero.querySelector('[role=tablist]');
      const nodes = hero.querySelectorAll('[role="tab"]');
      const liveRegionNode = hero.querySelector('.bux-hero__carousel-items');
    
      const showSlide = (index) => {
        slides[currentIndex].classList.remove("showing");
        tabs[currentIndex].classList.remove("bux-hero__tab--active");
        currentIndex = (index + slides.length) % slides.length;
        for (let i = 0; i < tabNodes.length; i++) {
          hideTabpanel(i);
        }
        tabs[currentIndex].removeAttribute('tabindex');
        slides[currentIndex].classList.add("showing");
        tabs[currentIndex].classList.add("bux-hero__tab--active");
        liveRegionNode.setAttribute("aria-live", "polite");
      }
    
      const showNextSlide = () => showSlide(currentIndex + 1);
      const showPrevSlide = () => showSlide(currentIndex - 1);
    
      const handleTabClick = (event) => {
        const clickedTab = event.target;
        if (clickedTab.classList.contains("bux-hero__tab")) {
          const clickedTabIndex = tabs.indexOf(clickedTab);
          showSlide(clickedTabIndex);
        }
      };
      
      const nextButton = hero.querySelector(".bux-hero__button--right");
      const prevButton = hero.querySelector(".bux-hero__button--left");
      const image = hero.querySelector(".bux-hero--carousel .showing .bux-hero__image");
      const tabContainer = hero.querySelector(
        ".bux-hero--carousel .bux-hero__tabs"
      );
      const buttons = Array.from(hero.querySelectorAll(".bux-hero__button"));
    
      nextButton.addEventListener("click", showNextSlide);
      prevButton.addEventListener("click", showPrevSlide);
      tabContainer.addEventListener("click", handleTabClick);
      
      buttons.forEach((button) => {
        const buttonHeight = button.getBoundingClientRect().height;
        button.style.top = `${
          (image.getBoundingClientRect().height - buttonHeight) / 2
        }px`;
      });
      
      // slide picker controls
      let tabNodes = [];
      let tabpanelNodes = [];
      
      const handleSlidepickerClick = (event) => {
        let index = tabNodes.indexOf(event.currentTarget);
        setSelectedTab(index, true);
      };
    
      const handleTabKeydown = (event) => {
        let flag = false;
      
        switch (event.key) {
          case 'ArrowRight':
            setSelectedToNextTab(true);
            flag = true;
            break;
      
          case 'ArrowLeft':
            setSelectedToPreviousTab(true);
            flag = true;
            break;
      
          case 'Home':
            setSelectedTab(0, true);
            flag = true;
            break;
      
          case 'End':
            setSelectedTab(tabNodes.length - 1, true);
            flag = true;
            break;
      
          default:
            break;
        }
      
        if (flag) {
          event.stopPropagation();
          event.preventDefault();
        }
      };
    
      const setSelectedToNextTab = (moveFocus) => {
        let nextIndex = currentIndex + 1;
      
        if (nextIndex >= tabNodes.length) {
          nextIndex = 0;
        }
      
        setSelectedTab(nextIndex, moveFocus);
      };
    
      const setSelectedToPreviousTab = (moveFocus) => {
        let nextIndex = currentIndex - 1;
      
        if (nextIndex < 0) {
          nextIndex = tabNodes.length - 1;
        }
      
        setSelectedTab(nextIndex, moveFocus);
      };
    
      const setSelectedTab = (index, moveFocus) => {
        if (index === currentIndex) {
          return;
        }
        currentIndex = index;
      
        for (let i = 0; i < tabNodes.length; i++) {
          hideTabpanel(i);
        }
      
        showTabpanel(index, moveFocus);
      };
    
      const showTabpanel = (index, moveFocus) => {
        let tabNode = tabNodes[index];
        let panelNode = tabpanelNodes[index];
      
        tabNode.setAttribute('aria-selected', 'true');
        tabNode.removeAttribute('tabindex');
        tabNode.classList.add('bux-hero__tab--active');
      
        if (panelNode) {
          panelNode.classList.add('showing');
        }
      
        if (moveFocus) {
          tabNode.focus();
        }
      };
    
      const hideTabpanel = (index) => {
        let tabNode = tabNodes[index];
        let panelNode = tabpanelNodes[index];
      
        tabNode.setAttribute('aria-selected', 'false');
        tabNode.setAttribute('tabindex', '-1');
        tabNode.classList.remove('bux-hero__tab--active');
      
        if (panelNode) {
          panelNode.classList.remove('showing');
        }
      };
    
      const handleTabFocus = () => {
        liveRegionNode.setAttribute('aria-live', 'polite');
      };
    
      tablistNode.addEventListener('focusin', handleTabFocus);
    
      for (let i = 0; i < nodes.length; i++) {
        let n = nodes[i];
    
        tabNodes.push(n);
    
        n.addEventListener('keydown', handleTabKeydown);
        n.addEventListener('click', handleSlidepickerClick);
    
        let tabpanelNode = document.getElementById(n.getAttribute('aria-controls'));
        if (tabpanelNode) {
          tabpanelNodes.push(tabpanelNode);
        } else {
          tabpanelNodes.push(null);
        }
    
        if (i === 0) {
          n.removeAttribute("tabindex");
        }
      }
    });
    
    // video controls
    const heroPauseButtons = Array.from(document.querySelectorAll(".bux-hero__video-button"));
    
    heroPauseButtons.forEach((pauseButton) => {
      const toggleVideo = () => {
        let buttonText = pauseButton.querySelector("span");
        const heroVideo = document.querySelector("video");
    
        if (heroVideo.paused) {
          heroVideo.play();
          buttonText.innerHTML = "Pause video";  
          pauseButton.classList.remove('bux-hero__video-play');
        } else {
          heroVideo.pause();
          buttonText.innerHTML = "Play video";
          pauseButton.classList.add('bux-hero__video-play');
        }
      }
      
      pauseButton.addEventListener("click", toggleVideo);
    });
  • URL: /components/raw/hero/hero.js
  • Filesystem Path: src/components/hero/hero.js
  • Size: 5.7 KB

No notes defined.