<div id="shorts-slider-76720-79249" class="shorts-slider">
    <div class="shorts-slider__shorts u-hide-scrollbar" id="shorts-slider-76720-79249-shorts">
        <div class="shorts-slider__short">
            <div class="external-video">
                <template class="external-video__code"><iframe width="315" height="560" src="https://www.youtube-nocookie.com/embed/tqH5nwGi3jQ" title="YouTube-Video" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></template>

                <div class="external-video__content">
                    <div class="external-video__preview" style="padding-top: 177.77777777778%;">
                        <img class="external-video__preview-image" src="https://i.ytimg.com/vi/PG8TPBfN0-s/hqdefault.jpg" width="315" height="315" alt="" role="presentation" lazy="lazy">

                        <div class="external-video__overlay has-overlay-link">
                            <p class="external-video__overlay-title">
                                <span class="u-line-clamp">Max. zweizeiliger Videotitel mit ca. 100 Zeichen, der automatisch von Youtube/Vimeo gezogen wird</span>
                            </p>

                            <div class="external-video__overlay-footer">
                                <div class="external-video__overlay-text">
                                    Bei Klick auf dieses Video wird eine Verbindung zu YouTube aufgebaut. Weitere Informationen findest Du in unserer <a class="link link--internal" href="#"><span class="link__text u-underline">Datenschutzerklärung</span></a>.
                                </div>

                                <button class="icon-button u-overlay-link external-video__overlay-button" type="button" title="Video abspielen">
                                    <span class="icon-button__icon">
                                        <svg class="icon icon--play" viewBox="0 0 200 200" aria-hidden="true">
                                            <use xlink:href="/assets/icons/icons.3bafb6df0d.svg#play"></use>
                                        </svg> </span>

                                </button>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
        <div class="shorts-slider__short">
            <div class="external-video">
                <template class="external-video__code"><iframe width="315" height="560" src="https://www.youtube-nocookie.com/embed/tqH5nwGi3jQ" title="YouTube-Video" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></template>

                <div class="external-video__content">
                    <div class="external-video__preview" style="padding-top: 177.77777777778%;">
                        <img class="external-video__preview-image" src="https://i.ytimg.com/vi/PG8TPBfN0-s/hqdefault.jpg" width="315" height="315" alt="" role="presentation" lazy="lazy">

                        <div class="external-video__overlay has-overlay-link">
                            <p class="external-video__overlay-title">
                                <span class="u-line-clamp">Max. zweizeiliger Videotitel mit ca. 100 Zeichen, der automatisch von Youtube/Vimeo gezogen wird</span>
                            </p>

                            <div class="external-video__overlay-footer">
                                <div class="external-video__overlay-text">
                                    Bei Klick auf dieses Video wird eine Verbindung zu YouTube aufgebaut. Weitere Informationen findest Du in unserer <a class="link link--internal" href="#"><span class="link__text u-underline">Datenschutzerklärung</span></a>.
                                </div>

                                <button class="icon-button u-overlay-link external-video__overlay-button" type="button" title="Video abspielen">
                                    <span class="icon-button__icon">
                                        <svg class="icon icon--play" viewBox="0 0 200 200" aria-hidden="true">
                                            <use xlink:href="/assets/icons/icons.3bafb6df0d.svg#play"></use>
                                        </svg> </span>

                                </button>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
        <div class="shorts-slider__short">
            <div class="external-video">
                <template class="external-video__code"><iframe width="315" height="560" src="https://www.youtube-nocookie.com/embed/tqH5nwGi3jQ" title="YouTube-Video" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></template>

                <div class="external-video__content">
                    <div class="external-video__preview" style="padding-top: 177.77777777778%;">
                        <img class="external-video__preview-image" src="https://i.ytimg.com/vi/PG8TPBfN0-s/hqdefault.jpg" width="315" height="315" alt="" role="presentation" lazy="lazy">

                        <div class="external-video__overlay has-overlay-link">
                            <p class="external-video__overlay-title">
                                <span class="u-line-clamp">Max. zweizeiliger Videotitel mit ca. 100 Zeichen, der automatisch von Youtube/Vimeo gezogen wird</span>
                            </p>

                            <div class="external-video__overlay-footer">
                                <div class="external-video__overlay-text">
                                    Bei Klick auf dieses Video wird eine Verbindung zu YouTube aufgebaut. Weitere Informationen findest Du in unserer <a class="link link--internal" href="#"><span class="link__text u-underline">Datenschutzerklärung</span></a>.
                                </div>

                                <button class="icon-button u-overlay-link external-video__overlay-button" type="button" title="Video abspielen">
                                    <span class="icon-button__icon">
                                        <svg class="icon icon--play" viewBox="0 0 200 200" aria-hidden="true">
                                            <use xlink:href="/assets/icons/icons.3bafb6df0d.svg#play"></use>
                                        </svg> </span>

                                </button>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
        <div class="shorts-slider__short">
            <div class="external-video">
                <template class="external-video__code"><iframe width="315" height="560" src="https://www.youtube-nocookie.com/embed/tqH5nwGi3jQ" title="YouTube-Video" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></template>

                <div class="external-video__content">
                    <div class="external-video__preview" style="padding-top: 177.77777777778%;">
                        <img class="external-video__preview-image" src="https://i.ytimg.com/vi/PG8TPBfN0-s/hqdefault.jpg" width="315" height="315" alt="" role="presentation" lazy="lazy">

                        <div class="external-video__overlay has-overlay-link">
                            <p class="external-video__overlay-title">
                                <span class="u-line-clamp">Max. zweizeiliger Videotitel mit ca. 100 Zeichen, der automatisch von Youtube/Vimeo gezogen wird</span>
                            </p>

                            <div class="external-video__overlay-footer">
                                <div class="external-video__overlay-text">
                                    Bei Klick auf dieses Video wird eine Verbindung zu YouTube aufgebaut. Weitere Informationen findest Du in unserer <a class="link link--internal" href="#"><span class="link__text u-underline">Datenschutzerklärung</span></a>.
                                </div>

                                <button class="icon-button u-overlay-link external-video__overlay-button" type="button" title="Video abspielen">
                                    <span class="icon-button__icon">
                                        <svg class="icon icon--play" viewBox="0 0 200 200" aria-hidden="true">
                                            <use xlink:href="/assets/icons/icons.3bafb6df0d.svg#play"></use>
                                        </svg> </span>

                                </button>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
        <div class="shorts-slider__short">
            <div class="external-video">
                <template class="external-video__code"><iframe width="315" height="560" src="https://www.youtube-nocookie.com/embed/tqH5nwGi3jQ" title="YouTube-Video" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></template>

                <div class="external-video__content">
                    <div class="external-video__preview" style="padding-top: 177.77777777778%;">
                        <img class="external-video__preview-image" src="https://i.ytimg.com/vi/PG8TPBfN0-s/hqdefault.jpg" width="315" height="315" alt="" role="presentation" lazy="lazy">

                        <div class="external-video__overlay has-overlay-link">
                            <p class="external-video__overlay-title">
                                <span class="u-line-clamp">Max. zweizeiliger Videotitel mit ca. 100 Zeichen, der automatisch von Youtube/Vimeo gezogen wird</span>
                            </p>

                            <div class="external-video__overlay-footer">
                                <div class="external-video__overlay-text">
                                    Bei Klick auf dieses Video wird eine Verbindung zu YouTube aufgebaut. Weitere Informationen findest Du in unserer <a class="link link--internal" href="#"><span class="link__text u-underline">Datenschutzerklärung</span></a>.
                                </div>

                                <button class="icon-button u-overlay-link external-video__overlay-button" type="button" title="Video abspielen">
                                    <span class="icon-button__icon">
                                        <svg class="icon icon--play" viewBox="0 0 200 200" aria-hidden="true">
                                            <use xlink:href="/assets/icons/icons.3bafb6df0d.svg#play"></use>
                                        </svg> </span>

                                </button>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
        <div class="shorts-slider__short">
            <div class="external-video">
                <template class="external-video__code"><iframe width="315" height="560" src="https://www.youtube-nocookie.com/embed/tqH5nwGi3jQ" title="YouTube-Video" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></template>

                <div class="external-video__content">
                    <div class="external-video__preview" style="padding-top: 177.77777777778%;">
                        <img class="external-video__preview-image" src="https://i.ytimg.com/vi/PG8TPBfN0-s/hqdefault.jpg" width="315" height="315" alt="" role="presentation" lazy="lazy">

                        <div class="external-video__overlay has-overlay-link">
                            <p class="external-video__overlay-title">
                                <span class="u-line-clamp">Max. zweizeiliger Videotitel mit ca. 100 Zeichen, der automatisch von Youtube/Vimeo gezogen wird</span>
                            </p>

                            <div class="external-video__overlay-footer">
                                <div class="external-video__overlay-text">
                                    Bei Klick auf dieses Video wird eine Verbindung zu YouTube aufgebaut. Weitere Informationen findest Du in unserer <a class="link link--internal" href="#"><span class="link__text u-underline">Datenschutzerklärung</span></a>.
                                </div>

                                <button class="icon-button u-overlay-link external-video__overlay-button" type="button" title="Video abspielen">
                                    <span class="icon-button__icon">
                                        <svg class="icon icon--play" viewBox="0 0 200 200" aria-hidden="true">
                                            <use xlink:href="/assets/icons/icons.3bafb6df0d.svg#play"></use>
                                        </svg> </span>

                                </button>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
        <div class="shorts-slider__short">
            <div class="external-video">
                <template class="external-video__code"><iframe width="315" height="560" src="https://www.youtube-nocookie.com/embed/tqH5nwGi3jQ" title="YouTube-Video" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></template>

                <div class="external-video__content">
                    <div class="external-video__preview" style="padding-top: 177.77777777778%;">
                        <img class="external-video__preview-image" src="https://i.ytimg.com/vi/PG8TPBfN0-s/hqdefault.jpg" width="315" height="315" alt="" role="presentation" lazy="lazy">

                        <div class="external-video__overlay has-overlay-link">
                            <p class="external-video__overlay-title">
                                <span class="u-line-clamp">Max. zweizeiliger Videotitel mit ca. 100 Zeichen, der automatisch von Youtube/Vimeo gezogen wird</span>
                            </p>

                            <div class="external-video__overlay-footer">
                                <div class="external-video__overlay-text">
                                    Bei Klick auf dieses Video wird eine Verbindung zu YouTube aufgebaut. Weitere Informationen findest Du in unserer <a class="link link--internal" href="#"><span class="link__text u-underline">Datenschutzerklärung</span></a>.
                                </div>

                                <button class="icon-button u-overlay-link external-video__overlay-button" type="button" title="Video abspielen">
                                    <span class="icon-button__icon">
                                        <svg class="icon icon--play" viewBox="0 0 200 200" aria-hidden="true">
                                            <use xlink:href="/assets/icons/icons.3bafb6df0d.svg#play"></use>
                                        </svg> </span>

                                </button>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <div class="shorts-slider__navigation">
        <div class="shorts-slider__scroll-bar" aria-hidden="true" data-scroll-bar-target="shorts-slider-76720-79249-shorts">
            <div class="shorts-slider__scroll-bar-backdrop"></div>
            <div class="shorts-slider__scroll-bar-thumb"></div>
        </div>

        <div class="shorts-slider__buttons">
            <button class="navigation-button shorts-slider__navigation-button shorts-slider__navigation-button--left" type="button" title="Nach links scrollen" disabled tabindex="-1">
                <svg class="icon icon--caret-left" viewBox="0 0 200 200" aria-hidden="true">
                    <use xlink:href="/assets/icons/icons.3bafb6df0d.svg#caret-left"></use>
                </svg></button>

            <button class="navigation-button shorts-slider__navigation-button shorts-slider__navigation-button--right" type="button" title="Nach rechts scrollen" disabled tabindex="-1">
                <svg class="icon icon--caret-right" viewBox="0 0 200 200" aria-hidden="true">
                    <use xlink:href="/assets/icons/icons.3bafb6df0d.svg#caret-right"></use>
                </svg></button>
        </div>
    </div>
