<section class="slider" data-slideshow-autoplay="true" data-slideshow-speed="10000">
    <div class="slider__inner">
        <div class="slider__slides">
            <div class="slider__slide" data-label="Erstes Slider-Thema" data-icon="position">
                <div style="height: 40rem; background-color: purple;">slide1</div>
            </div>
            <div class="slider__slide" data-label="Noch eine Beschriftung" data-icon="online-consulting">
                <div style="height: 40rem; background-color: yellow;">slide2</div>
            </div>
            <div class="slider__slide" data-label="Weiteres Slider-Thema" data-icon="employed">
                <div style="height: 40rem; background-color: blue;">slide3</div>
            </div>
        </div>
        <div class="slider__prev">
            <button class="icon-button slider__control slider__control--hidden icon-button--functional" id="icon-button-f5f3" type="button">
<svg class="icon icon--arrow-thin-left" id="icon-7fdf" viewBox="0 0 200 200" role="img" aria-labelledby="title-icon-7fdf">
  <title id="title-icon-7fdf">Previous slide</title>
  <use xlink:href="#icon-arrow-thin-left"></use>
</svg>
</button>
        </div>
        <div class="slider__next">
            <button class="icon-button slider__control icon-button--functional" id="icon-button-a5a8" type="button">
<svg class="icon icon--arrow-thin-right" id="icon-e1f8" viewBox="0 0 200 200" role="img" aria-labelledby="title-icon-e1f8">
  <title id="title-icon-e1f8">Next slide</title>
  <use xlink:href="#icon-arrow-thin-right"></use>
</svg>
</button>
        </div>
    </div>
</section>
-
  //- Prepare attr object
  attr = attr || {};
  attr.class = classList(attr.class);

  //- Tag
  tag = tag ? tag : 'section';

  //- Slideshow options
  attr['data-slideshow-autoplay'] = 'true';
  attr['data-slideshow-speed'] = 10000;

