Copy environment

Accordion

<div class="accordion js-accordion-group  ">
    <div class="accordion__item js-accordion is-open" id="accordion-item-1">
        <a href="#accordion-item-1" class="accordion__header js-accordion-control">
            <div class="accordion__title">Accordion item 1 <svg class="icon  accordion__header-icon">
                    <use xlink:href="../../inc/svg/global.49d3f64de1a3f5ccf16c763316702027.svg#accordion-open"></use>
                </svg>
                <svg class="icon accordion__header-icon--collapse accordion__header-icon">
                    <use xlink:href="../../inc/svg/global.49d3f64de1a3f5ccf16c763316702027.svg#accordion-collapse"></use>
                </svg>
            </div>
        </a>
        <div class="accordion__content js-accordion-content">
            <div class="accordion__inner">
                Lorem ipsum dolor sit amet, consectetur adipisicing elit. Harum quo voluptatum, accusantium exercitationem totam tempora error delectus libero commodi et. Similique vel exercitationem rerum distinctio itaque sunt voluptatibus enim sint.
            </div>
        </div>
    </div>
    <div class="accordion__item js-accordion " id="accordion-item-2">
        <a href="#accordion-item-2" class="accordion__header js-accordion-control">
            <div class="accordion__title">Accordion item 2 <svg class="icon  accordion__header-icon">
                    <use xlink:href="../../inc/svg/global.49d3f64de1a3f5ccf16c763316702027.svg#accordion-open"></use>
                </svg>
                <svg class="icon accordion__header-icon--collapse accordion__header-icon">
                    <use xlink:href="../../inc/svg/global.49d3f64de1a3f5ccf16c763316702027.svg#accordion-collapse"></use>
                </svg>
            </div>
        </a>
        <div class="accordion__content js-accordion-content">
            <div class="accordion__inner">
                Lorem ipsum dolor sit amet, consectetur adipisicing elit. Harum quo voluptatum, accusantium exercitationem totam tempora error delectus libero commodi et. Similique vel exercitationem rerum distinctio itaque sunt voluptatibus enim sint.
            </div>
        </div>
    </div>
    <div class="accordion__item js-accordion " id="accordion-item-3">
        <a href="#accordion-item-3" class="accordion__header js-accordion-control">
            <div class="accordion__title">Accordion item 3 <svg class="icon  accordion__header-icon">
                    <use xlink:href="../../inc/svg/global.49d3f64de1a3f5ccf16c763316702027.svg#accordion-open"></use>
                </svg>
                <svg class="icon accordion__header-icon--collapse accordion__header-icon">
                    <use xlink:href="../../inc/svg/global.49d3f64de1a3f5ccf16c763316702027.svg#accordion-collapse"></use>
                </svg>
            </div>
        </a>
        <div class="accordion__content js-accordion-content">
            <div class="accordion__inner">
                Lorem ipsum dolor sit amet, consectetur adipisicing elit. Harum quo voluptatum, accusantium exercitationem totam tempora error delectus libero commodi et. Similique vel exercitationem rerum distinctio itaque sunt voluptatibus enim sint.
            </div>
        </div>
    </div>
</div>
{% set iconOpen %}
    {% include '@icon' with {name: 'accordion-open', class: 'accordion__header-icon'}%}
{% endset %}
{% set iconCollapse %}
    {% include '@icon' with {name: 'accordion-collapse', class: 'accordion__header-icon', modifier: 'accordion__header-icon--collapse'}%}
{% endset %}

<div class="accordion js-accordion-group {{ modifier }} {{ class }}">
    {% if data.items %}
        {% for item in data.items %}
            <div class="accordion__item js-accordion {% if loop.first %}is-open{% endif %}" id="{{ item.id }}">
                <a href="#{{ item.id }}" class="accordion__header js-accordion-control">
                    <div class="accordion__title">{{ item.title }}{{ iconOpen }}{{ iconCollapse }}</div>
                </a>
                <div class="accordion__content js-accordion-content">
                    <div class="accordion__inner">
                        {{ item.content }}
                    </div>
                </div>
            </div>
        {% endfor %}
    {% endif %}
