<div id="community-breaker-36015-37585" class="community-breaker">
    <div class="community-breaker__inner">
        <h2 class="community-breaker__headline"><span class="community-breaker__headline-text">Suchergebnisse in der Community</span><span class="community-breaker__headline-icon">&#65279;<svg class="icon icon--cta-arrow community-breaker__headline-icon-inner" viewBox="0 0 200 200" aria-hidden="true">
                    <use xlink:href="/assets/icons/icons.3bafb6df0d.svg#cta-arrow"></use>
                </svg></span></h2>

        <div class="community-breaker__teasers u-hide-scrollbar">
            <p>0 Treffer für XY.</p>

        </div>

        <div class="community-breaker__buttons">

        </div>
    </div>
</div>
{% set id = id ??? html_id('community-breaker') %}
{% set level = level ??? 2 -%}
{% set type = type ??? 'highlights' %}

<div {{ html_attributes({
  id: id,
  class: 'community-breaker',
}, attrs ?? {}) }}>
  <div class="community-breaker__inner">
    {% if headline|default %}
      <h{{ level }} class="community-breaker__headline">{% apply spaceless %}
        <span class="community-breaker__headline-text">
          {{- headline.text -}}
        </span>

        <span class="community-breaker__headline-icon">
          {{- '&#65279;' | raw -}}
          {%- include '@icon' with {
            icon: 'cta-arrow',
            class: 'community-breaker__headline-icon-inner',
          } only -%}
        </span>
      {% endapply %}</h{{ level }}>
    {% endif %}

    <div class="community-breaker__teasers u-hide-scrollbar">
      {% for teaser in teasers %}
        <div class="community-breaker__teaser">
          {% include "@community-teaser" with teaser | merge({
            level: level + 1,
          }) only %}
        </div>
      {% else %}
        {% if emptyMessage|default %}
          <p>{{ emptyMessage }}</p>
        {% endif %}
      {% endfor %}

      {% if callToAction|default %}
        <div class="community-breaker__call-to-action u-inverted">
          {% if callToAction.icon|default %}
            {% include '@icon' with {
              icon: callToAction.icon,
              class: 'community-breaker__call-to-action-icon',
            } only %}
          {% endif %}

          <div class="community-breaker__call-to-action-headline">
            {% include '@headline' with callToAction.headline | merge({
              size: 3,
              level: level + 1,
            }) only %}
          </div>

          {% if callToAction.button|default %}
            <div class="community-breaker__call-to-action-button">
              {% include '@button' with callToAction.button | merge({
                outline: true,
              }) only %}
            </div>
          {% endif %}

          {% if callToAction.text|default %}
            <div class="community-breaker__call-to-action-text">
              {{- callToAction.text | componentize -}}
            </div>
          {% endif %}
        </div>
      {% endif %}
    </div>

    <div class="community-breaker__buttons">
      {% if button|default %}
        <div class="community-breaker__button">
          {% include '@button' with button only %}
        </div>
      {% endif %}

      {% if teasers and teasers|length > 1 %}
        <div class="community-breaker__navigation-buttons">
          {% include '@navigation-button' with {
            title: 'Scroll left' | t('site'),
            direction: 'left',
            disabled: true,
            tabindex: '-1',
            attrs: {
              class: 'community-breaker__navigation-button community-breaker__navigation-button--left',
            },
          } only %}

          {% include '@navigation-button' with {
            title: 'Scroll right' | t('site'),
            direction: 'right',
            disabled: true,
            tabindex: '-1',
            attrs: {
              class: 'community-breaker__navigation-button community-breaker__navigation-button--right',
            },
          } only %}
        </div>
      {% endif %}
    </div>
  </div>
