<div class="tabs">
<ul class="tabs__list">
<li class="tabs__label">
<a class="tabs__item" href="#section1">publications</a>
</li>
<li class="tabs__label">
<a class="tabs__item" href="#section2">videos</a>
</li>
<li class="tabs__label">
<a class="tabs__item" href="#section3">infographics</a>
</li>
</ul>
<div class="tabs__bar"></div>
<section id="section1" class="tabs__panel">
<h3 class="h3">publications</h3>
<p class="text">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam euismod, tortor nec pharetra ultricies, ante erat imperdiet velit, nec laoreet enim lacus a velit. <a href="#">Nam luctus</a>, enim in interdum condimentum, nisl diam iaculis lorem,
vel volutpat mi leo sit amet lectus. Praesent non odio bibendum magna bibendum accumsan.</p>
</section>
<section id="section2" class="tabs__panel">
<h3 class="h3">videos</h3>
<p class="text">Nullam at diam nec arcu suscipit auctor non a erat. Sed et magna semper, eleifend magna non, facilisis nisl. Proin et est et lorem dictum finibus ut nec turpis. Aenean nisi tortor, euismod a mauris a, mattis scelerisque tortor. Sed dolor risus,
varius a nibh id, condimentum lacinia est. In lacinia cursus odio a aliquam. Curabitur tortor magna, laoreet ut rhoncus at, sodales consequat tellus.</p>
</section>
<section id="section3" class="tabs__panel">
<h3 class="h3">infographics</h3>
<p class="text">Phasellus ac tristique orci. Nulla maximus <a href="">justo nec dignissim consequat</a>. Sed vehicula diam sit amet mi efficitur vehicula in in nisl. Aliquam erat volutpat. Suspendisse lorem turpis, accumsan consequat consectetur gravida, <a href="#">pellentesque ac ante</a>.
Aliquam in commodo ligula, sit amet mollis neque. Vestibulum at facilisis massa.</p>
</section>
</div>
<div class="tabs">
<ul class="tabs__list">
<li class="tabs__label">
<a class="tabs__item" href="#section1">publications</a>
</li>
<li class="tabs__label">
<a class="tabs__item" href="#section2">videos</a>
</li>
<li class="tabs__label">
<a class="tabs__item" href="#section3">infographics</a>
</li>
</ul>
<div class="tabs__bar"></div>
<section id="section1" class="tabs__panel">
<h3 class="h3">publications</h3>
<p class="text">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam euismod, tortor nec pharetra ultricies, ante erat imperdiet velit, nec laoreet enim lacus a velit. <a href="#">Nam luctus</a>, enim in interdum condimentum, nisl diam iaculis lorem, vel volutpat mi leo sit amet lectus. Praesent non odio bibendum magna bibendum accumsan.</p>
</section>
<section id="section2" class="tabs__panel">
<h3 class="h3">videos</h3>
<p class="text">Nullam at diam nec arcu suscipit auctor non a erat. Sed et magna semper, eleifend magna non, facilisis nisl. Proin et est et lorem dictum finibus ut nec turpis. Aenean nisi tortor, euismod a mauris a, mattis scelerisque tortor. Sed dolor risus, varius a nibh id, condimentum lacinia est. In lacinia cursus odio a aliquam. Curabitur tortor magna, laoreet ut rhoncus at, sodales consequat tellus.</p>
</section>
<section id="section3" class="tabs__panel">
<h3 class="h3">infographics</h3>
<p class="text">Phasellus ac tristique orci. Nulla maximus <a href="">justo nec dignissim consequat</a>. Sed vehicula diam sit amet mi efficitur vehicula in in nisl. Aliquam erat volutpat. Suspendisse lorem turpis, accumsan consequat consectetur gravida, <a href="#">pellentesque ac ante</a>. Aliquam in commodo ligula, sit amet mollis neque. Vestibulum at facilisis massa.</p>
</section>
</div>
/* No context defined for this component. */
// Necessary for tabs and accordion.
const hasClass = (element, identifier) => {
const className = identifier.replace('.', '');
const classes = (' ' + element.className + ' ').replace(/[\n\t]/g, ' ');
return classes.indexOf(' ' + className + ' ') > -1;
}
// Get wrapper element. Necessary for tabs and accordion.
const getWrapperElement = (element, identifier) => {
let parent = element.parentElement;
while (parent !== null) {
if (hasClass(parent, identifier)) {
return parent;
} else {
parent = parent.parentElement;
}
}
return null;
}
// Moves bar bellow tab
const moveBar = (tab, bar) => {
const initialSectionSize = tab.offsetWidth;
const tablist = getWrapperElement(tab, '.tabs__list');
const initialPositionBar = tablist.querySelectorAll('.tabs__label')[0].offsetLeft; // First tab.
const startSection = tab.offsetLeft - initialPositionBar;
const getStyle = (width, left, start) => (
`width: ${width}px; left: ${left}px; transition: all .5s ease-in-out; transform: translate(${start}px, 0);`
);
// Apply properties to bar
bar.setAttribute('style', getStyle(initialSectionSize, initialPositionBar, startSection));
}
// Selects tab according to URL hash and shows corresponding panel.
const selectTab = (hash) => {
let selectedTab = document.querySelector("[href='" + hash + "']");
const tabbed = document.querySelector('.tabs');
const tablist = tabbed.querySelector('.tabs__list');
const tabs = tablist.querySelectorAll('.tabs__item');
const panels = tabbed.querySelectorAll('.tabs__panel');
const bar = tabbed.querySelector('.tabs__bar');
if (selectedTab !== null) {
const showTabIndex = Array.prototype.indexOf.call(tabs, selectedTab);
tabs.forEach((element, index, array) => {
if (index == showTabIndex) {
panels[index].hidden = false;
selectedTab.focus();
selectedTab.removeAttribute('tabindex');
selectedTab.setAttribute('aria-selected', 'true');
} else {
panels[index].hidden = true;
element.removeAttribute('aria-selected');
element.setAttribute('tabindex', '-1');
}
});
moveBar(selectedTab, bar);
}
}
// Show the correct tab when accessing the URL, if it has a fragment
// identifier (the part beginning with and following the # symbol).
// The code below should run as soon as the HTML page is loaded.
//
if (location.hash) {
if (document.readyState === "complete") {
selectTab(location.hash);
} else if (document.readyState !== "loading" && !document.documentElement.doScroll) {
selectTab(location.hash);
} else {
document.addEventListener("DOMContentLoaded", () => {
selectTab(location.hash);
});
}
}
(function() {
// Get relevant elements and collections
const tabsgroup = document.querySelectorAll('.tabs');
tabsgroup.forEach(tabbed => {
const tablist = tabbed.querySelector('.tabs__list');
const tabs = tablist.querySelectorAll('.tabs__item');
const panels = tabbed.querySelectorAll('.tabs__panel');
const bar = tabbed.querySelector('.tabs__bar');
// The tab switching function
const switchTab = (oldTab, newTab) => {
newTab.focus();
// Make the active tab focusable by the user (Tab key)
newTab.removeAttribute('tabindex');
// Set the selected state
newTab.setAttribute('aria-selected', 'true');
oldTab.removeAttribute('aria-selected');
oldTab.setAttribute('tabindex', '-1');
// Get the indices of the new and old tabs to find the correct
// tab panels to show and hide
let index = Array.prototype.indexOf.call(tabs, newTab);
let oldIndex = Array.prototype.indexOf.call(tabs, oldTab);
panels[oldIndex].hidden = true;
panels[index].hidden = false;
// Move bar to the right place.
moveBar(newTab, bar);
}
// Add the tablist role to the first <ul> in the .tabbed container
tablist.setAttribute('role', 'tablist');
// Add semantics are remove user focusability for each tab
Array.prototype.forEach.call(tabs, (tab, i) => {
tab.setAttribute('role', 'tab');
tab.setAttribute('id', 'tab' + (i + 1));
tab.setAttribute('tabindex', '-1');
tab.parentNode.setAttribute('role', 'presentation');
// Handle clicking of tabs for mouse users
tab.addEventListener('click', e => {
e.preventDefault();
let currentTab = tablist.querySelector('[aria-selected]');
if (e.currentTarget !== currentTab) {
switchTab(currentTab, e.currentTarget);
}
});
// Handle keydown events for keyboard users
tab.addEventListener('keydown', e => {
// Get the index of the current tab in the tabs node list
let index = Array.prototype.indexOf.call(tabs, e.currentTarget);
// Work out which key the user is pressing and
// Calculate the new tab's index where appropriate
let dir = e.which === 37 ? index - 1 : e.which === 39 ? index + 1 : e.which === 40 ? 'down' : null;
if (dir !== null) {
e.preventDefault();
// If the down key is pressed, move focus to the open panel,
// otherwise switch to the adjacent tab
dir === 'down' ? panels[i].focus() : tabs[dir] ? switchTab(e.currentTarget, tabs[dir]) : void 0;
}
});
});
// Add tab panel semantics and hide them all
Array.prototype.forEach.call(panels, (panel, i) => {
panel.setAttribute('role', 'tabpanel');
panel.setAttribute('tabindex', '-1');
let id = panel.getAttribute('id');
panel.setAttribute('aria-labelledby', tabs[i].id);
panel.hidden = true;
});
// Initially activate the first tab and reveal the first tab panel
tabs[0].removeAttribute('tabindex');
tabs[0].setAttribute('aria-selected', 'true');
panels[0].hidden = false;
// Move bar to the first tab.
moveBar(tabs[0], bar);
})
// The tab switching function
const switchTab2 = (oldTab, newTab) => {
const tabbed = getWrapperElement(newTab, '.tabs');
const tablist = tabbed.querySelector('.tabs__list');
const tabs = tablist.querySelectorAll('.tabs__item');
const panels = tabbed.querySelectorAll('.tabs__panel');
const bar = tabbed.querySelector('.tabs__bar');
// Get the indices of the new and old tabs to find the correct
// tab panels to show and hide
let index = Array.prototype.indexOf.call(tabs, newTab);
let oldIndex = Array.prototype.indexOf.call(tabs, oldTab);
newTab.focus();
// Make the active tab focusable by the user (Tab key)
newTab.removeAttribute('tabindex');
// Set the selected state
newTab.setAttribute('aria-selected', 'true');
// Show tab.
panels[index].hidden = false;
if (index != oldIndex) {
oldTab.removeAttribute('aria-selected');
oldTab.setAttribute('tabindex', '-1');
panels[oldIndex].hidden = true;
}
moveBar(newTab, bar);
}
// Show the tab when the fragment identifier of the URL has changed
// (the part of the URL beginning with and following the # symbol).
const locationHashChanged = () => {
const currentHash = location.hash
let nextTab = document.querySelector("[href='" + currentHash + "']");
let tablist = getWrapperElement(nextTab, '.tabs__list');
let currentTab = tablist.querySelector('[aria-selected]');
if (nextTab !== null) {
switchTab2(currentTab, nextTab);
}
}
// Binds the function to the event.
if(location.hash != ""){
window.onhashchange = locationHashChanged;
}
})();
// Structure
.tabs__list {
margin: .7rem 0;
padding: 0;
display: flex;
justify-content: center;
max-width: 100vw;
}
.tabs__list [aria-selected] {
position: relative;
@include breakpoint($small-only) {
position: static;
}
}
.tabs__label {
list-style-type: none;
display: inline-block;
min-width: 150px;
text-align: center;
@include breakpoint($small-only) {
display: block;
position: static;
min-width: 100px;
font-size: 80%;
}
}
.tabs__item {
display: inline-block;
text-decoration: none;
color: inherit;
@include breakpoint($small-only) {
display: block;
position: static;
}
}
.tabs__item:focus {
outline: none;
}
.tabs__bar{
position: absolute;
height: 5px;
margin: 0;
}
// Visuals
.tabs__list {
text-transform: uppercase;
color: hsla(var(--navy-hsl), 0.3);
font-weight: bold;
letter-spacing: 0.6px;
}
.tabs__list [aria-selected] {
color: var(--color-navy);
}
.tabs__bar {
border: none;
background-color: var(--color-yellow);
}
.tabs__panel {
box-shadow: 0px 8px 32px hsla(var(--black-hsl), .15);
padding: var(--s1) 0;
outline: unset;
}
There are no notes for this item.