<div class="tabs">
<ul class="tabs__list" role="tablist">
<li class="tabs__item active" role="tab" aria-selected="true" aria-controls="A" tabindex="0">Perceivable</li>
<li class="tabs__item" role="tab" aria-selected="false" aria-controls="B" tabindex="-1">Operable</li>
<li class="tabs__item" role="tab" aria-selected="false" aria-controls="C" tabindex="-1">Understandable</li>
<li class="tabs__item" role="tab" aria-selected="false" aria-controls="D" tabindex="-1">Robust</li>
</ul>
<div class="tabs__group">
<div data-panel="A" class="tabs__panel active" role="tabpanel" aria-hidden="false">A</div>
<div data-panel="B" class="tabs__panel inactive" role="tabpanel" aria-hidden="true">B</div>
<div data-panel="C" class="tabs__panel inactive" role="tabpanel" aria-hidden="true">C</div>
<div data-panel="D" class="tabs__panel inactive" role="tabpanel" aria-hidden="true">D</div>
</div>
</div>
const tabs = Array.from(document.querySelectorAll('.tabs__list > li'));
tabs.forEach(tab => tab.addEventListener('keydown', (ev) => {
ev.preventDefault();
openTabKey(tab, ev);
}));
tabs.forEach(tab => tab.addEventListener('click', (ev) => {
ev.preventDefault();
openTab(tab);
}));
const resetTabs = function (el) {
const tabs = el.getElementsByClassName('tabs__item');
for (let i = 0; i < tabs.length; i++) {
tabs[i].classList.remove('active');
tabs[i].setAttribute('aria-selected', 'false');
tabs[i].tabIndex = '-1';
}
const tabBox = el.getElementsByClassName('tabs__panel');
for (let i = 0; i < tabBox.length; i++) {
tabBox[i].classList.remove('active');
tabBox[i].setAttribute('aria-hidden', 'true');
}
};
const openTab = function (tab) {
resetTabs(tab.parentElement.parentElement);
tab.classList.add('active');
tab.setAttribute('aria-selected', 'true');
tab.tabIndex = '0';
const panel = tab.getAttribute('aria-controls');
tab.parentElement.nextElementSibling.querySelectorAll(`[data-panel='${panel}']`)[0].classList.add('active');
tab.parentElement.nextElementSibling.querySelectorAll(`[data-panel='${panel}']`)[0].setAttribute('aria-hidden', 'false');
tab.focus();
};
const openTabKey = function (tab, e) {
const key = e.which;
if (key === 37 || key === 38 || (key === 33 && key.ctrlKey)) {
const prevEl = tab.previousElementSibling;
if (prevEl) {
openTab(prevEl);
e.preventDefault();
} else {
const lastItem = tab.parentElement.lastElementChild;
openTab(lastItem);
e.preventDefault();
}
} else if (key === 39 || key === 40 || (key === 34 && key.ctrlKey)) {
const nextEl = tab.nextElementSibling;
if (nextEl) {
openTab(nextEl);
e.preventDefault();
} else {
const firstItem = tab.parentElement.firstElementChild;
openTab(firstItem);
e.preventDefault();
}
}
};
.tabs {
background-color: #eee;
border: 1px solid #ccc;
border-radius: 10px;
padding: 20px;
}
.tabs__list {
list-type: none;
margin: 0 0 0 20px;
padding: 0;
}
.tabs__list li {
background: #fff;
border: 1px solid #d9d9d9;
border-bottom: none;
border-radius: 10px 10px 0 0;
float: left;
list-style-type: none;
margin: 0 5px 0 0;
padding: 6px 9px 3px 9px;
position: relative;
top: 1px;
}
.tabs__item:hover {
cursor:pointer;
}
.tabs__item:focus {
outline: 2px solid #8cc63f;
outline-offset: 2px;
}
.tabs__item.active {
font-weight: bold;
padding: 7px 9px 4px 9px;
position: relative;
top: 1px;
}
.tabs__group {
background: #fff;
border: 1px solid #CCC;
border-radius: 10px;
box-shadow: #e8e8e8 0 0px 3px;
clear: both;
padding: 30px;
z-index: 99;
}
.tabs__panel {
display: none;
}
.tabs__panel.active {
display: block;
}
See the Pen OEmpMr by Shane Prendergast (@webknit) on CodePen.
Refs
- Tabpanel Widget - dequeuniversity.com