</div>
{% set id = id ??? html_id('shorts-slider') %}

<div {{ html_attributes({
  id: id,
  class: 'shorts-slider',
}, attrs ?? {}) }}>
  <div class="shorts-slider__shorts u-hide-scrollbar" id="{{ 'shorts' | namespaceInputId(id) }}">
    {% for short in shorts %}
      <div class="shorts-slider__short">
        {% include '@external-video' with short only %}
      </div>
    {% endfor %}
  </div>

  <div class="shorts-slider__navigation">
    <div class="shorts-slider__scroll-bar" aria-hidden="true" data-scroll-bar-target="{{ 'shorts' | namespaceInputId(id) }}">
      <div class="shorts-slider__scroll-bar-backdrop"></div>
      <div class="shorts-slider__scroll-bar-thumb"></div>
    </div>

    <div class="shorts-slider__buttons">
      {% include '@navigation-button' with {
        title: 'Scroll left' | t('site'),
        direction: 'left',
        disabled: true,
        tabindex: '-1',
        attrs: {
          class: 'shorts-slider__navigation-button shorts-slider__navigation-button--left',
        },
      } only %}

      {% include '@navigation-button' with {
        title: 'Scroll right' | t('site'),
        direction: 'right',
        disabled: true,
        tabindex: '-1',
        attrs: {
          class: 'shorts-slider__navigation-button shorts-slider__navigation-button--right',
        },
      } only %}
    </div>
  </div>
