<div class="rating">
    <div class="rating__text">Bewertung: 3,5/5 (16 Stimmen)</div>

    <form class="rating__form" method="post">

        <button class="rating__button rating__button--filled rating__button--half" type="submit" name="rating" value="1" title="Bewerte diese Seite mit 1 von 5 Sternen">
            <svg class="rating__icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200">
                <path class="rating__icon-fill" d="M36.2 192.5c-2.9 2.8-8.6-1-7.7-4.8 0-13.3 5.7-25.6 11.5-37L56 113.5C37.1 99.3 18.1 85 5.7 65c-1.9-2.8 1-7.6 4.8-7.6l67.5 2A438.3 438.3 0 0 0 92.3 8.8c.5-3.2 3.1-4.3 5.7-3.8h.2c2 .5 3.7 1.8 4.5 3.8a558.9 558.9 0 0 0 17.1 52.3l70.4 3.8c4.8 0 6.7 6.7 2 9.6l-54.3 41.8 22.8 72.3c2 4.7-4.7 8.6-8.5 4.7L98 146Z" />
                <path class="rating__icon-half" d="M100 5.8c-4-1.9-7.2 0-7.7 3.1A438.3 438.3 0 0 1 78 59.3l-67.5-1.9c-3.8 0-6.7 4.8-4.8 7.6 12.4 20 31.4 34.3 50.4 48.6l-16.1 37c-5.8 11.5-11.5 23.8-11.5 37.1-1 3.8 4.8 7.6 7.7 4.8L98 145.9l2-140.1Z" />
            </svg>
        </button>
        <button class="rating__button rating__button--filled rating__button--half" type="submit" name="rating" value="2" title="Bewerte diese Seite mit 2 von 5 Sternen">
            <svg class="rating__icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200">
                <path class="rating__icon-fill" d="M36.2 192.5c-2.9 2.8-8.6-1-7.7-4.8 0-13.3 5.7-25.6 11.5-37L56 113.5C37.1 99.3 18.1 85 5.7 65c-1.9-2.8 1-7.6 4.8-7.6l67.5 2A438.3 438.3 0 0 0 92.3 8.8c.5-3.2 3.1-4.3 5.7-3.8h.2c2 .5 3.7 1.8 4.5 3.8a558.9 558.9 0 0 0 17.1 52.3l70.4 3.8c4.8 0 6.7 6.7 2 9.6l-54.3 41.8 22.8 72.3c2 4.7-4.7 8.6-8.5 4.7L98 146Z" />
                <path class="rating__icon-half" d="M100 5.8c-4-1.9-7.2 0-7.7 3.1A438.3 438.3 0 0 1 78 59.3l-67.5-1.9c-3.8 0-6.7 4.8-4.8 7.6 12.4 20 31.4 34.3 50.4 48.6l-16.1 37c-5.8 11.5-11.5 23.8-11.5 37.1-1 3.8 4.8 7.6 7.7 4.8L98 145.9l2-140.1Z" />
            </svg>
        </button>
        <button class="rating__button rating__button--filled rating__button--half" type="submit" name="rating" value="3" title="Bewerte diese Seite mit 3 von 5 Sternen">
            <svg class="rating__icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200">
                <path class="rating__icon-fill" d="M36.2 192.5c-2.9 2.8-8.6-1-7.7-4.8 0-13.3 5.7-25.6 11.5-37L56 113.5C37.1 99.3 18.1 85 5.7 65c-1.9-2.8 1-7.6 4.8-7.6l67.5 2A438.3 438.3 0 0 0 92.3 8.8c.5-3.2 3.1-4.3 5.7-3.8h.2c2 .5 3.7 1.8 4.5 3.8a558.9 558.9 0 0 0 17.1 52.3l70.4 3.8c4.8 0 6.7 6.7 2 9.6l-54.3 41.8 22.8 72.3c2 4.7-4.7 8.6-8.5 4.7L98 146Z" />
                <path class="rating__icon-half" d="M100 5.8c-4-1.9-7.2 0-7.7 3.1A438.3 438.3 0 0 1 78 59.3l-67.5-1.9c-3.8 0-6.7 4.8-4.8 7.6 12.4 20 31.4 34.3 50.4 48.6l-16.1 37c-5.8 11.5-11.5 23.8-11.5 37.1-1 3.8 4.8 7.6 7.7 4.8L98 145.9l2-140.1Z" />
            </svg>
        </button>
        <button class="rating__button rating__button--half" type="submit" name="rating" value="4" title="Bewerte diese Seite mit 4 von 5 Sternen">
            <svg class="rating__icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200">
                <path class="rating__icon-fill" d="M36.2 192.5c-2.9 2.8-8.6-1-7.7-4.8 0-13.3 5.7-25.6 11.5-37L56 113.5C37.1 99.3 18.1 85 5.7 65c-1.9-2.8 1-7.6 4.8-7.6l67.5 2A438.3 438.3 0 0 0 92.3 8.8c.5-3.2 3.1-4.3 5.7-3.8h.2c2 .5 3.7 1.8 4.5 3.8a558.9 558.9 0 0 0 17.1 52.3l70.4 3.8c4.8 0 6.7 6.7 2 9.6l-54.3 41.8 22.8 72.3c2 4.7-4.7 8.6-8.5 4.7L98 146Z" />
                <path class="rating__icon-half" d="M100 5.8c-4-1.9-7.2 0-7.7 3.1A438.3 438.3 0 0 1 78 59.3l-67.5-1.9c-3.8 0-6.7 4.8-4.8 7.6 12.4 20 31.4 34.3 50.4 48.6l-16.1 37c-5.8 11.5-11.5 23.8-11.5 37.1-1 3.8 4.8 7.6 7.7 4.8L98 145.9l2-140.1Z" />
            </svg>
        </button>
        <button class="rating__button" type="submit" name="rating" value="5" title="Bewerte diese Seite mit 5 von 5 Sternen">
            <svg class="rating__icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200">
                <path class="rating__icon-fill" d="M36.2 192.5c-2.9 2.8-8.6-1-7.7-4.8 0-13.3 5.7-25.6 11.5-37L56 113.5C37.1 99.3 18.1 85 5.7 65c-1.9-2.8 1-7.6 4.8-7.6l67.5 2A438.3 438.3 0 0 0 92.3 8.8c.5-3.2 3.1-4.3 5.7-3.8h.2c2 .5 3.7 1.8 4.5 3.8a558.9 558.9 0 0 0 17.1 52.3l70.4 3.8c4.8 0 6.7 6.7 2 9.6l-54.3 41.8 22.8 72.3c2 4.7-4.7 8.6-8.5 4.7L98 146Z" />
                <path class="rating__icon-half" d="M100 5.8c-4-1.9-7.2 0-7.7 3.1A438.3 438.3 0 0 1 78 59.3l-67.5-1.9c-3.8 0-6.7 4.8-4.8 7.6 12.4 20 31.4 34.3 50.4 48.6l-16.1 37c-5.8 11.5-11.5 23.8-11.5 37.1-1 3.8 4.8 7.6 7.7 4.8L98 145.9l2-140.1Z" />
            </svg>
        </button>
    </form>

    <div class="rating__status" aria-live="assertive">Vielen Dank für deine Bewertung!</div>
