diff --git a/gadjo/static/css/_forms.scss b/gadjo/static/css/_forms.scss index 1e4c4ea..70d5413 100644 --- a/gadjo/static/css/_forms.scss +++ b/gadjo/static/css/_forms.scss @@ -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; + } +} diff --git a/gadjo/static/js/gadjo.js b/gadjo/static/js/gadjo.js index 9233554..36daa7b 100644 --- a/gadjo/static/js/gadjo.js +++ b/gadjo/static/js/gadjo.js @@ -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;