Accordeon

<ul class="accordeon">
    <li class="accordeon__item">
        <div class="accordeon__item-container">
            <div class="accordeon__item-header" id="header-1">
                <h4><button type="button" aria-expanded="false" aria-controls="body-1" class="trigger button--full-width">
                        <span class="accordeon__item-icon"><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 16 16" class="icon">
                                <g>
                                    <polygon fill="currentColor" points="14.9,3.4 8,10.3 1.1,3.4 0,4.6 6.9,11.4 8,12.6 9.1,11.4 16,4.6" />
                                </g>
                            </svg>
                        </span>
                        <span>Eerste titel</span>
                    </button></h4>
            </div>
            <div class="accordeon__item-body" role="region" aria-labelledby="header-1" id="body-1">
                <p>Lorem ipsum dolor sit amet, consectetur
                    adipisicing elit. Consectetur dolores itaque quas quis voluptas! Alias debitis dolores enim et harum ipsa labore
                    molestias, nemo odit omnis quidem reiciendis repellendus voluptatibus.</p>
            </div>
        </div>
    </li>
    <li class="accordeon__item accordeon__item--show">
        <div class="accordeon__item-container">
            <div class="accordeon__item-header" id="header-2">
                <h4><button type="button" aria-expanded="true" aria-controls="body-2" class="trigger button--full-width area-expanded">
                        <span class="accordeon__item-icon"><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 16 16" class="icon">
                                <g>
                                    <polygon fill="currentColor" points="1.1,12.6 8,5.7 14.9,12.6 16,11.4 9.1,4.6 8,3.4 6.9,4.6 0,11.4" />
                                </g>
                            </svg>
                        </span>
                        <span>Tweede titel</span>
                    </button></h4>
            </div>
            <div class="accordeon__item-body open" role="region" aria-labelledby="header-2" id="body-2">
                <p>Dit is een voorbeeld van een tekst die in de accordeon
                    komt te staan. Het accordeon element levert grote hoeveelheden inhoud in een kleimne ruimte door middel van progressieve openbaarmaking.
                    Dat wil zeggen dat de gebruiker belangrijke details te zien krijgt over de onderliggende inhoud en kan ervoor kiezen om die inhoud uit te breiden
                    binnen de beperkingen van het accordeon.</p>
                <a class="button">test button</a>
            </div>
        </div>
    </li>
    <li class="accordeon__item">
        <div class="accordeon__item-container">
            <div class="accordeon__item-header" id="header-3">
                <h4><button type="button" aria-expanded="false" aria-controls="body-3" class="trigger button--full-width">
                        <span class="accordeon__item-icon"><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 16 16" class="icon">
                                <g>
                                    <polygon fill="currentColor" points="14.9,3.4 8,10.3 1.1,3.4 0,4.6 6.9,11.4 8,12.6 9.1,11.4 16,4.6" />
                                </g>
                            </svg>
                        </span>
                        <span>Derde titel</span>
                    </button></h4>
            </div>
            <div class="accordeon__item-body" role="region" aria-labelledby="header-3" id="body-3">
                <p>Lorem ipsum dolor sit amet, consectetur
                    adipisicing elit. Delectus esse ipsum nemo quo saepe. Adipisci aut eligendi eos fugit iure iusto necessitatibus
                    nostrum provident quasi quod, quos reiciendis repudiandae similique.</p>
            </div>
        </div>
    </li>
</ul>
<ul class="accordeon">
  <li class="accordeon__item">
    <div class="accordeon__item-container">
      <div class="accordeon__item-header" id="header-1">
        <h4><button type="button" aria-expanded="false" aria-controls="body-1" class="trigger button--full-width">
            <span class="accordeon__item-icon">{{> @icon--dropdown }}</span>
            <span>Eerste titel</span>
        </button></h4>
      </div>
      <div class="accordeon__item-body" role="region" aria-labelledby="header-1" id="body-1"><p>Lorem ipsum dolor sit amet, consectetur
        adipisicing elit. Consectetur dolores itaque quas quis voluptas! Alias debitis dolores enim et harum ipsa labore
        molestias, nemo odit omnis quidem reiciendis repellendus voluptatibus.</p>
      </div>
    </div>
  </li>
  <li class="accordeon__item accordeon__item--show">
    <div class="accordeon__item-container">
      <div class="accordeon__item-header" id="header-2">
        <h4><button type="button" aria-expanded="true" aria-controls="body-2" class="trigger button--full-width area-expanded">
          <span class="accordeon__item-icon">{{> @icon--pull-up  }}</span>
          <span>Tweede titel</span>
        </button></h4>
      </div>
      <div class="accordeon__item-body open" role="region" aria-labelledby="header-2" id="body-2"><p>Dit is een voorbeeld van een tekst die in de accordeon
        komt te staan. Het accordeon element levert grote hoeveelheden inhoud in een kleimne ruimte door middel van progressieve openbaarmaking.
        Dat wil zeggen dat de gebruiker belangrijke details te zien krijgt over de onderliggende inhoud en kan ervoor kiezen om die inhoud uit te breiden
        binnen de beperkingen van het accordeon.</p>
        <a class="button">test button</a>
      </div>
    </div>
  </li>
  <li class="accordeon__item">
    <div class="accordeon__item-container">
      <div class="accordeon__item-header" id="header-3">
        <h4><button type="button" aria-expanded="false" aria-controls="body-3" class="trigger button--full-width">
          <span class="accordeon__item-icon">{{> @icon--dropdown }}</span>
          <span>Derde titel</span>
        </button></h4>
      </div>
      <div class="accordeon__item-body" role="region" aria-labelledby="header-3" id="body-3"><p>Lorem ipsum dolor sit amet, consectetur
        adipisicing elit. Delectus esse ipsum nemo quo saepe. Adipisci aut eligendi eos fugit iure iusto necessitatibus
        nostrum provident quasi quod, quos reiciendis repudiandae similique.</p>
      </div>
    </div>
  </li>