</div>
{% set stars = stars ??? 5 %}
{% set rating = rating ?? 0 %}
{% set total = total ?? 0 %}
{% set disabled = disabled ?? false -%}

<div {{ html_attributes({
  id: id ?? false,
  class: 'rating',
}, attrs ?? {}) }}>
  <div class="rating__text">
    {{- 'Rating: {rating, number}/{stars, number} ({total, plural, one {1 vote} other {# votes}})' | t('site', {
      rating: rating,
      stars: stars,
      total: total,
    }) -}}
  </div>

  <form {{ html_attributes({
    class: 'rating__form',
    action: action ??? '',
    method: method ??? 'post',
  }, formAttrs ?? {}) }}>
    {{ csrf|default ? csrfInput({ autocomplete: 'false' }) }}
    {{ actionMethod|default ? actionInput(actionMethod) }}
    {{ redirectUrl|default ? redirectInput(redirectUrl) }}

    {% for name, value in hiddenInputs|default %}
      {{ value ? hiddenInput(name, value) }}
    {% endfor %}

    {% for star in range(1, stars) %}
      <button {{ html_attributes({
        class: {
          'rating__button': true,
          'rating__button--filled': rating >= star,
          'rating__button--half': rating >= (star - 0.5),
        },
        type: 'submit',
        name: name ??? 'rating',
        value: loop.index,
        disabled: disabled,
        title: not disabled ? "Rate this page with {star, number} out of {stars, number} stars" | t('site', {
          star: star,
          stars: stars,
        }),
      }) }}>
        <svg class="rating__icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200">
          <path class="rating__icon-fill" d="M36.2 192.5c-2.9 2.8-8.6-1-7.7-4.8 0-13.3 5.7-25.6 11.5-37L56 113.5C37.1 99.3 18.1 85 5.7 65c-1.9-2.8 1-7.6 4.8-7.6l67.5 2A438.3 438.3 0 0 0 92.3 8.8c.5-3.2 3.1-4.3 5.7-3.8h.2c2 .5 3.7 1.8 4.5 3.8a558.9 558.9 0 0 0 17.1 52.3l70.4 3.8c4.8 0 6.7 6.7 2 9.6l-54.3 41.8 22.8 72.3c2 4.7-4.7 8.6-8.5 4.7L98 146Z" />
          <path class="rating__icon-half" d="M100 5.8c-4-1.9-7.2 0-7.7 3.1A438.3 438.3 0 0 1 78 59.3l-67.5-1.9c-3.8 0-6.7 4.8-4.8 7.6 12.4 20 31.4 34.3 50.4 48.6l-16.1 37c-5.8 11.5-11.5 23.8-11.5 37.1-1 3.8 4.8 7.6 7.7 4.8L98 145.9l2-140.1Z" />
        </svg>
      </button>
    {% endfor %}
  </form>

  {% if status|default %}
    <div class="rating__status" aria-live="assertive">
      {{- status -}}
    </div>
  {% endif %}
