general: add support for tabs (#63293)

This commit is contained in:
Frédéric Péters 2022-03-26 17:30:03 +01:00
parent f9d78b8162
commit 71361429a0
2 changed files with 118 additions and 0 deletions

View File

@ -594,3 +594,44 @@ form.pk-mark-optional-fields {
}
}
}
.pk-tabs {
display: flex;
flex-direction: row;
&--tab-list {
flex: 0;
display: flex;
justify-content: flex-start;
flex-direction: column;
background: #fafafa;
padding: 0.5em;
button {
border: 0px solid transparent;
border-left-width: 3px;
text-align: left;
font-weight: normal;
background: transparent;
width: 100%;
min-width: 10em;
margin-bottom: 1px;
color: #333;
&:focus {
outline: none;
}
&:hover {
color: inherit;
background: #eee;
}
&[aria-selected="true"] {
background: #e0e0e0;
border-left-color: $primary-color;
}
}
}
&--container {
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
}
}

View File

@ -274,6 +274,83 @@ var gadjo_js = gadjo_js || {};
return false;
}
// Tabs
// adapted from https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/Tab_Role
gadjo_js.Tabs = function(tabs_el) {
this.parent = tabs_el;
this.tabList = this.parent.querySelector('[role="tablist"]');
this.tabs = this.tabList.querySelectorAll('[role="tab"]');
this.tabpanels = this.parent.querySelectorAll('[role="tabpanel"]');
this.init();
}
gadjo_js.Tabs.prototype = {
init : function() {
const _self = this;
// Add a click event handler to each tab
this.tabs.forEach(function(tab) {
tab.addEventListener('click', function(e) {_self.selectTab.call(_self, e)});
});
// Enable arrow navigation between tabs in the tab list
let tabFocus = 0;
this.tabList.addEventListener('keydown', function(e) {
// Move up & down
if (e.key === "ArrowDown" || e.key === "ArrowUp") {
e.preventDefault();
_self.tabs[tabFocus].setAttribute('tabindex', -1);
if (e.key === "ArrowDown") {
tabFocus++;
// If we're at the end, go to the start
if (tabFocus >= _self.tabs.length) {
tabFocus = 0;
}
} else if (e.key === "ArrowUp") {
tabFocus--;
// If we're at the start, move to the end
if (tabFocus < 0) {
tabFocus = _self.tabs.length - 1;
}
}
_self.tabs[tabFocus].setAttribute('tabindex', 0);
_self.tabs[tabFocus].focus();
}
});
},
selectTab: function(e) {
const btn = e.target && e.target || e;
// Remove all current selected tabs
this.tabList
.querySelectorAll('[aria-selected="true"]')
.forEach(function(t) { t.setAttribute('aria-selected', false); });
// Set this tab as selected
btn.setAttribute('aria-selected', true);
// Hide all tab panels
this.tabpanels.forEach(function(p) { p.hidden = true });
// Show the selected panel
this.parent
.querySelector('#' + btn.getAttribute('aria-controls'))
.hidden = false;
return false;
}
}
window.addEventListener('DOMContentLoaded', function() {
$(document.querySelectorAll('.pk-tabs')).each(function(i, el) {
el.tabs = new gadjo_js.Tabs(el);
});
});
var storage = undefined;
try {
window.localStorage._gadgo_test = true;