</div>
{
  "shorts": [
    {
      "width": 315,
      "height": 560,
      "content": "<iframe width=\"315\" height=\"560\" src=\"https://www.youtube-nocookie.com/embed/tqH5nwGi3jQ\" title=\"YouTube-Video\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>",
      "preview": "https://i.ytimg.com/vi/PG8TPBfN0-s/hqdefault.jpg",
      "title": "Max. zweizeiliger Videotitel mit ca. 100 Zeichen, der automatisch von Youtube/Vimeo gezogen wird",
      "provider": "YouTube",
      "privacyLink": "#"
    },
    {
      "width": 315,
      "height": 560,
      "content": "<iframe width=\"315\" height=\"560\" src=\"https://www.youtube-nocookie.com/embed/tqH5nwGi3jQ\" title=\"YouTube-Video\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>",
      "preview": "https://i.ytimg.com/vi/PG8TPBfN0-s/hqdefault.jpg",
      "title": "Max. zweizeiliger Videotitel mit ca. 100 Zeichen, der automatisch von Youtube/Vimeo gezogen wird",
      "provider": "YouTube",
      "privacyLink": "#"
    },
    {
      "width": 315,
      "height": 560,
      "content": "<iframe width=\"315\" height=\"560\" src=\"https://www.youtube-nocookie.com/embed/tqH5nwGi3jQ\" title=\"YouTube-Video\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>",
      "preview": "https://i.ytimg.com/vi/PG8TPBfN0-s/hqdefault.jpg",
      "title": "Max. zweizeiliger Videotitel mit ca. 100 Zeichen, der automatisch von Youtube/Vimeo gezogen wird",
      "provider": "YouTube",
      "privacyLink": "#"
    },
    {
      "width": 315,
      "height": 560,
      "content": "<iframe width=\"315\" height=\"560\" src=\"https://www.youtube-nocookie.com/embed/tqH5nwGi3jQ\" title=\"YouTube-Video\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>",
      "preview": "https://i.ytimg.com/vi/PG8TPBfN0-s/hqdefault.jpg",
      "title": "Max. zweizeiliger Videotitel mit ca. 100 Zeichen, der automatisch von Youtube/Vimeo gezogen wird",
      "provider": "YouTube",
      "privacyLink": "#"
    },
    {
      "width": 315,
      "height": 560,
      "content": "<iframe width=\"315\" height=\"560\" src=\"https://www.youtube-nocookie.com/embed/tqH5nwGi3jQ\" title=\"YouTube-Video\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>",
      "preview": "https://i.ytimg.com/vi/PG8TPBfN0-s/hqdefault.jpg",
      "title": "Max. zweizeiliger Videotitel mit ca. 100 Zeichen, der automatisch von Youtube/Vimeo gezogen wird",
      "provider": "YouTube",
      "privacyLink": "#"
    },
    {
      "width": 315,
      "height": 560,
      "content": "<iframe width=\"315\" height=\"560\" src=\"https://www.youtube-nocookie.com/embed/tqH5nwGi3jQ\" title=\"YouTube-Video\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>",
      "preview": "https://i.ytimg.com/vi/PG8TPBfN0-s/hqdefault.jpg",
      "title": "Max. zweizeiliger Videotitel mit ca. 100 Zeichen, der automatisch von Youtube/Vimeo gezogen wird",
      "provider": "YouTube",
      "privacyLink": "#"
    },
    {
      "width": 315,
      "height": 560,
      "content": "<iframe width=\"315\" height=\"560\" src=\"https://www.youtube-nocookie.com/embed/tqH5nwGi3jQ\" title=\"YouTube-Video\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>",
      "preview": "https://i.ytimg.com/vi/PG8TPBfN0-s/hqdefault.jpg",
      "title": "Max. zweizeiliger Videotitel mit ca. 100 Zeichen, der automatisch von Youtube/Vimeo gezogen wird",
      "provider": "YouTube",
      "privacyLink": "#"
    }
  ]
}
  • Content:
    .shorts-slider__inner {
      @include use-break-out();
    }
    
    .shorts-slider__shorts {
      display: flex;
      overflow-x: scroll;
      overflow-y: hidden;
      position: relative;
      scroll-behavior: smooth;
      scroll-snap-type: x mandatory;
      z-index: 1;
    
      @include use-responsive-sizing(gap, $gaps);
    }
    
    .shorts-slider__shorts--was-dragged {
      scroll-behavior: auto;
    }
    
    .shorts-slider__short {
      display: grid;
      flex-shrink: 0;
      inline-size: 32.5rem;
      scroll-snap-align: start;
    
      .shorts-slider__cards--was-dragged & {
        scroll-snap-align: none;
      }
    }
    
    .shorts-slider__navigation {
      align-items: center;
      display: flex;
      gap: 2rem;
      margin-block-start: 2rem;
    }
    
    .shorts-slider__scroll-bar {
      block-size: 1rem;
      flex-grow: 1;
      opacity: 0.3;
      pointer-events: none;
      position: relative;
      transition-property: opacity, transform;
    }
    
    .shorts-slider__scroll-bar--enabled {
      cursor: pointer;
      opacity: 1;
      pointer-events: all;
    
      &:hover {
        transform: scaleY(2);
      }
    }
    
    .shorts-slider__scroll-bar-backdrop {
      background-color: var(--color-grey-x-light);
      border-radius: 0.5rem;
      inset: 0;
      position: absolute;
    }
    
    .shorts-slider__scroll-bar-thumb {
      background-color: var(--color-midnight);
      border-radius: 0.5rem;
      inset-block: 0;
      position: absolute;
      will-change: left, width, transform;
    }
    
    .shorts-slider__buttons {
      display: flex;
      flex-shrink: 0;
      gap: 2rem;
      touch-action: manipulation;
    }
    
  • URL: /components/raw/shorts-slider/shorts-slider.scss
  • Filesystem Path: src/components/3-organisms/shorts-slider/shorts-slider.scss
  • Size: 1.4 KB
  • Content:
    import Draggabilly from 'draggabilly';
    import { destroyExternalVideo } from '../../2-molecules/external-video/external-video';
    
    class ShortsSlider {
      $shortsSlider: HTMLElement;
      $shorts: HTMLElement;
      $scrollBar: HTMLElement;
      $thumb: HTMLElement;
      $$short: NodeListOf<HTMLElement>;
      $leftScrollButton: HTMLElement | null = null;
      $rightScrollButton: HTMLElement | null = null;
      thumbLeft = 0;
      enableScrollbarUpdates = true;
      enableLeftScrollButton = false;
      enableRightScrollButton = false;
    
      constructor($shortsSlider: HTMLElement) {
        this.$shortsSlider = $shortsSlider;
    
        const $shorts = this.$shortsSlider.querySelector<HTMLElement>(
          '.shorts-slider__shorts',
        );
    
        const $$short = this.$shortsSlider.querySelectorAll<HTMLElement>(
          '.shorts-slider__short',
        );
    
        const $scrollBar = this.$shortsSlider.querySelector<HTMLElement>(
          '.shorts-slider__scroll-bar',
        );
    
        const $thumb = $scrollBar?.querySelector<HTMLElement>(
          '.shorts-slider__scroll-bar-thumb',
        );
    
        if (!$shorts || !$scrollBar || !$thumb) {
          throw new Error('Shorts and/or scroll bar are missing');
        }
    
        this.$shorts = $shorts;
        this.$scrollBar = $scrollBar;
        this.$thumb = $thumb;
        this.$$short = $$short;
    
        // Init everything
        this.initScrollButtons();
        this.initScrollBar();
        this.initSwitcher();
    
        // Force to scroll position to zero on load
        window.requestAnimationFrame(() => {
          this.$shorts.scrollTo({ left: 0, behavior: 'instant' });
          this.update();
        });
      }
    
      initSwitcher() {
        this.$$short.forEach(($short) => {
          $short.addEventListener('click', (event) => {
            const { target } = event;
    
            if (
              target instanceof HTMLElement &&
              target.closest('.external-video__overlay-button')
            ) {
              this.$$short.forEach(($otherShort) => {
                if ($otherShort !== $short) {
                  const $externalVideo =
                    $otherShort.querySelector<HTMLElement>('.external-video');
    
                  if ($externalVideo) {
                    destroyExternalVideo($externalVideo);
                  }
                }
              });
            }
          });
        });
      }
    
      initScrollBar() {
        // Update on scroll and initial load
        this.$shorts.addEventListener('scroll', () => this.update(), {
          passive: true,
        });
    
        // Update on resizing of scroll bar
        const resizeObserver = new ResizeObserver(() => this.update());
        resizeObserver.observe(this.$scrollBar);
    
        // Move on backdrop click
        this.$scrollBar
          .querySelector('.shorts-slider__scroll-bar-backdrop')
          ?.addEventListener('click', (event) => {
            // @ts-expect-error layerX is a non-standard, but well supported attribute on MouseEvent
            const { layerX } = event;
    
            this.$shorts.scrollLeft =
              (layerX / this.$scrollBar.offsetWidth) * this.$shorts.scrollWidth;
          });
    
        const draggie = new Draggabilly(this.$thumb, {
          axis: 'x',
          containment: true,
        });
    
        draggie.on('dragStart', () => {
          this.enableScrollbarUpdates = false;
          this.$shorts.classList.add('shorts-slider__shorts--was-dragged');
        });
    
        draggie.on('dragMove', (event, pointer, moveVector) => {
          this.$shorts.scrollLeft =
            ((this.thumbLeft + moveVector.x) / this.$scrollBar.offsetWidth) *
            this.$shorts.scrollWidth;
        });
    
        draggie.on('dragEnd', () => {
          this.enableScrollbarUpdates = true;
          this.$shorts.classList.remove('shorts-slider__shorts--was-dragged');
          this.update();
        });
      }
    
      initScrollButtons() {
        // Left scroll button
        this.$leftScrollButton = this.$shortsSlider.querySelector(
          '.shorts-slider__navigation-button--left',
        );
    
        this.$leftScrollButton?.addEventListener('click', (event) => {
          event.preventDefault();
          this.move('left');
        });
    
        // Right scroll button
        this.$rightScrollButton = this.$shortsSlider.querySelector(
          '.shorts-slider__navigation-button--right',
        );
    
        this.$rightScrollButton?.addEventListener('click', (event) => {
          event.preventDefault();
          this.move('right');
        });
      }
    
      move(direciton: 'left' | 'right') {
        const cardWidth = this.$shorts.querySelector<HTMLElement>(
          '.shorts-slider__short',
        )?.offsetWidth;
    
        if (cardWidth) {
          this.$shorts.scrollTo({
            left:
              this.$shorts.scrollLeft +
              (direciton === 'left' ? cardWidth * -1 : cardWidth),
          });
        }
      }
    
      update() {
        if (!this.enableScrollbarUpdates) {
          return;
        }
    
        window.requestAnimationFrame(() => {
          const width = (this.$shorts.offsetWidth / this.$shorts.scrollWidth) * 100;
          this.thumbLeft =
            (this.$shorts.scrollLeft / this.$shorts.scrollWidth) *
            this.$scrollBar.offsetWidth;
    
          this.$thumb.style.setProperty('width', `${width}%`);
          this.$thumb.style.setProperty('left', `${this.thumbLeft}px`);
    
          this.$scrollBar.classList.toggle(
            'shorts-slider__scroll-bar--enabled',
            width < 100,
          );
    
          this.$leftScrollButton?.toggleAttribute(
            'disabled',
            this.$shorts.scrollLeft === 0,
          );
    
          this.$rightScrollButton?.toggleAttribute(
            'disabled',
            this.$shorts.scrollWidth <=
              this.$shorts.scrollLeft + this.$shorts.offsetWidth,
          );
        });
      }
    }
    
    document
      .querySelectorAll<HTMLElement>('.shorts-slider')
      .forEach(($shortsSlider) => new ShortsSlider($shortsSlider));
    
    export default ShortsSlider;
    
  • URL: /components/raw/shorts-slider/shorts-slider.ts
  • Filesystem Path: src/components/3-organisms/shorts-slider/shorts-slider.ts
  • Size: 5.5 KB

No notes defined.