</div>
{
  "headline": {
    "text": "Suchergebnisse in der Community"
  },
  "teasers": false,
  "emptyMessage": "0 Treffer für XY."
}
  • Content:
    .community-breaker {
      --community-teaser-badge-offset-factor: 2.2;
      --community-breaker-call-to-action-icon-size: 7.4rem;
      --community-breaker-call-to-action-padding: 4rem;
    
      background-color: var(--community-breaker-background-color, var(--color-cyan-light));
    
      @include use-responsive-sizing(--community-breaker-padding-block, responsive-map(xs 4rem, xl 6rem));
      @include use-responsive-sizing(--community-teaser-badge-size, responsive-map(xs 5rem, xl 7.5rem));
    }
    
    .community-breaker__inner {
      padding-block: var(--community-breaker-padding-block);
      position: relative;
    
      @include use-container();
    }
    
    .community-breaker__headline {
      font-weight: var(--font-weight-semibold);
      letter-spacing: -0.04em;
      line-height: var(--line-height-small);
      margin-block-end: 2rem;
      position: relative;
      z-index: 2;
    
      @include use-responsive-sizing(font-size, responsive-map(xs 2.6rem, xl 3.6rem));
    }
    
    .community-breaker__headline-icon {
      color: var(--color-orange);
      font-size: 5.3rem;
      margin-inline-start: 1rem;
      vertical-align: -2.4rem;
      white-space: nowrap;
    
      @include mq($from: l) {
        font-size: 7.2rem;
        vertical-align: -3.2rem;
      }
    }
    
    .community-breaker__headline-icon-inner {
      position: relative;
      rotate: -105deg;
    }
    
    .community-breaker__teasers {
      display: flex;
      flex-shrink: 0;
      flex-wrap: wrap;
      margin-inline: calc(var(--inner-container-padding) * -1);
      overflow-x: hidden;
      position: relative;
      row-gap: 2rem;
      scroll-behavior: smooth;
      scroll-snap-type: y mandatory;
      z-index: 2;
    
      @include use-responsive-sizing(column-gap, $gaps);
    
      @include mq($from: m) {
        flex-wrap: nowrap;
        margin-inline: 0;
        overflow-x: scroll;
        overflow-y: hidden;
        scroll-snap-type: x mandatory;
      }
    }
    
    .community-breaker__teaser,
    .community-breaker__call-to-action {
      @include use-responsive-sizing(--community-breaker-teaser-width, (
        xs: 100%,
        m: column-width(m, 6),
        l: column-width(l, 4),
        xl: column-width(xl, 4),
      ));
    }
    
    .community-breaker__teaser {
      display: flex;
      flex-shrink: 0;
      inline-size: var(--community-breaker-teaser-width);
      padding-inline: var(--inner-container-padding);
      position: relative;
      scroll-snap-align: start;
      z-index: 2;
    
      @include mq($from: m) {
        padding-inline: 0;
      }
    }
    
    .community-breaker__call-to-action {
      --community-breaker-call-to-action-offset: calc(var(--community-teaser-badge-size) / var(--community-teaser-badge-offset-factor));
    
      align-items: center;
      background-color: var(--color-midnight);
      color: var(--color-white);
      display: flex;
      flex-direction: column;
      flex-shrink: 0;
      gap: 1.5rem;
      inline-size: var(--community-breaker-teaser-width);
      inset-block-end: 0;
      inset-inline: auto;
      justify-content: center;
      padding: var(--community-breaker-call-to-action-padding);
      position: sticky;
      scroll-snap-align: start;
      text-align: center;
      z-index: 3;
    
      @include mq($from: m) {
        border-block-start-color: var(--community-breaker-background-color, var(--color-cyan-light));
        border-block-start-style: solid;
        border-block-start-width: var(--community-breaker-call-to-action-offset);
        inline-size: calc(var(--community-breaker-teaser-width) + 1px);
        inset-block: auto;
        inset-inline-end: 1px;
        inset-inline-start: auto;
        margin-inline-start: auto;
      }
    }
    
    .community-breaker__call-to-action-icon {
      color: var(--color-orange);
      display: flex;
      font-size: var(--community-breaker-call-to-action-icon-size);
      line-height: 0;
      margin-block-end: 1rem;
      margin-block-start: calc(var(--community-breaker-call-to-action-offset) * -1 - var(--community-breaker-call-to-action-padding));
      rotate: 13deg;
    }
    
    .community-breaker__call-to-action-button {
      margin-block-start: 1rem;
    }
    
    .community-breaker__call-to-action-text {
      font-size: 1.6rem;
      line-height: var(--line-height-body);
    }
    
    .community-breaker__buttons {
      display: flex;
      flex-direction: column;
      justify-content: space-between;
      position: relative;
      row-gap: 3rem;
      z-index: 2;
    
      @include mq($from: m) {
        flex-direction: row;
        justify-content: space-between;
      }
    }
    
    .community-breaker__navigation-buttons {
      display: flex;
      flex-shrink: 0;
      gap: 2rem;
      margin-block-start: 4rem;
      margin-inline-start: auto;
    
      @include mq($until: m) {
        display: none;
      }
    }
    
    .community-breaker__button {
      margin-block-start: 4rem;
    }
    
  • URL: /components/raw/community-breaker/community-breaker.scss
  • Filesystem Path: src/components/3-organisms/community-breaker/community-breaker.scss
  • Size: 4.3 KB
  • Content:
    class CommunityBreaker {
      $communitySlider: HTMLElement;
      $communityTeaser: HTMLElement;
      $leftScrollButton: HTMLElement | null = null;
      $rightScrollButton: HTMLElement | null = null;
      enableLeftScrollButton = false;
      enableRightScrollButton = false;
    
      constructor($communitySlider: HTMLElement) {
        this.$communitySlider = $communitySlider;
    
        const $communityTeaser = this.$communitySlider.querySelector<HTMLElement>(
          '.community-breaker__teasers',
        );
    
        if (!$communityTeaser) {
          throw new Error('communityTeaser are missing');
        }
    
        this.$communityTeaser = $communityTeaser;
    
        // Update on scroll and initial load
        this.$communityTeaser.addEventListener('scroll', () => this.update(), {
          passive: true,
        });
    
        // Update on resizing of teaser-list container
        const resizeObserver = new ResizeObserver(() => this.update());
        resizeObserver.observe(this.$communityTeaser);
    
        // Init everything
        this.initScrollButtons();
        this.update();
      }
    
      initScrollButtons() {
        // Left scroll button
        this.$leftScrollButton = this.$communitySlider.querySelector(
          '.community-breaker__navigation-button--left',
        );
    
        this.$leftScrollButton?.addEventListener('click', (event) => {
          event.preventDefault();
          this.move('left');
        });
    
        // Right scroll button
        this.$rightScrollButton = this.$communitySlider.querySelector(
          '.community-breaker__navigation-button--right',
        );
    
        this.$rightScrollButton?.addEventListener('click', (event) => {
          event.preventDefault();
          this.move('right');
        });
      }
    
      move(direction: 'left' | 'right') {
        // Get first teaser
        const teaser = this.$communityTeaser.querySelector<HTMLElement>(
          '.community-breaker__teaser:nth-child(2)',
        );
    
        // Without a teaser, there is nothing to move
        if (!teaser) {
          return;
        }
    
        const { columnGap: columnGapPx } = window.getComputedStyle(
          this.$communityTeaser,
        );
    
        const columnGap = parseInt(columnGapPx, 10);
        const scrollWidth = teaser.clientWidth + columnGap;
    
        this.$communityTeaser.scrollBy({
          left: direction === 'left' ? scrollWidth * -1 : scrollWidth,
        });
      }
    
      update() {
        window.requestAnimationFrame(() => {
          this.$leftScrollButton?.toggleAttribute(
            'disabled',
            this.$communityTeaser.scrollLeft === 0,
          );
    
          this.$rightScrollButton?.toggleAttribute(
            'disabled',
            this.$communityTeaser.scrollWidth - 10 <=
              this.$communityTeaser.scrollLeft + this.$communityTeaser.offsetWidth,
          );
        });
      }
    }
    
    document
      .querySelectorAll<HTMLElement>('.community-breaker')
      .forEach(($communitySlider) => new CommunityBreaker($communitySlider));
    
    export default CommunityBreaker;
    
  • URL: /components/raw/community-breaker/community-breaker.ts
  • Filesystem Path: src/components/3-organisms/community-breaker/community-breaker.ts
  • Size: 2.8 KB

No notes defined.