</ul>
/* No context defined for this component. */
  • Content:
    $offset : 2px;
    
    .accordeon {
    
      $parent: &;
      list-style: none;
      padding: 0;
      margin: 0;
    
      ul {
        list-style: disc;
      }
    
      li {
        margin-bottom: $space-s;
      }
    
      p:empty:before {
        content: ' ';
        white-space: pre;
      }
    
      &__item {
        &:first-child .button {
          border-width: $offset;
        }
    
        &--show {
    
          #{$parent}__item-header .trigger {
            border-width: $offset;
          }
    
          #{$parent}__item-body {
            border: $border;
            border-top: transparent;
          }
    
          .icon {
            color: $grey-dark;
          }
        }
    
        &-header {
          h3,
          h4 {
            margin: 0;
          }
        }
    
        &-header .trigger,
        &-body {
          padding: calc(#{$space-xxs} * 3 - #{$offset});
          color: $grey-dark;
        }
    
        &-body {
          background-color: $white;
          max-height: 0;
          overflow: hidden;
    
          p {
            margin: calc(#{$space-xxs} * 3 - #{$offset}) 0;
          }
    
          a {
            margin-bottom: calc(#{$space-xxs} * 3 - #{$offset});
          }
    
        }
    
        &-header .trigger {
          display: flex;
          background-color: $white-dark;
          font-size: 1rem;
          border: $offset solid transparent;
    
          span {
            font-weight: $fw-bold;
            font-size: $fs-up-1;
            font-family: $font-serif;
            text-align: left;
          }
        }
    
        &-header .trigger:hover {
          cursor: pointer;
        }
    
        &-header .area-expanded {
          background-color: $grey-light;
          border-bottom-color: transparent;
        }
    
        &-header .trigger:focus {
          outline: none;
          border: $offset $border-style $black;
        }
    
        &-icon {
          color: $blue;
          margin-right: $space-xs;
          margin-top: calc(#{$offset} * 2 - 1px);
        }
    
        &-body {
          padding: 0 calc(#{$space-xxs} * 3 - 1px);
        }
      }
    
      .rte_container {
        max-height: 99999px;
      }
    
      .table-responsive {
        overflow-x: hidden;
      }
    }
    
    .button--full-width {
      width: 100%;
    }
    
    .accordeon-icon {
      width: 1em;
      height: 1em;
      font-size: 1em;
      fill: currentColor;
      padding: .1em;
    }
    
    .accordeon-title {
      font-weight: 700;
      font-size: 20px;
      font-family: $font-serif;
      text-align: left;
    }
    
  • URL: /components/raw/accordeon/_accordeon.scss
  • Filesystem Path: src/components/01-componenten/accordeon/_accordeon.scss
  • Size: 2.1 KB
  • Content:
    var upIcon =
      '<svg version="1.1" focusable="false"  xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 16 16" class="icon">\n' +
      "  <g>\n" +
      '    <polygon fill="currentColor" points="1.1,12.6 8,5.7 14.9,12.6 16,11.4 9.1,4.6 8,3.4 6.9,4.6 0,11.4"/>\n' +
      "  </g>\n" +
      "</svg>";
    
    var downIcon =
      '<svg version="1.1 focusable="false" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 16 16" class="icon">\n' +
      "  <g>\n" +
      '    <polygon fill="currentColor" points="14.9,3.4 8,10.3 1.1,3.4 0,4.6 6.9,11.4 8,12.6 9.1,11.4 16,4.6"/>\n' +
      "  </g>\n" +
      "</svg>";
    
    /**
     * Component
     *
     * @param {Element} element
     */
    export default function Accordeon(element) {
      /* eslint-disable */
    
      var itemElementList = element.getElementsByClassName("accordeon__item");
    
      var accordeonItemList = [];
      for (var i = 0; i < itemElementList.length; i++) {
        var accordeonElement = itemElementList[i];
    
        // Set values for item.
        var accordeonItem = {
          itemElement: accordeonElement,
          itemContainerElement: accordeonElement.querySelector(
            ".accordeon__item-container"
          ),
          buttonElement: accordeonElement.querySelector(
            ".accordeon__item-header button"
          ),
          iconElement: accordeonElement.querySelector(".accordeon__item-icon"),
          bodyElement: accordeonElement.querySelector(".accordeon__item-body"),
          expanded: false
        };
    
        // Check if initially is expanded and set accordingly.
        if (accordeonItem.buttonElement.getAttribute("aria-expanded") === "true") {
          accordeonItem.expanded = true;
        }
    
        accordeonItem.buttonElement.addEventListener(
          "click",
          toggle(accordeonItem)
        );
    
        window.onload = setMaxHeight(accordeonItem);
        accordeonItemList[i] = accordeonItem;
      }
    
      var triggers = Array.prototype.slice.call(
        document.getElementsByClassName("trigger")
      );
      var inputs = document.getElementsByClassName("accordeon__item");
      for (var i = 0; i < inputs.length; i++) {
        inputs[i].addEventListener("keydown", function(event) {
          var target = event.target;
          var key = event.which.toString();
          // Is this coming from an accordion header?
          if (target.classList.contains("trigger")) {
            // Up/ Down arrow and Control + Page Up/ Page Down keyboard operations
            // 38 = Up, 40 = Down
            if (key.match(/38|40/)) {
              var index = triggers.indexOf(target);
              var direction = key.match(/34|40/) ? 1 : -1;
              var length = triggers.length;
              var newIndex = (index + length + direction) % length;
    
              triggers[newIndex].focus();
    
              event.preventDefault();
            } else if (key.match(/35|36/)) {
              // 35 = End, 36 = Home keyboard operations
              switch (key) {
                // Go to first accordion
                case "36":
                  triggers[0].focus();
                  break;
                // Go to last accordion
                case "35":
                  triggers[triggers.length - 1].focus();
                  break;
              }
              event.preventDefault();
            }
          }
        });
      }
    }
    
    function getTransitionEndEventName() {
      var transitions = {
          "transition"      : "transitionend",
          "OTransition"     : "oTransitionEnd",
          "MozTransition"   : "transitionend",
          "WebkitTransition": "webkitTransitionEnd"
       }
      let bodyStyle = document.body.style;
      for(let transition in transitions) {
          if(bodyStyle[transition] != undefined) {
              return transitions[transition];
          }
      }
    }
    
    function toggle(item) {
      return function() {
        item.expanded = !item.expanded;
        item.buttonElement.setAttribute("aria-expanded", item.expanded);
        var transitionEndEventName = getTransitionEndEventName();
        var panel = item.bodyElement;
        panel.style.transition = "max-height 0.2s ease-out";
        if (panel.style.maxHeight) {
          panel.style.maxHeight = panel.scrollHeight + "px";
          panel.style.maxHeight = null;
          var toggle = true;
          //change maxheight to make room for resize
          panel.addEventListener(transitionEndEventName, function(){
            if (toggle) {
              item.iconElement.innerHTML = item.expanded ? upIcon : downIcon;
              item.itemElement.classList.remove("accordeon__item--show");
              item.buttonElement.classList.remove("area-expanded");
              panel.style.display = 'none';
              toggle = false;
            }
          });
        } else {
          item.iconElement.innerHTML = item.expanded ? upIcon : downIcon;
          item.itemElement.classList.add("accordeon__item--show");
          item.buttonElement.classList.add("area-expanded");
          panel.style.display = 'block';
          panel.style.maxHeight = panel.scrollHeight + "px";
          var toggle = true;
          //change maxheight to make room for resize
          panel.addEventListener(transitionEndEventName, function(){
            if (toggle) {
              panel.style.maxHeight = panel.scrollHeight * 4 + "px";
              toggle = false;
            }
          });
        }
      };
    }
    
      function setMaxHeight(item) {
          var body = item.bodyElement;
          if(body.classList.contains("open")) {
            body.style.maxHeight = body.scrollHeight + "px";
          }
      }
    
  • URL: /components/raw/accordeon/accordeon.js
  • Filesystem Path: src/components/01-componenten/accordeon/accordeon.js
  • Size: 5.2 KB

Omschrijving

Accordeon zorgt ervoor dat de gebruiker [gebruik van het component].

[Afbeelding in live omgeving]

Gedrag

Wanneer een gebruiker x doet, dan gebeurt er y.

Algemene richtlijnen

Waarvoor kun je dit component gebruiken?

Content richtlijnen

Zijn er specifieke content richtlijnen?

Accessibility richtlijnen

Zijn er specifieke accessibility richtlijnen?

Varianten

Variant 1: gebruik je in situatie x. Variant 2: gebruik je in situatie y. Variant 3: gebruik je in situatie z.

Changelog

Versie 0.1: component aangemaakt