Europa Component Library

Expandables

When and how to use this component

If you need to present a lot of content on a page, it can be divided into sub-sections in a structured way.

When to use this component

  • when you have a large amount of information

Do not use this component

  • as a rule avoid hiding information as much as possible

Implementation

In order to automatically attach event listeners on your expandables, add the following script to your page:

document.addEventListener('DOMContentLoaded', function() {
  ECL.initExpandables();
});

Change button label when the component is collapsed/expanded

You can attach data-label-expanded and data-label-collapsed attributes to your button. The button label will be updated dynamically according to these values. Check the first example for more information.

Resources

{#
  The following snippets are examples.
  The template should not be reused direclty.
#}

<!-- Button collapse -->

<div style="margin-top:1rem">
  {% include '@ec-europa/ecl-buttons' with {
    'label': 'What is this all about?',
    'extra_classes': 'ecl-expandable__button',
    'extra_attributes': [
      { 'name': 'aria-controls', 'value': 'example-expandable-1'},
      { 'name': 'aria-expanded', 'value': 'false'},
      { 'name': 'data-label-expanded', 'value': 'Hide me'},
      { 'name': 'data-label-collapsed', 'value': 'What is this all about?'},
      { 'name': 'id', 'value': 'example-expandable-button-1' },
      { 'name': 'type', 'value': 'button'},
    ]
  } %}
  <div
    aria-hidden="true"
    aria-labelledby="example-expandable-button-1"
    id="example-expandable-1"
  >
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
    <p>Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat...</p>
  </div>
</div>

<!-- Expandable link -->

<div style="margin-top:1rem">
  <a
    aria-controls="example-expandable-2"
    aria-expanded="false"
    class="ecl-link ecl-expandable__button"
    href="#"
    id="example-expandable-button-2"
  >
    Expandable link
  </a>
  <div
    aria-hidden="true"
    aria-labelledby="example-expandable-button-2"
    id="example-expandable-2"
  >
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
    <p>Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat...</p>
  </div>
</div>
{
  "_demo": {
    "scripts": "document.addEventListener('DOMContentLoaded', function () { ECL.initExpandables(); });"
  }
}
<!-- Button collapse -->

<div style="margin-top:1rem">

  <button class="ecl-button ecl-button--default ecl-expandable__button" aria-controls="example-expandable-1" aria-expanded="false" data-label-expanded="Hide me" data-label-collapsed="What is this all about?" id="example-expandable-button-1" type="button">What is this all about?</button>
  <div aria-hidden="true" aria-labelledby="example-expandable-button-1" id="example-expandable-1">
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
    <p>Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat...</p>
  </div>
</div>

<!-- Expandable link -->

<div style="margin-top:1rem">
  <a aria-controls="example-expandable-2" aria-expanded="false" class="ecl-link ecl-expandable__button" href="#" id="example-expandable-button-2">
    Expandable link
  </a>
  <div aria-hidden="true" aria-labelledby="example-expandable-button-2" id="example-expandable-2">
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
    <p>Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat...</p>
  </div>
</div>
  • Content:
    /**
     * ECL Expandable
     * @define expandable
     */
    
    .ecl-expandable__button {
      &::after {
        @extend %ecl-icon--after;
    
        @include ecl-button--caret();
      }
    
      &[aria-expanded='false']::after {
        @include ecl-icon('down');
      }
    
      &[aria-expanded='true']::after {
        @include ecl-icon('up');
      }
    }
    
  • URL: /components/raw/ecl-expandables/_expandables.scss
  • Filesystem Path: framework/components/ecl-expandables/_expandables.scss
  • Size: 300 Bytes
  • Content:
    /* eslint-disable no-param-reassign */
    
    export const toggleExpandable = (
      toggleElement,
      {
        context = document,
        forceClose = false,
        closeSiblings = false,
        siblingsSelector = '[aria-controls][aria-expanded]',
      } = {}
    ) => {
      if (!toggleElement) {
        return;
      }
    
      // Get target element
      const target = document.getElementById(
        toggleElement.getAttribute('aria-controls')
      );
    
      // Exit if no target found
      if (!target) {
        return;
      }
    
      // Get current status
      const isExpanded =
        forceClose === true ||
        toggleElement.getAttribute('aria-expanded') === 'true';
    
      // Toggle the expandable/collapsible
      toggleElement.setAttribute('aria-expanded', !isExpanded);
      target.setAttribute('aria-hidden', isExpanded);
    
      // Toggle label if possible
      if (!isExpanded && toggleElement.hasAttribute('data-label-expanded')) {
        toggleElement.innerHTML = toggleElement.getAttribute('data-label-expanded');
      } else if (isExpanded && toggleElement.hasAttribute('data-label-collapsed')) {
        toggleElement.innerHTML = toggleElement.getAttribute(
          'data-label-collapsed'
        );
      }
    
      // Close siblings if requested
      if (closeSiblings === true) {
        const siblingsArray = Array.prototype.slice
          .call(context.querySelectorAll(siblingsSelector))
          .filter(sibling => sibling !== toggleElement);
    
        siblingsArray.forEach(sibling => {
          toggleExpandable(sibling, {
            context,
            forceClose: true,
          });
        });
      }
    };
    
    // Helper method to automatically attach the event listener to all the expandables on page load
    export const initExpandables = (
      selector = '[aria-controls][aria-expanded]',
      context = document
    ) => {
      const nodesArray = Array.prototype.slice.call(
        context.querySelectorAll(selector)
      );
    
      nodesArray.forEach(node =>
        node.addEventListener('click', e => {
          toggleExpandable(node, { context });
          e.preventDefault();
        })
      );
    };
    
  • URL: /components/raw/ecl-expandables/expandables.js
  • Filesystem Path: framework/components/ecl-expandables/expandables.js
  • Size: 1.9 KB
  • Handle: @ec-europa/ecl-expandables
  • Tags: molecule
  • Preview:
  • Filesystem Path: framework/components/ecl-expandables/ecl-expandables.twig