<div class="accordion js-accordion-group ">
<div class="accordion__item js-accordion animation__target" id="accordion-item-1">
<a href="#accordion-item-1" class="accordion__header js-accordion-control">
<h3 class="h3 accordion__title">Big mobile view multiline accordion item 1</h3>
<svg class="icon accordion__icon">
<use xlink:href="../../inc/svg/global.bc9cdd731ad718497c5d8f03d08908d4.svg#plus-36"></use>
</svg>
</a>
<div class="accordion__content js-accordion-content">
<div class="accordion__inner text">
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 animation__target" id="accordion-item-2">
<a href="#accordion-item-2" class="accordion__header js-accordion-control">
<h3 class="h3 accordion__title">Accordion item 2</h3>
<svg class="icon accordion__icon">
<use xlink:href="../../inc/svg/global.bc9cdd731ad718497c5d8f03d08908d4.svg#plus-36"></use>
</svg>
</a>
<div class="accordion__content js-accordion-content">
<div class="accordion__inner text">
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 animation__target" id="accordion-item-3">
<a href="#accordion-item-3" class="accordion__header js-accordion-control">
<h3 class="h3 accordion__title">Accordion item 3</h3>
<svg class="icon accordion__icon">
<use xlink:href="../../inc/svg/global.bc9cdd731ad718497c5d8f03d08908d4.svg#plus-36"></use>
</svg>
</a>
<div class="accordion__content js-accordion-content">
<div class="accordion__inner text">
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>
<div class="accordion js-accordion-group {{ modifier }} {{ class }}">
{% if data.items %}
{% for item in data.items %}
<div class="accordion__item js-accordion animation__target" id="{{ item.id }}">
<a href="#{{ item.id }}" class="accordion__header js-accordion-control">
<h3 class="h3 accordion__title">{{ item.title }}</h3>
{% include '@icon' with {name: 'plus-36', class: 'accordion__icon', modifier: ''} %}
</a>
<div class="accordion__content js-accordion-content">
<div class="accordion__inner text">
{{ item.content }}
</div>
</div>
</div>
{% endfor %}
{% endif %}
</div>
{
"language": "en-US",
"data": {
"items": [
{
"id": "accordion-item-1",
"title": "Big mobile view multiline 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."
}
]
}
}
.accordion {
counter-reset: accordion_counter;
}
.accordion__item {
border-top: 1px solid $color-brand-01;
transition: box-shadow $transition-duration $transition-easing-out;
box-shadow: inset 0 0 0 0 $color-brand-01, inset 0 0 0 0 $color-brand-01;
&:last-of-type {
border-bottom: 1px solid $color-brand-01;
}
&:hover {
transition: box-shadow $transition-duration $transition-easing-in;
box-shadow: inset 0 -1px 0 0 $color-brand-01, inset 0 1px 0 0 $color-brand-01;
}
}
.accordion__header {
color: $color-brand-01;
text-decoration: none;
position: relative;
display: flex;
align-items: center;
padding: 49px 52px 49px 56px;
overflow: hidden;
@include bp(sm-min) {
padding: 72px 40px 72px 112px;
}
&::before {
position: absolute;
left: 0;
top: 49px;
counter-increment: accordion_counter;
content: counter(accordion_counter, decimal-leading-zero);
font-size: $font-size-h3-xs;
font-weight: $font-weight-medium;
line-height: $line-height-h3-xs;
@include bp(sm-min) {
top: 72px;
font-size: $font-size-h3-lg;
line-height: $line-height-h3-lg;
}
}
}
.accordion__icon {
position: absolute;
right: 0;
top: 45px;
font-size: 36px;
transition-duration: $transition-duration;
transition-timing-function: $transition-easing-out;
@include bp(sm-min) {
top: 72px;
}
.accordion__item.is-open & {
transition-timing-function: $transition-easing-in;
transform: rotate(45deg);
}
}
.accordion__content {
display: none;
font-size: $font-size-small;
@include bp(sm-min) {
font-size: $font-size-base;
}
html.no-js &,
.accordion__item.is-open > & {
display: block;
}
}
.accordion__inner {
margin-left: 57px;
padding-bottom: 31px;
@include bp(sm-min) {
margin-left: 112px;
padding-bottom: 72px;
}
}
import Helpers from '../helpers/helpers';
import './accordion.scss';
export enum AccordionAnimationType {
slide,
fadeAndSlide,
}
export enum AccordionAnimationDirection {
in,
out,
}
export interface IAccordionSettings {
openClass?: string;
accordionClass?: string;
groupClass?: string;
singleOpenClass?: string;
controlClass?: string;
contentClass?: string;
animationSlideTime?: number;
animationFadeTime?: number;
scrollDelay?: number;
animationSlideEase?: string;
animationFadeEase?: string;
animationType?: AccordionAnimationType;
}
export const accordionSettings: IAccordionSettings = {
accordionClass: 'js-accordion',
animationFadeEase: 'swing',
animationFadeTime: 500,
animationSlideEase: 'swing',
animationSlideTime: 500,
animationType: AccordionAnimationType.slide,
contentClass: 'js-accordion-content',
controlClass: 'js-accordion-control',
groupClass: 'js-accordion-group',
openClass: 'is-open',
scrollDelay: 500,
singleOpenClass: 'accordion--single',
};
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 + '.' + this.settings.singleOpenClass);
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();
});
<div class="accordion js-accordion-group accordion--single ">
<div class="accordion__item js-accordion animation__target" id="accordion-item-1">
<a href="#accordion-item-1" class="accordion__header js-accordion-control">
<h3 class="h3 accordion__title">Big mobile view multiline accordion item 1</h3>
<svg class="icon accordion__icon">
<use xlink:href="../../inc/svg/global.bc9cdd731ad718497c5d8f03d08908d4.svg#plus-36"></use>
</svg>
</a>
<div class="accordion__content js-accordion-content">
<div class="accordion__inner text">
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 animation__target" id="accordion-item-2">
<a href="#accordion-item-2" class="accordion__header js-accordion-control">
<h3 class="h3 accordion__title">Accordion item 2</h3>
<svg class="icon accordion__icon">
<use xlink:href="../../inc/svg/global.bc9cdd731ad718497c5d8f03d08908d4.svg#plus-36"></use>
</svg>
</a>
<div class="accordion__content js-accordion-content">
<div class="accordion__inner text">
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 animation__target" id="accordion-item-3">
<a href="#accordion-item-3" class="accordion__header js-accordion-control">
<h3 class="h3 accordion__title">Accordion item 3</h3>
<svg class="icon accordion__icon">
<use xlink:href="../../inc/svg/global.bc9cdd731ad718497c5d8f03d08908d4.svg#plus-36"></use>
</svg>
</a>
<div class="accordion__content js-accordion-content">
<div class="accordion__inner text">
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>
<div class="accordion js-accordion-group {{ modifier }} {{ class }}">
{% if data.items %}
{% for item in data.items %}
<div class="accordion__item js-accordion animation__target" id="{{ item.id }}">
<a href="#{{ item.id }}" class="accordion__header js-accordion-control">
<h3 class="h3 accordion__title">{{ item.title }}</h3>
{% include '@icon' with {name: 'plus-36', class: 'accordion__icon', modifier: ''} %}
</a>
<div class="accordion__content js-accordion-content">
<div class="accordion__inner text">
{{ item.content }}
</div>
</div>
</div>
{% endfor %}
{% endif %}
</div>
{
"language": "en-US",
"data": {
"items": [
{
"id": "accordion-item-1",
"title": "Big mobile view multiline 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."
}
]
},
"modifier": "accordion--single"
}
.accordion {
counter-reset: accordion_counter;
}
.accordion__item {
border-top: 1px solid $color-brand-01;
transition: box-shadow $transition-duration $transition-easing-out;
box-shadow: inset 0 0 0 0 $color-brand-01, inset 0 0 0 0 $color-brand-01;
&:last-of-type {
border-bottom: 1px solid $color-brand-01;
}
&:hover {
transition: box-shadow $transition-duration $transition-easing-in;
box-shadow: inset 0 -1px 0 0 $color-brand-01, inset 0 1px 0 0 $color-brand-01;
}
}
.accordion__header {
color: $color-brand-01;
text-decoration: none;
position: relative;
display: flex;
align-items: center;
padding: 49px 52px 49px 56px;
overflow: hidden;
@include bp(sm-min) {
padding: 72px 40px 72px 112px;
}
&::before {
position: absolute;
left: 0;
top: 49px;
counter-increment: accordion_counter;
content: counter(accordion_counter, decimal-leading-zero);
font-size: $font-size-h3-xs;
font-weight: $font-weight-medium;
line-height: $line-height-h3-xs;
@include bp(sm-min) {
top: 72px;
font-size: $font-size-h3-lg;
line-height: $line-height-h3-lg;
}
}
}
.accordion__icon {
position: absolute;
right: 0;
top: 45px;
font-size: 36px;
transition-duration: $transition-duration;
transition-timing-function: $transition-easing-out;
@include bp(sm-min) {
top: 72px;
}
.accordion__item.is-open & {
transition-timing-function: $transition-easing-in;
transform: rotate(45deg);
}
}
.accordion__content {
display: none;
font-size: $font-size-small;
@include bp(sm-min) {
font-size: $font-size-base;
}
html.no-js &,
.accordion__item.is-open > & {
display: block;
}
}
.accordion__inner {
margin-left: 57px;
padding-bottom: 31px;
@include bp(sm-min) {
margin-left: 112px;
padding-bottom: 72px;
}
}
import Helpers from '../helpers/helpers';
import './accordion.scss';
export enum AccordionAnimationType {
slide,
fadeAndSlide,
}
export enum AccordionAnimationDirection {
in,
out,
}
export interface IAccordionSettings {
openClass?: string;
accordionClass?: string;
groupClass?: string;
singleOpenClass?: string;
controlClass?: string;
contentClass?: string;
animationSlideTime?: number;
animationFadeTime?: number;
scrollDelay?: number;
animationSlideEase?: string;
animationFadeEase?: string;
animationType?: AccordionAnimationType;
}
export const accordionSettings: IAccordionSettings = {
accordionClass: 'js-accordion',
animationFadeEase: 'swing',
animationFadeTime: 500,
animationSlideEase: 'swing',
animationSlideTime: 500,
animationType: AccordionAnimationType.slide,
contentClass: 'js-accordion-content',
controlClass: 'js-accordion-control',
groupClass: 'js-accordion-group',
openClass: 'is-open',
scrollDelay: 500,
singleOpenClass: 'accordion--single',
};
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 + '.' + this.settings.singleOpenClass);
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();
});