Tabs

<div class="interactive-image-tabs " role="tablist">
    <div class="interactive-image-tabs__navigation">
        <button aria-controls="panel-lorem-ipsum-dolor-sit-amet" aria-expanded="false" role="tab" class="interactive-image-tabs__button">
            Lorem ipsum dolor sit amet
            <svg class="icon interactive-image-tabs__icon" focusable="false">
                <use xlink:href="#icon-chevron-down"></use>
            </svg>
        </button>
        <button aria-controls="panel-vivamus" aria-expanded="false" role="tab" class="interactive-image-tabs__button">
            Vivamus
            <svg class="icon interactive-image-tabs__icon" focusable="false">
                <use xlink:href="#icon-chevron-down"></use>
            </svg>
        </button>
        <button aria-controls="panel-in-placerat" aria-expanded="false" role="tab" class="interactive-image-tabs__button">
            In placerat
            <svg class="icon interactive-image-tabs__icon" focusable="false">
                <use xlink:href="#icon-chevron-down"></use>
            </svg>
        </button>
        <button aria-controls="panel-in-sagittis" aria-expanded="false" role="tab" class="interactive-image-tabs__button">
            In sagittis
            <svg class="icon interactive-image-tabs__icon" focusable="false">
                <use xlink:href="#icon-chevron-down"></use>
            </svg>
        </button>
    </div>

    <div class="interactive-image-tabs__content">
        <button aria-controls="panel-lorem-ipsum-dolor-sit-amet" aria-expanded="false" role="tab" class="interactive-image-tabs__button">
            Lorem ipsum dolor sit amet
            <svg class="icon interactive-image-tabs__icon" focusable="false">
                <use xlink:href="#icon-chevron-down"></use>
            </svg>
        </button>
        <div role="tabpanel" class="interactive-image-tabs__content-item" id="panel-lorem-ipsum-dolor-sit-amet" aria-hidden="true" aria-labelledby="tab-lorem-ipsum-dolor-sit-amet">
            <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris fermentum mattis arcu at sollicitudin. Aenean quis ante bibendum, suscipit enim et, pharetra arcu. Proin eleifend laoreet est, eu fermentum leo porttitor non. Donec id ex mauris. Nam elementum tellus ante, quis tincidunt tortor volutpat ut. Etiam ut nibh eget est semper lacinia. Sed non justo eu leo dignissim consectetur pulvinar sed arcu. Etiam at metus vel turpis mattis commodo ac eu ligula. Etiam convallis mauris sem, a gravida ex finibus eu. Etiam eu pulvinar lorem, eu dictum orci. Aliquam eros sapien, commodo non nulla sed, venenatis rhoncus tortor. Aenean non ipsum id mauris fermentum rutrum. Vestibulum aliquam at eros condimentum euismod. Etiam ut lorem euismod, porttitor dui ac, maximus metus. Interdum et malesuada fames ac ante ipsum primis in faucibus.</p>
        </div>
        <button aria-controls="panel-vivamus" aria-expanded="false" role="tab" class="interactive-image-tabs__button">
            Vivamus
            <svg class="icon interactive-image-tabs__icon" focusable="false">
                <use xlink:href="#icon-chevron-down"></use>
            </svg>
        </button>
        <div role="tabpanel" class="interactive-image-tabs__content-item" id="panel-vivamus" aria-hidden="true" aria-labelledby="tab-vivamus">
            <p>Vivamus a erat risus. Suspendisse vel tortor a tortor vestibulum lacinia non blandit massa. Suspendisse potenti. Etiam odio quam, cursus feugiat pretium eu, sollicitudin ac ex. Sed imperdiet lorem leo, id elementum orci egestas in. Donec nec vestibulum augue, at feugiat metus. In mollis dictum ex, quis aliquam felis finibus ac. Donec ac varius risus. Fusce iaculis felis dolor, nec elementum ex blandit sit amet. Sed imperdiet nisl eu pharetra venenatis. In vitae malesuada quam, ac lobortis lorem. Aenean commodo dui sit amet lectus scelerisque vehicula. Ut libero mauris, porttitor sit amet metus sed, accumsan pulvinar nunc. Nulla consequat fringilla ipsum sit amet fringilla. Ut facilisis arcu in enim congue tristique.</p>
        </div>
        <button aria-controls="panel-in-placerat" aria-expanded="false" role="tab" class="interactive-image-tabs__button">
            In placerat
            <svg class="icon interactive-image-tabs__icon" focusable="false">
                <use xlink:href="#icon-chevron-down"></use>
            </svg>
        </button>
        <div role="tabpanel" class="interactive-image-tabs__content-item" id="panel-in-placerat" aria-hidden="true" aria-labelledby="tab-in-placerat">
            <p>In placerat, felis id scelerisque porttitor, risus turpis sagittis mauris, quis tincidunt lectus erat vel lorem. Aenean tincidunt ligula a justo ultricies eleifend. Vestibulum odio velit, aliquet sit amet sapien id, posuere porttitor est. Proin commodo mattis placerat. Fusce dictum diam nec augue bibendum sagittis. Suspendisse elementum lectus congue egestas tempus. Cras auctor nulla lacus, quis ullamcorper dui laoreet nec. Phasellus ac congue velit, sit amet venenatis est. Cras consequat vitae nisi nec blandit. Vestibulum ut nisl consequat, tempor turpis vel, cursus velit. Etiam sed pretium leo. Ut orci mi, dictum vitae nisi id, sagittis ornare libero. Suspendisse vel auctor sapien. Aliquam ullamcorper placerat elit.</p>
        </div>
        <button aria-controls="panel-in-sagittis" aria-expanded="false" role="tab" class="interactive-image-tabs__button">
            In sagittis
            <svg class="icon interactive-image-tabs__icon" focusable="false">
                <use xlink:href="#icon-chevron-down"></use>
            </svg>
        </button>
        <div role="tabpanel" class="interactive-image-tabs__content-item" id="panel-in-sagittis" aria-hidden="true" aria-labelledby="tab-in-sagittis">
            <p>In sagittis lacinia pulvinar. Nullam scelerisque tellus vitae urna finibus aliquam. Morbi tempor ut lectus quis lobortis. Nulla congue nisi in sapien lacinia, elementum commodo elit dapibus. Curabitur quis risus ornare, sodales enim id, sollicitudin augue. Aliquam dictum urna est, at volutpat lorem pulvinar ut. Mauris mollis vel elit ac hendrerit. Vestibulum dui ligula, consectetur nec maximus eget, finibus eget tortor. Mauris congue magna nec sapien bibendum pulvinar.</p>
        </div>
    </div>