</div>
{
  "language": "en-US",
  "data": {
    "items": [
      {
        "id": "accordion-item-1",
        "title": "Accordion item 1",
        "content": "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Harum quo voluptatum, accusantium exercitationem totam tempora error delectus libero commodi et. Similique vel exercitationem rerum distinctio itaque sunt voluptatibus enim sint."
      },
      {
        "id": "accordion-item-2",
        "title": "Accordion item 2",
        "content": "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Harum quo voluptatum, accusantium exercitationem totam tempora error delectus libero commodi et. Similique vel exercitationem rerum distinctio itaque sunt voluptatibus enim sint."
      },
      {
        "id": "accordion-item-3",
        "title": "Accordion item 3",
        "content": "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Harum quo voluptatum, accusantium exercitationem totam tempora error delectus libero commodi et. Similique vel exercitationem rerum distinctio itaque sunt voluptatibus enim sint."
      }
    ]
  }
}
  • Content:
    .accordion {
        box-shadow: 0 1px 0 0 var(--color-brand);
        transition: $transition-duration $transition-easing;
        transition-property: box-shadow;
    }
    
    .accordion__item {
        transition: $transition-duration $transition-easing;
        transition-property: box-shadow;
        box-shadow: 0 -1px 0 0 var(--color-brand);
    }
    
    .accordion__header {
        position: relative;
        display: block;
        background: transparent;
        padding: 7px 16px;
        transition: $transition-duration $transition-easing;
        transition-property: background-color, color;
    
        @include bp(sm-min) {
            padding: 17px 32px;
        }
    
        .accordion__item:hover & {
            @media (hover: hover) {
                background-color: var(--color-brand);
                color: var(--color-text-inverse);
            }
        }
    
        .accordion &:before {
            content: none;
        }
    
        .accordion &:after {
            content: none;
        }
    }
    
    .accordion__content {
        display: none;
        transition: $transition-duration $transition-easing;
        transition-property: background-color, color;
        color: var(--color-text);
    
        html.no-js &,
        .accordion__item.is-open > & {
            display: block;
        }
    
        .accordion__item:hover & {
            @media (hover: hover) {
                background-color: var(--color-brand);
                color: var(--color-text-inverse);
            }
        }
    }
    
    .accordion__title {
        vertical-align: middle;
        line-height: 24px;
        margin-right: 28px;
    }
    
    .accordion__header-icon {
        position: absolute;
        vertical-align: middle;
        right: 16px;
        top: 0;
        bottom: 0;
        margin: auto;
        transition: $transition-duration $transition-easing;
        transition-property: fill;
        visibility: visible;
    
        .accordion__item.is-open & {
            visibility: hidden;
        }
    
        @include bp(sm-min) {
            right: 32px;
        }
    
        .accordion__item:hover & {
            @media (hover: hover) {
                fill: var(--color-text-inverse);
            }
        }
    
        &.accordion__header-icon--collapse {
            padding-top: 1px;
            visibility: hidden;
    
            .accordion__item.is-open & {
                visibility: visible;
            }
        }
    }
    
    .accordion__inner {
        padding: 7px 16px;
        opacity: .6;
    
        @include bp(sm-min) {
            padding: 17px 32px;
        }
    }
    
  • URL: /components/raw/accordion/accordion.scss
  • Filesystem Path: src/patterns/components/accordion/accordion.scss
  • Size: 2.2 KB
  • Content:
    import Helpers from '@helpers';
    
    import './accordion.scss';
    
    export enum AccordionAnimationType {
        slide,
        fadeAndSlide,
    }
    
    export enum AccordionAnimationDirection {
        in,
        out,
    }
    
    export interface IAccordionSettings {
        openClass?: string;
        accordionClass?: string;
        groupClass?: string;
        controlClass?: string;
        contentClass?: string;
        animationSlideTime?: number;
        animationFadeTime?: number;
        scrollDelay?: number;
        animationSlideEase?: string;
        animationFadeEase?: string;
        animationType?: AccordionAnimationType;
        openIcon?: string;
        closeIcon?: string;
    }
    
    export const accordionSettings: IAccordionSettings = {
        accordionClass: 'js-accordion',
        animationFadeEase: 'swing',
        animationFadeTime: 500,
        animationSlideEase: 'swing',
        animationSlideTime: 500,
        animationType: AccordionAnimationType.slide,
        closeIcon: 'accordion-open',
        contentClass: 'js-accordion-content',
        controlClass: 'js-accordion-control',
        groupClass: 'js-accordion-group',
        openClass: 'is-open',
        openIcon: 'accordion-collapse',
        scrollDelay: 500,
    };
    
    export default class Accordion {
    
        settings: IAccordionSettings;
        element: JQuery;
    
        constructor(target: HTMLElement, settings: IAccordionSettings = {}) {
            this.settings = jQuery.extend(accordionSettings, settings) as IAccordionSettings;
            this.element = $(target);
        }
    
        getAccordion(): JQuery {
            let accordion: JQuery;
    
            if (this.element.hasClass(this.settings.accordionClass)) {
                accordion = this.element.addClass(this.settings.accordionClass);
            } else {
                accordion = this.element.parents('.' + this.settings.accordionClass);
            }
    
            return accordion.length ? $(accordion.get(0)) : accordion;
        }
    
        toggle(accordion: JQuery = this.getAccordion()): void {
            if (accordion.length) {
                if (accordion.hasClass(this.settings.openClass)) {
                    this.close(accordion);
                } else {
                    this.open(accordion);
                }
            }
        }
    
        open(accordion: JQuery = this.getAccordion(), recursive: boolean = false, initialLoad: boolean = false): void {
            if (accordion && accordion.length) {
                this.closeOpen(accordion, recursive);
                const parent: JQuery = accordion.parents('.' + this.settings.accordionClass);
    
                if (parent.length) {
                    const parentAccordion: Accordion = new Accordion(parent.get(0));
    
                    parentAccordion.open(null, true, initialLoad);
                }
                accordion.addClass(this.settings.openClass);
                const content: JQuery = accordion.find('.' + this.settings.contentClass);
    
                if (content.length) {
                    if (!recursive) {
                        setTimeout((): void => {
                            if (!Helpers.isOnScreen($(content.get(0)))) {
                                Helpers.scrollToTarget(accordion);
                            }
                        }, this.settings.scrollDelay);
                    }
                }
                if (!recursive && !initialLoad) {
                    this.animate(AccordionAnimationDirection.in, accordion);
                }
            }
        }
    
        close(accordion: JQuery = this.getAccordion(), recursive: boolean = false): void {
            if (accordion.length) {
                if (!recursive) {
                    this.animate(AccordionAnimationDirection.out, accordion, (): void => {
                        accordion.removeClass(this.settings.openClass);
                    });
                } else {
                    accordion.removeClass(this.settings.openClass);
                }
            }
        }
    
        closeOpen(accordion: JQuery = this.getAccordion(), recursive: boolean = false): void {
            let group: JQuery = accordion.parents('.' + this.settings.groupClass);
    
            if (group.length) {
                group = $(group.get(0));
                const open: JQuery = group.find('> .' + this.settings.accordionClass + '.' + this.settings.openClass);
    
                open.each((index: number, element: HTMLElement): void => {
                    this.close($(element), recursive);
                });
            }
        }
    
        animate(type: AccordionAnimationDirection, accordion: JQuery = this.getAccordion(), onComplete: () => void = null): void {
            if (accordion.length) {
                let content: JQuery = accordion.find('.' + this.settings.contentClass);
                const triggerOnComplete: () => void = (): void => {
                    content.removeAttr('style');
                    if (onComplete) {
                        onComplete();
                    }
                };
    
                if (content.length) {
                    const contentHeight: string = content.get(0).offsetHeight + 'px';
    
                    content = content.length ? $(content.get(0)) : content;
                    switch (this.settings.animationType) {
                        case AccordionAnimationType.slide:
                            switch (type) {
                                case AccordionAnimationDirection.in:
                                    content.stop().css({
                                        height: 0,
                                    }).animate({
                                        height: contentHeight,
                                    }, this.settings.animationFadeTime, this.settings.animationFadeEase, triggerOnComplete);
                                    break;
                                case AccordionAnimationDirection.out:
                                    content.stop().animate({
                                        height: 0,
                                    }, this.settings.animationSlideTime, this.settings.animationSlideEase, triggerOnComplete);
                                    break;
                            }
                            break;
                        case AccordionAnimationType.fadeAndSlide:
                            switch (type) {
                                case AccordionAnimationDirection.in:
                                    content.stop().css({
                                        height: 0,
                                        opacity: 0,
                                    }).animate({
                                        height: contentHeight,
                                    }, this.settings.animationSlideTime, this.settings.animationSlideEase, (): void => {
                                        content.stop().animate({
                                            opacity: 1,
                                        }, this.settings.animationFadeTime, this.settings.animationFadeEase, triggerOnComplete);
                                    });
                                    break;
                                case AccordionAnimationDirection.out:
                                    content.stop().animate({
                                        opacity: 0,
                                    }, this.settings.animationFadeTime, this.settings.animationFadeEase, (): void => {
                                        content.stop().animate({
                                            height: 0,
                                        }, this.settings.animationSlideTime, this.settings.animationSlideEase, triggerOnComplete);
                                    });
                                    break;
                            }
                            break;
                    }
                }
            }
        }
    }
    
    function onControlClick(event: JQuery.Event): void {
        event.preventDefault();
        const accordion: Accordion = new Accordion(this);
    
        accordion.toggle();
    }
    
    const onLoadHashCheck: () => void = (): void => {
        if (window.location.hash && $(window.location.hash).length && $(window.location.hash).hasClass(accordionSettings.accordionClass)) {
            const accordion: Accordion = new Accordion($(window.location.hash).get(0));
    
            accordion.open(null, false, true);
        }
    };
    
    $((): void => {
        $(document).on('click', '.' + accordionSettings.controlClass, onControlClick);
        onLoadHashCheck();
    });
    
  • URL: /components/raw/accordion/accordion.ts
  • Filesystem Path: src/patterns/components/accordion/accordion.ts
  • Size: 8 KB
  • Handle: @accordion--default
  • Filesystem Path: src/patterns/components/accordion/accordion.twig
  • References (1): @icon
  • Referenced by (2): @detail-meta, @faq