</div>
{
  "rating": 3.5,
  "total": 16,
  "stars": 5,
  "status": "Vielen Dank für deine Bewertung!"
}
  • Content:
    :root {
      --rating-star-color: var(--color-orange);
      --rating-star-active-color: var(--color-midnight);
    }
    
    .rating {
      line-height: 1;
    
      &:is(.htmx-request) {
        pointer-events: none;
      }
    }
    
    .rating__text {
      margin-block-end: 1rem;
    }
    
    .rating__form {
      display: flex;
      flex-wrap: wrap;
      margin-block-start: 0.25rem;
      margin-inline-start: -0.75rem;
    }
    
    .rating__button {
      --rating-star-fill: transparent;
      --rating-star-half-fill: transparent;
      --rating-star-stroke: var(--rating-star-color);
    
      align-items: center;
      block-size: 4.5rem;
      display: flex;
      inline-size: 4.5rem;
      justify-content: center;
    
      &:is(.rating__button--filled) {
        --rating-star-fill: var(--rating-star-color);
        --rating-star-half-fill: var(--rating-star-color);
      }
    
      &:is(.rating__button--half) {
        --rating-star-half-fill: var(--rating-star-color);
      }
    
      &:is(.rating__button--active) {
        --rating-star-fill: var(--rating-star-active-color);
        --rating-star-stroke: var(--rating-star-active-color);
        --rating-star-half-fill: var(--rating-star-active-color);
      }
    }
    
    .rating__icon {
      block-size: 3rem;
      display: block;
      fill: transparent;
      inline-size: 3rem;
      overflow: visible;
    }
    
    .rating__icon-half {
      fill: var(--rating-star-half-fill);
      transition-property: fill;
    }
    
    .rating__icon-fill {
      fill: var(--rating-star-fill);
      stroke: var(--rating-star-stroke);
      stroke-width: 9.8;
      transition-property: stroke, fill;
    }
    
    .rating__status {
      font-weight: var(--font-weight-semibold);
      margin-block-start: 1rem;
    }
    
  • URL: /components/raw/rating/rating.scss
  • Filesystem Path: src/components/1-atoms/rating/rating.scss
  • Size: 1.5 KB
  • Content:
    import { on } from 'delegated-events';
    
    const TARGET = '.rating__button:not([disabled])';
    
    const onRatingButton = ($ratingButton: HTMLElement) => {
      $ratingButton.classList.add('rating__button--active');
    
      if ($ratingButton.previousElementSibling) {
        onRatingButton($ratingButton.previousElementSibling as HTMLElement);
      }
    };
    
    const offRatingButton = ($ratingButton: HTMLElement) => {
      $ratingButton.classList.remove('rating__button--active');
    
      if ($ratingButton.previousElementSibling) {
        offRatingButton($ratingButton.previousElementSibling as HTMLElement);
      }
    };
    
    on('mouseover', TARGET, (event) => {
      const { currentTarget: $ratingButton } = event;
      onRatingButton($ratingButton);
    });
    
    on('mouseout', TARGET, (event) => {
      const { currentTarget: $ratingButton } = event;
      offRatingButton($ratingButton);
    });
    
    on('focusin', TARGET, (event) => {
      const { currentTarget: $ratingButton } = event;
      onRatingButton($ratingButton);
    });
    
    on('focusout', TARGET, (event) => {
      const { currentTarget: $ratingButton } = event;
      offRatingButton($ratingButton);
    });
    
  • URL: /components/raw/rating/rating.ts
  • Filesystem Path: src/components/1-atoms/rating/rating.ts
  • Size: 1.1 KB

No notes defined.