To access options, add data-attribute to .dropdown div.
<!-- Dropdown with
data-dropdown-close-on-click,
data-dropdown-set-header,
data-close-attr
-->
<div class="dropdown" data-dropdown data-dropdown-close-on-click data-dropdown-set-header data-close-attr>
<div class="dropdown__header" data-dropdown-header>
<span class="dropdown__header-text">Dropdown</span>
</div>
<div class="dropdown__content" data-dropdown-content>
<ul class="reset-ul dropdown__content-list">
<li class="dropdown__content-list-item">
Item 1
</li>
<li class="dropdown__content-list-item">
Item 2
</li>
<li class="dropdown__content-list-item">
Item 3
</li>
</ul>
</div>
</div>
<!-- Dropdown with input checkboxes and data-close-attr -->
<div class="dropdown" data-dropdown data-close-attr>
<div class="dropdown__header" data-dropdown-header>
<span class="dropdown__header-text">Dropdown</span>
</div>
<div class="dropdown__content" data-dropdown-content>
<form>
<ul class="reset-ul dropdown__content-list">
<li class="dropdown__content-list-item">
<div class="input-element input-element--dark">
<input type="checkbox" name="checkbox" class="input-element__checkbox" id="checkbox" />
<label for="checkbox" class="input-element__label">Checkbox 1</label>
</div>
</li>
<li class="dropdown__content-list-item">
<div class="input-element input-element--dark">
<input type="checkbox" name="checkbox" class="input-element__checkbox" id="checkbox2" />
<label for="checkbox2" class="input-element__label">Checkbox 2</label>
</div>
</li>
<li class="dropdown__content-list-item">
<div class="input-element input-element--dark">
<input type="checkbox" name="checkbox" class="input-element__checkbox" id="checkbox3" />
<label for="checkbox3" class="input-element__label">Checkbox 2</label>
</div>
</li>
</ul>
</form>
</div>
</div>
<!-- Dropdown with input radio buttons and data-close-attr -->
<div class="dropdown" data-dropdown data-close-attr>
<div class="dropdown__header" data-dropdown-header>
<span class="dropdown__header-text">Dropdown</span>
</div>
<div class="dropdown__content" data-dropdown-content>
<form>
<ul class="reset-ul dropdown__content-list">
<li class="dropdown__content-list-item">
<div class="input-element input-element--dark">
<input type="radio" name="radio" class="input-element__radio" id="radio" />
<label for="radio" class="input-element__label">radio 1</label>
</div>
</li>
<li class="dropdown__content-list-item">
<div class="input-element input-element--dark">
<input type="radio" name="radio" class="input-element__radio" id="radio2" />
<label for="radio2" class="input-element__label">radio 2</label>
</div>
</li>
<li class="dropdown__content-list-item">
<div class="input-element input-element--dark">
<input type="radio" name="radio" class="input-element__radio" id="radio3" />
<label for="radio3" class="input-element__label">radio 2</label>
</div>
</li>
</ul>
</form>
</div>
</div>
// local vars
$dropdown-spacing: 2.2rem;
$icon-size: 1.1rem;
$icon-size--devices: 1.4rem;
.dropdown {
position: relative;
z-index: 2;
//header
&__header {
padding: $dropdown-spacing;
background-color: $color-gray-wild-sand;
font-weight: 600;
position: relative;
cursor: pointer;
}
&__header:after {
content: '';
position: absolute;
top: 2.5rem;
right: $dropdown-spacing;
width: $icon-size;
height: $icon-size;
background-image: url('~@/assets/images/icons/angle.svg');
background-size: 100% 100%;
transform: rotate(90deg) scale(1);
transition: transform $transition--fast;
}
&__header-text {
line-height: 1;
font-size: 1.6rem;
}
// content
&__content {
position: absolute;
background-color: $color-gray-wild-sand;
left: 0;
right: 0;
max-height: 0;
overflow: hidden;
transition: $transition--fast;
}
// content list
&__content-list {
margin: 0;
padding-left: 0;
}
&__content-list-item {
padding: 0 $dropdown-spacing;
font-size: 1.4rem;
cursor: pointer;
opacity: 0;
padding-bottom: 1.5rem;
transform: translate3d(0,-2rem,0);
transition: $transition;
&:last-child {
padding-bottom: 2.5rem
}
}
// content list loop
@for $i from 1 through 14 {
&__content-list-item:nth-child(#{$i}) {
transition-delay: $i*.04s;
}
}
}
// hover transition
.dropdown__header:hover {
&:after {
transform: rotate(90deg) scale(1.4);
}
}
// active transition
.dropdown.is-active {
.dropdown__header:hover {
&:after {
transform: rotate(-90deg) scale(1.4);
}
}
.dropdown__header:after {
transform: rotate(-90deg) scale(1);
}
.dropdown__content {
max-height: 40rem;
transition: $transition--slow;
}
.dropdown__content-list-item {
opacity: 1;
transform: translate3d(0,0,0);
}
}
// overwrite custom checkbox margin
.dropdown {
.input-element {
margin: .28rem 0;
}
}
// tablet and down
@include viewport-large {
.dropdown__header:after {
top: 2.48rem;
width: $icon-size--devices;
height: $icon-size--devices;
}
.dropdown__header-text {
line-height: 1;
font-size: 1.8rem;
}
}
export class Dropdown {
dropdownItemList: NodeList = document.querySelectorAll("[data-dropdown]");
dropdownItemListArray: HTMLElement[] = Array.prototype.slice.call(this.dropdownItemList);
dropdownItemHeaderList: NodeList = document.querySelectorAll("[data-dropdown-header]");
dropdownItemArray: HTMLElement[] = Array.prototype.slice.call(this.dropdownItemHeaderList);
dropdownItemContentList: NodeList = document.querySelectorAll("[data-dropdown-close-on-click] [data-dropdown-content]");
dropdownItemContentArray: HTMLElement[] = Array.prototype.slice.call(this.dropdownItemContentList);
dropdownItemContentSetHeaderList: NodeList = document.querySelectorAll("[data-dropdown-set-header] [data-dropdown-content] li");
dropdownItemContentSetHeaderArray: HTMLElement[] = Array.prototype.slice.call(this.dropdownItemContentSetHeaderList);
activeClass: string = 'is-active';
constructor() {
this.toggleDropdownContent()
this.onclickHandler()
this.setHeaderValue()
}
private toggleDropdownContent = () => {
this.dropdownItemArray.forEach((elem) => {
elem.addEventListener("click", () => {
if (!elem.parentElement.classList.contains(this.activeClass)) {
// add active class to clicked, and remove from other
this.removeActiveHelper();
elem.parentElement.classList.add(this.activeClass);
} else {
// toggle active class on clicked elm
elem.parentElement.classList.remove(this.activeClass);
}
});
});
}
private removeActiveHelper = () => {
// remove active class helper
this.dropdownItemListArray.forEach((test) => {
test.classList.remove(this.activeClass);
});
}
private onclickHandler = () => {
// Close dropdown, when child element is clicked
this.dropdownItemContentArray.forEach((elem) => {
elem.addEventListener("click", () => {
elem.parentElement.classList.remove(this.activeClass);
});
});
}
// set header on click
private setHeaderValue = () => {
this.dropdownItemContentSetHeaderArray.forEach((elem) => {
elem.addEventListener("click", () => {
const clickedVal = elem.innerText;
let getParent = elem.parentElement.parentElement.parentElement;
let getParentHeader = getParent.firstElementChild.firstElementChild as HTMLElement;
getParentHeader.innerText = clickedVal;
});
});
}
}
const selector = '[data-close-attr]';
const activeClass: string = 'is-active'
export class ClickHandler {
constructor() {
document.addEventListener('click', this.hideOnClickOutside)
}
private hideOnClickOutside = (e: Event) => {
if (!$(e.target).closest(selector).length) {
if ($(selector).is(':visible')) {
$(selector).removeClass(activeClass);
}
}
}
}