</div>
<div class="interactive-image-tabs {{getmodifiers modifiers "interactive-image-tabs"}}" role="tablist">
    <div class="interactive-image-tabs__navigation">
        {{#each items}}
            <button aria-controls="panel-{{ id }}" aria-expanded="{{active}}" role="tab" class="interactive-image-tabs__button">
                {{ title }}
                {{> @icon id='chevron-down' additionalClasses="interactive-image-tabs__icon"}}
            </button>
        {{/each}}
    </div>

    <div class="interactive-image-tabs__content">
        {{#>@partial-block}}
            {{#each items }}
                <button aria-controls="panel-{{ id }}" aria-expanded="{{active}}" role="tab" class="interactive-image-tabs__button">
                    {{ title }}
                    {{> @icon id='chevron-down' additionalClasses="interactive-image-tabs__icon"}}
                </button>
                <div role="tabpanel" class="interactive-image-tabs__content-item" id="panel-{{ id }}" aria-hidden="{{#if active }}false{{else}}true{{/if}}" aria-labelledby="tab-{{ id }}">
                    {{#if childcomponent }}
                        {{render (getcomponent childcomponent)}}
                    {{else}}
                        {{{ body }}}
                    {{/if}}
                </div>
            {{/each}}
        {{/@partial-block}}
    </div>
</div>
{
  "items": [
    {
      "title": "Lorem ipsum dolor sit amet",
      "id": "lorem-ipsum-dolor-sit-amet",
      "active": false,
      "body": "<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris fermentum mattis arcu at sollicitudin. Aenean quis ante bibendum, suscipit enim et, pharetra arcu. Proin eleifend laoreet est, eu fermentum leo porttitor non. Donec id ex mauris. Nam elementum tellus ante, quis tincidunt tortor volutpat ut. Etiam ut nibh eget est semper lacinia. Sed non justo eu leo dignissim consectetur pulvinar sed arcu. Etiam at metus vel turpis mattis commodo ac eu ligula. Etiam convallis mauris sem, a gravida ex finibus eu. Etiam eu pulvinar lorem, eu dictum orci. Aliquam eros sapien, commodo non nulla sed, venenatis rhoncus tortor. Aenean non ipsum id mauris fermentum rutrum. Vestibulum aliquam at eros condimentum euismod. Etiam ut lorem euismod, porttitor dui ac, maximus metus. Interdum et malesuada fames ac ante ipsum primis in faucibus.</p>"
    },
    {
      "title": "Vivamus",
      "id": "vivamus",
      "active": false,
      "body": "<p>Vivamus a erat risus. Suspendisse vel tortor a tortor vestibulum lacinia non blandit massa. Suspendisse potenti. Etiam odio quam, cursus feugiat pretium eu, sollicitudin ac ex. Sed imperdiet lorem leo, id elementum orci egestas in. Donec nec vestibulum augue, at feugiat metus. In mollis dictum ex, quis aliquam felis finibus ac. Donec ac varius risus. Fusce iaculis felis dolor, nec elementum ex blandit sit amet. Sed imperdiet nisl eu pharetra venenatis. In vitae malesuada quam, ac lobortis lorem. Aenean commodo dui sit amet lectus scelerisque vehicula. Ut libero mauris, porttitor sit amet metus sed, accumsan pulvinar nunc. Nulla consequat fringilla ipsum sit amet fringilla. Ut facilisis arcu in enim congue tristique.</p>"
    },
    {
      "title": "In placerat",
      "id": "in-placerat",
      "active": false,
      "body": "<p>In placerat, felis id scelerisque porttitor, risus turpis sagittis mauris, quis tincidunt lectus erat vel lorem. Aenean tincidunt ligula a justo ultricies eleifend. Vestibulum odio velit, aliquet sit amet sapien id, posuere porttitor est. Proin commodo mattis placerat. Fusce dictum diam nec augue bibendum sagittis. Suspendisse elementum lectus congue egestas tempus. Cras auctor nulla lacus, quis ullamcorper dui laoreet nec. Phasellus ac congue velit, sit amet venenatis est. Cras consequat vitae nisi nec blandit. Vestibulum ut nisl consequat, tempor turpis vel, cursus velit. Etiam sed pretium leo. Ut orci mi, dictum vitae nisi id, sagittis ornare libero. Suspendisse vel auctor sapien. Aliquam ullamcorper placerat elit.</p>"
    },
    {
      "title": "In sagittis",
      "id": "in-sagittis",
      "active": false,
      "body": "<p>In sagittis lacinia pulvinar. Nullam scelerisque tellus vitae urna finibus aliquam. Morbi tempor ut lectus quis lobortis. Nulla congue nisi in sapien lacinia, elementum commodo elit dapibus. Curabitur quis risus ornare, sodales enim id, sollicitudin augue. Aliquam dictum urna est, at volutpat lorem pulvinar ut. Mauris mollis vel elit ac hendrerit. Vestibulum dui ligula, consectetur nec maximus eget, finibus eget tortor. Mauris congue magna nec sapien bibendum pulvinar.</p>"
    }
  ]
}
  • Content:
    import InteractiveImageTabs from './interactive-image-tabs';
    const els = document.querySelectorAll('.interactive-image-tabs');
    
    for (let el of els) {
        InteractiveImageTabs(el);
    }
    
  • URL: /components/raw/interactive-image-tabs/index.js
  • Filesystem Path: src/components/interactive-image-tabs/index.js
  • Size: 182 Bytes
  • Content:
    import { gsap } from 'gsap';
    import isInViewport from '../../functions/isInViewport';
    import isHidden from '../../functions/isHidden';
    
    const Tabs = (el) => {
        let panelIsOpen = null;
        const panels = el.querySelectorAll('.interactive-image-tabs__content-item');
        const buttons = [...panels].reduce((acc, panel) => {
            const btnGroup = Array.prototype.slice.call(document.querySelectorAll(`[aria-controls="${panel.id}"]`));
            return [
                ...acc,
                ...btnGroup
            ];
        }, []);
    
        const open = (activeId) => {
            const activePanel = document.getElementById(activeId);
            const activeButtons = [...buttons].filter((button) => button.getAttribute('aria-controls') === activeId);
            let visibleActiveButton = null;
    
            for (let button of activeButtons) {
                button.setAttribute('aria-expanded', true);
    
                if (!isHidden(button) && button.getAttribute('role') === 'tab') {
                    visibleActiveButton = button;
                }
            }
    
            activePanel.setAttribute('aria-hidden', false);
            el.classList.add('interactive-image-tabs--open');
            panelIsOpen = activePanel;
    
            if (visibleActiveButton && !isInViewport(activePanel)) {
                gsap.to(window, { duration: 0.3, scrollTo: visibleActiveButton });
            };
        };
    
        const close = () => {
            panelIsOpen = null;
            el.classList.remove('interactive-image-tabs--open');
        };
    
        const toggle = (activeId) => {
            resetTabs();
    
            if (!panelIsOpen) {
                open(activeId);
            } else {
                if (panelIsOpen.getAttribute('id') === activeId) {
                    close();
                } else {
                    open(activeId);
                }
            }
        };
    
        const resetTabs = () => {
            for (let panel of panels) {
                panel.setAttribute('aria-hidden', true);
            }
    
            for (let button of buttons) {
                button.setAttribute('aria-expanded', false);
            }
        };
    
        const addEventListeners = () => {
            for (let button of buttons) {
                button.addEventListener('click', (e) => {
                    const id = e.currentTarget.getAttribute('aria-controls');
                    toggle(id);
                });
            }
        };
    
        const init = () => {
            addEventListeners();
        };
    
        init();
    };
    
    export default Tabs;
    
  • URL: /components/raw/interactive-image-tabs/interactive-image-tabs.js
  • Filesystem Path: src/components/interactive-image-tabs/interactive-image-tabs.js
  • Size: 2.4 KB
  • Content:
    .interactive-image-tabs__navigation {
        display: flex;
        font-size: $size-16;
    }
    
    .interactive-image-tabs__button {
        position: relative;
        width: 100%;
        padding: size(2.5) size(5) size(2.5) size(2);
        background: $color-white;
        color: $color-gray-5;
        font-size: size(2);
        font-weight: $font-weight-bold;
        line-height: size(3);
        text-align: left;
        border-bottom: 1px solid $color-gray-2;
        cursor: pointer;
    
        @include breakpoint($m) {
            display: none;
        }
    
        .interactive-image-tabs__navigation & {
            display: none;
            flex: 1 1 0px;
            padding: size(3) size(5) size(3) size(2);
            border: 1px solid $color-gray-2;
            border-left: none;
    
            &:first-child {
                border-left: 1px solid $color-gray-2;
            }
    
            @include breakpoint($m) {
                display: block;
            }
    
            @include breakpoint($xl) {
                padding: size(3) size(6) size(3) size(3);
            }
        }
    
        &[aria-expanded="true"] {
            color: $color-green-dark;
            z-index: $z-promoted;
            border-bottom-color: $color-white;
    
            .theme--blue & {
                color: $color-blue-2;
            }
        }
    
        .interactive-image-tabs--open & {
            &[aria-expanded="false"] {
                background-color: $color-gray-1;
            }
        }
    }
    
    .interactive-image-tabs__content {
        background: $color-white;
        border: 1px solid $color-gray-2;
        border-bottom: none;
    
        @include breakpoint($m) {
            border-top: none;
        }
    }
    
    .interactive-image-tabs__content-item {
        display: none;
        border-bottom: 1px solid $color-gray-2;
        padding: size(2);
    
        @include breakpoint($xl) {
            padding: size(3);
        }
    
        &[aria-hidden="false"] {
            display: block;
        }
    }
    
    .interactive-image-tabs__icon {
        fill: $color-gray-5;
        position: absolute;
        top: 50%;
        right: size(2);
        width: size(2);
        height: size(2);
        transform: translateY(-50%);
    
        @include breakpoint($xl) {
            right: size(3);
            width: size(2.5);
            height: size(2.5);
        }
    
        .interactive-image-tabs__button[aria-expanded="true"] & {
            transform: translateY(-50%) rotate(180deg);
            fill: $color-green-dark;
    
            .theme--blue & {
                fill: $color-blue-2;
            }
        }
    }
    
  • URL: /components/raw/interactive-image-tabs/interactive-image.scss
  • Filesystem Path: src/components/interactive-image-tabs/interactive-image.scss
  • Size: 2.3 KB

No notes defined.