//- Render slider
#{tag}.slider&attributes(attr): .slider__inner
  //- Slides
  .slider__slides
    if slides
      each slide in slides
        .slider__slide&attributes({ 'data-label': slide.label, 'data-icon': slide.icon })
          != renderPug(slide.content)

  //- Previous slide
  .slider__prev
    != include('@icon-button--functional', { attr: { class: 'slider__control slider__control--hidden' }, icon: 'arrow-thin-left', title: 'Previous slide' })

  //- Next slide
  .slider__next
    != include('@icon-button--functional', { attr: { class: 'slider__control' }, icon: 'arrow-thin-right', title: 'Next slide' })
{
  "tag": "section",
  "slides": [
    {
      "label": "Erstes Slider-Thema",
      "icon": "position",
      "content": "div(style='height: 40rem; background-color: purple;') slide1\n"
    },
    {
      "label": "Noch eine Beschriftung",
      "icon": "online-consulting",
      "content": "div(style='height: 40rem; background-color: yellow;') slide2\n"
    },
    {
      "label": "Weiteres Slider-Thema",
      "icon": "employed",
      "content": "div(style='height: 40rem; background-color: blue;') slide3\n"
    }
  ]
}
  • Content:
    import { lory } from 'lory.js';
    import h from 'hyperscript';
    import icon from '../../../javascripts/utils/icon';
    
    class Slider {
      constructor($el) {
        this.$el = $el;
    
        const { dataset } = this.$el;
        this.config = {
          autoplay: dataset.slideshowAutoplay === 'true',
          speed: Number(dataset.slideshowSpeed) || 10000,
        };
    
        this.$sliderInner = this.$el.querySelector('.slider__inner');
        this.$slides = this.$el.querySelectorAll('.slider__slide');
        this.$controlPrev = this.$el
          .querySelector('.slider__prev')
          .querySelector('.slider__control');
    
        this.initEvents();
        this.initLory();
        this.initControls();
      }
    
      initEvents() {
        this.$el.addEventListener('after.lory.init', () => {
          this.$el.classList.add('slider--initialized');
        });
    
        this.$el.addEventListener('before.lory.slide', () => {
          if (this.config.autoplay) {
            this.stopSlideshow();
          }
        });
    
        this.$el.addEventListener('after.lory.slide', ({ detail }) => {
          const { currentSlide } = detail;
          const $navItems = this.$el.querySelectorAll('.slider__nav [data-slide-id]');
    
          $navItems.forEach(
            ($navItem) => {
              const isCurrentSlide = Number($navItem.dataset.slideId) === currentSlide;
    
              if (isCurrentSlide) {
                $navItem.classList.add('is-active');
              } else {
                $navItem.classList.remove('is-active');
              }
            },
          );
    
          if (this.config.autoplay) {
            this.startSlideshow();
          }
    
          if (currentSlide === 0) {
            this.$controlPrev.classList.add('slider__control--hidden');
          } else {
            this.$controlPrev.classList.remove('slider__control--hidden');
          }
        });
      }
    
      initLory() {
        this.lory = lory(this.$el, {
          infinite: false,
          rewind: true,
          slideSpeed: 1000,
          rewindOnResize: false,
          classNameFrame: 'slider__inner',
          classNameSlideContainer: 'slider__slides',
          classNamePrevCtrl: 'slider__prev',
          classNameNextCtrl: 'slider__next',
        });
    
        if (this.config.autoplay) {
          this.startSlideshow();
        }
      }
    
      initControls() {
        const hasPageNav = Array.from(this.$slides).some(
          $slide => Boolean($slide.dataset.label)
        );
    
        const $dotNav = h('ul.slider__dot-nav',
          this.$slides.map(
            (_, slideIndex) => h('li.slider__dot-item',
              h(`button.slider__dot-button${slideIndex === 0 ? '.is-active' : ''}`, {
                type: 'button',
                'data-slide-id': slideIndex,
                onclick: e => this.showSlide(e),
              }),
            ),
          ),
        );
    
        const $pageNav = hasPageNav
          ? h('ul.slider__page-nav',
            this.$slides.map(
              ({ dataset }, slideIndex) => h('li.slider__page-item',
                h(`button.slider__page-button${slideIndex === 0 ? '.is-active' : ''}`,
                  {
                    type: 'button',
                    'data-slide-id': slideIndex,
                    onclick: e => this.showSlide(e),
                  },
                  h('span.slider__page-clamp',
                    dataset.icon
                      ? h('span.slider__page-icon', icon({ icon: dataset.icon }))
                      : null,
                    dataset.label
                      ? h('span.slider__page-label', dataset.label)
                      : null,
                  ),
                  h('span.slider__page-progress', { style: { 'animation-duration': `${this.config.speed}ms` } }),
                ),
              ),
            ),
          )
          : null;
    
        const $pause = h('button.slider__pause', {
          type: 'button',
          onclick: e => this.toggleSlideshow(e),
        });
    
        this.$sliderInner.appendChild(
          h(`.slider__nav${hasPageNav ? '.slider__nav--has-page-nav' : ''}`,
            $pageNav,
            $dotNav,
            $pause,
          ),
        );
      }
    
      toggleSlideshow({ currentTarget }) {
        this.config.autoplay = !this.config.autoplay;
    
        if (this.config.autoplay) {
          currentTarget.classList.remove('slider__pause--active');
          this.startSlideshow();
        } else {
          currentTarget.classList.add('slider__pause--active');
          this.stopSlideshow();
        }
      }
    
      startSlideshow() {
        this.$el.classList.add('slider--autoplaying');
    
        this.slideshowTimer = setInterval(() => {
          this.lory.next();
        }, this.config.speed);
      }
    
      stopSlideshow() {
        this.$el.classList.remove('slider--autoplaying');
    
        clearInterval(this.slideshowTimer);
      }
    
      showSlide({ currentTarget }) {
        this.lory.slideTo(Number(currentTarget.dataset.slideId));
      }
    }
    
    document.querySelectorAll('.slider').forEach($slider => new Slider($slider));
    
  • URL: /components/raw/slider/slider.js
  • Filesystem Path: src/components/organisms/slider/slider.js
  • Size: 4.6 KB
  • Content:
    $slider-controls-margin: 4rem;
    $slider-controls-margin-from-xl: 3rem;
    $slider-controls-margin-from-xxl: calc(((100vw - #{$page-inner-max-width}) / 2) + 3rem);
    $slider-controls-margin-from-page-max: (($page-max-width - $page-inner-max-width) / 2) + 3rem;
    
    $slider-controls-dot-functional-size: 1.8rem;
    
    @mixin pause-svg($color: #fff) {
      background-image: svg-url('<svg viewBox="0 0 6 8" xmlns="http://www.w3.org/2000/svg"><path fill="' + $color + '" d="M0,1.3603254 L2.22044605e-16,6.61640556 C2.45376032e-16,7.16869031 0.44771525,7.61640556 1,7.61640556 C1.55228475,7.61640556 2,7.16869031 2,6.61640556 L2,1.3603254 C2,0.808040647 1.55228475,0.360325397 1,0.360325397 C0.44771525,0.360325397 -2.33314267e-17,0.808040647 0,1.3603254 Z" /><path fill="' + $color + '" d="M3.5,1.3603254 L3.5,6.61640556 C3.5,7.16869031 3.94771525,7.61640556 4.5,7.61640556 C5.05228475,7.61640556 5.5,7.16869031 5.5,6.61640556 L5.5,1.3603254 C5.5,0.808040647 5.05228475,0.360325397 4.5,0.360325397 C3.94771525,0.360325397 3.5,0.808040647 3.5,1.3603254 Z" /></svg>');
      background-position: center;
      background-size: 0.8rem;
    }
    
    .slider {
      width: 100%;
    }
    
    .slider--initialized {
      .slider__inner {
        overflow: hidden;
      }
    
      @include mq($from: l) {
        &:hover {
          .slider__control:not(.slider__control--hidden) {
            display: block;
          }
        }
    
        .slider__control--hidden {
          display: none;
        }
      }
    }
    
    .slider__inner {
      overflow-x: scroll;
      position: relative;
      width: 100%;
    }
    
    .slider__slides {
      display: flex;
      z-index: 1;
    }
    
    .slider__slide {
      flex-shrink: 0;
      position: relative;
      width: 100%;
    }
    
    .slider__control {
      background-color: rgba($color-steelgrey-dark, 0.3);
      color: #fff;
      display: none;
      height: 9rem;
      margin: 0;
      transition-duration: $default-transition-duration;
      transition-property: background-color;
    
      &:hover,
      &:focus {
        background-color: $color-steelgrey-dark;
      }
    }
    
    .slider__prev,
    .slider__next {
      cursor: pointer;
      display: block;
      position: absolute;
      top: 50%;
      transform: translate(0, -50%);
      z-index: 2;
    }
    
    .slider__next {
      right: $slider-controls-margin;
    
      @include mq($from: xl) {
        right: $slider-controls-margin-from-xl;
      }
    
      @include mq($from: xxl) {
        right: $slider-controls-margin-from-xxl;
      }
    
      @include mq($from: page-max) {
        right: $slider-controls-margin-from-page-max;
      }
    }
    
    .slider__prev {
      left: $slider-controls-margin;
    
      @include mq($from: xl) {
        left: $slider-controls-margin-from-xl;
      }
    
      @include mq($from: xxl) {
        left: $slider-controls-margin-from-xxl;
      }
    
      @include mq($from: page-max) {
        left: $slider-controls-margin-from-page-max;
      }
    }
    
    .slider__nav {
      @include make-container();
      align-items: flex-end;
      bottom: 5rem;
      display: flex;
      left: 0;
      position: absolute;
      right: 0;
      z-index: 1;
    
      @include mq($from: m) {
        bottom: 9rem;
      }
    }
    
    .slider__nav--has-page-nav {
      @include mq($until: l) {
        .slider__page-nav {
          display: none;
        }
      }
    
      @include mq($from: l) {
        align-items: center;
    
        .slider__dot-nav {
          display: none;
        }
      }
    }
    
    .slider__dot-nav {
      @include list-reset();
      display: flex;
      margin-left: auto;
      margin-right: 0.5rem;
    }
    
    .slider__dot-item {
      display: inline-flex;
      margin-left: 0.5rem;
      margin-right: 0.5rem;
    }
    
    .slider__dot-button {
      background-color: $color-steelgrey-dark;
      cursor: pointer;
      display: inline-block;
      height: 0.7rem;
      width: 2rem;
    
      &:hover {
        background-color: #fff;
      }
    
      &.is-active {
        background-color: #fff;
      }
    }
    
    .slider__page-nav {
      @include list-reset();
      align-items: center;
      display: flex;
      flex-grow: 1;
      justify-content: center;
      list-style: none;
      margin-left: auto;
      margin-right: auto;
    }
    
    .slider__page-item {
      margin-left: 0.3rem;
      margin-right: 0.3rem;
    }
    
    .slider__page-button {
      background-color: #fff;
      color: $color-blue;
      cursor: pointer;
      display: inline-block;
      font-weight: normal;
      line-height: 1;
      min-width: 20rem;
      padding: 1rem;
      position: relative;
      transition-duration: $default-transition-duration;
      transition-property: color;
    
      &:not(.is-active):hover {
        color: $color-blue-light;
      }
    
      &.is-active {
        cursor: default;
        font-weight: bold;
      }
    }
    
    .slider__page-clamp {
      align-items: center;
      display: flex;
    }
    
    .slider__page-icon {
      flex-shrink: 0;
      font-size: 1.6rem;
      margin-right: 0.8rem;
    }
    
    .slider__page-label {
      font-size: 1.4rem;
    }
    
    @keyframes sliderProgress {
      0% {
        width: 0;
      }
    
      100% {
        width: 100%;
      }
    }
    
    .slider__page-progress {
      background-color: $color-blue;
      bottom: -0.2rem;
      height: 0.2rem;
      left: 0;
      position: absolute;
      width: 0;
    }
    
    .slider__pause {
      @include pause-svg();
      background-color: $color-steelgrey-dark;
      border-radius: 2px;
      cursor: pointer;
      display: inline-block;
      height: $slider-controls-dot-functional-size;
      width: $slider-controls-dot-functional-size;
    }
    
    .slider__pause--active {
      background-color: $color-red;
    }
    
    // Hide page nav on smaller viewports
    @include mq($until: l) {
      .slider__nav--has-page-nav .slider__page-nav {
        display: none;
      }
    }
    
    @include mq($from: l) {
      // Show page nav on larger viewports and hide redundant dot nav
      .slider__nav--has-page-nav {
        align-items: center;
    
        .slider__dot-nav {
          display: none;
        }
      }
    
      // Enable progress animation on page nav buttons for active pages
      .slider--autoplaying .slider__page-button.is-active .slider__page-progress {
        animation-name: sliderProgress;
        animation-timing-function: linear;
      }
    }
    
  • URL: /components/raw/slider/slider.scss
  • Filesystem Path: src/components/organisms/slider/slider.scss
  • Size: 5.5 KB

There are no notes for this item.