Skip to content

Disclosure Card13.10.5

A Disclosure Card is used for cards with expandable content.


$ npm i @if-design-system/disclosure-card@13.10.5

Edit this section

Overview

There is currently no documentation for this section yet.
Contact the Design System team for questions.

If you want to contribute, you can also add the documentation yourself!

Edit this section

Usage

There is currently no documentation for this section yet.
Contact the Design System team for questions.

If you want to contribute, you can also add the documentation yourself!

Edit this section

Behaviours

Interactions

Toggle

Hover

Focus

Focus

3px outline with 1px offset and color BL 1, BLUE Complement, a direct complement color of BL 1, BLUE.

Modifiers

All Disclose Card containers , .cards.disclosures, can be modified with the classes one, two or three for a desired layout.

<ul class="if cards.disclosures [one|two|three]" role="presentation"></ul>
Edit this section

Accessibility

When using the disclosure cards, it is important to add and update the required accessibility attributes.

For the container, you need to add role="presentation", since the list is not used as a list.

<ul  role="presentation"></ul>

For the list item, you need to add role="presentation", since the list item is not used as a list item.

<li class="if" role="presentation"></li>

For the button, you need to add the required aria-*-attributes:

  • aria-haspopup="true" to indicate that this control has an expandable
  • aria-expanded="false" to indicate if the disclosure card is open or not
  • aria-controls="<id to expandable content>" to indicate what the button controls
  • aria-labelledby="<id to text to label>" OR aria-label="<relevant label>"
<button
  aria-haspopup="true"
  aria-expanded="false"
  aria-controls="expandable-content-16"
  aria-labelledby="expandable-text-16"
  class="if disclosure-card"
  type="button"
></button>
Edit this section

Anatomy

Disclosure Card
  1. Button
  2. Image
  3. Title
  4. Text
Edit this section

Specs

Edit this section

Implementation

<ul class="if cards disclosures" role="presentation">
  <li class="if" role="presentation">
    <button
      aria-haspopup="true"
      aria-expanded="false"
      aria-controls="expandable-content-16"
      aria-labelledby="expandable-text-16"
      class="if disclosure-card"
      type="button"
    >
      <img class="if image" src="/images/travel.png" />
      <p id="expandable-text-16" class="if text body">Reseforsäkring</p>
      <p class="if expandable text meta">Dölj reseförsäkringar</p>
    </button>
    <div tabindex="-1" id="expandable-content-16" class="if block expandable"></div>
  </li>
  <li class="if" role="presentation"></li>
  <li class="if" role="presentation"></li>
</ul>

JavaScript Implementation Example

const getElementCSSStyle = el => (window.getComputedStyle ? getComputedStyle(el, null) : el.currentStyle);

const toggleExpandableBlock = disclosureCard => {
  const isOpen = disclosureCard.classList.contains('is-expanded');
  const blockToBeExpanded = disclosureCard.parentElement.querySelector('.if.disclosure-card + .if.block.expandable');
  if (blockToBeExpanded) {
    const parentElement = disclosureCard.parentElement;
    const parentBlock = disclosureCard.closest('.if.block');
    const disclosureCardElementRect = disclosureCard.getBoundingClientRect();

    if (isOpen) {
      disclosureCard.classList.remove('is-expanded');
      blockToBeExpanded.classList.remove('is-expanded');
      blockToBeExpanded.style.top = null;
      blockToBeExpanded.style.left = null;
      parentBlock.style.height = null;
      document.querySelectorAll('.if.block.hidden.fake').forEach(fakeBlock => {
        fakeBlock.remove();
      });
    } else {
      document.querySelectorAll('.if.block.hidden.fake').forEach(fakeBlock => {
        fakeBlock.remove();
      });
      const createFakeBlockForBackgroundColorFix = document.createElement('div');
      createFakeBlockForBackgroundColorFix.classList.add('if');
      createFakeBlockForBackgroundColorFix.classList.add('block');
      createFakeBlockForBackgroundColorFix.classList.add('hidden');
      createFakeBlockForBackgroundColorFix.classList.add('fake');
      parentBlock.insertAdjacentElement('afterend', createFakeBlockForBackgroundColorFix);
      document.querySelectorAll('.if.disclosure-card.is-expanded').forEach(disclosureCardExpandable => {
        disclosureCardExpandable.classList.remove('is-expanded');
        disclosureCardExpandable.closest('.if.block').style.height = null;
      });
      document.querySelectorAll('.if.block.expandable.is-expanded').forEach(blockExpandable => {
        blockExpandable.classList.remove('is-expanded');
        blockExpandable.style.top = null;
        blockExpandable.style.left = null;
      });
      blockToBeExpanded.classList.add('is-expanded');
      disclosureCard.classList.add('is-expanded');
      const blockToBeExpandedRect = blockToBeExpanded.getBoundingClientRect();
      const parentElementStyle = getElementCSSStyle(parentElement);
      const parentElementRect = parentElement.getBoundingClientRect();
      const parentElementViewportLeft = parentElementRect.left;

      const parentBlockStyle = getElementCSSStyle(parentBlock);
      const parentBlockRect = parentBlock.getBoundingClientRect();

      const bodyRect = document.querySelector('body').getBoundingClientRect();

      const expandedBlockWidth = parentBlockRect.width >= bodyRect.width ? bodyRect.width : parentBlockRect.width;

      const expandedOffsetLeft =
        parentBlockRect.width >= bodyRect.width
          ? parentElementViewportLeft
          : parentElementViewportLeft - parentBlockRect.left;

      Object.assign(blockToBeExpanded.style, {
        width: `${expandedBlockWidth}px`,
        top: `${disclosureCardElementRect.height -
          parseInt(parentElementStyle.marginTop, 10) +
          parseInt(parentBlockStyle.paddingBottom, 10)}px`,
        left: `-${expandedOffsetLeft}px`
      });

      Object.assign(parentBlock.style, {
        // - border-top of blockToBeExpanded
        height: `calc(${parentBlockRect.height + blockToBeExpandedRect.height}px - 2pt)`
      });
    }
  }
};

const init = () => {
  document.querySelectorAll('.if.disclosure-card').forEach(disclosureCard => {
    document.querySelectorAll('.if.block.hidden.fake').forEach(fakeBlock => {
      fakeBlock.remove();
    });
    disclosureCard.removeEventListener('click', () => {
      toggleExpandableBlock(disclosureCard);
    });
    disclosureCard.addEventListener('click', () => {
      toggleExpandableBlock(disclosureCard);
    });
  });
};

init();
Edit this section

Contact us