diff --git a/bookwyrm/static/css/bookwyrm.css b/bookwyrm/static/css/bookwyrm.css index ed03aa7b1..5df456648 100644 --- a/bookwyrm/static/css/bookwyrm.css +++ b/bookwyrm/static/css/bookwyrm.css @@ -301,6 +301,159 @@ details.dropdown .dropdown-menu a:focus-visible { } } +/** Bookwyrm Tabs + ******************************************************************************/ + +.bw-tabs { + -webkit-overflow-scrolling:touch; + -webkit-touch-callout:none; + position: relative; + align-items:center; + display:flex; + font-size:1rem; + justify-content:flex-start; + overflow-x:auto; + overflow-y:hidden; + user-select:none; + white-space:nowrap +} +.bw-tabs::before { + border-bottom-color:#dbdbdb; + border-bottom-style:solid; + border-bottom-width:1px; + bottom: 0; + content:""; + position: absolute; + width: 100%; +} +.bw-tabs:not(:last-child) { + margin-bottom:1.5rem +} +.bw-tabs a { + align-items:center; + border-bottom-color:#dbdbdb; + border-bottom-style:solid; + border-bottom-width:1px; + color:#4a4a4a; + display:flex; + justify-content:center; + margin-bottom:-1px; + padding:.5em 1em; + position: relative; +} +.bw-tabs a:hover { + border-bottom-color:transparent; + color:#363636 +} +.bw-tabs a.is-active { + border-bottom-color:transparent; + color:#3273dc +} +.bw-tabs.is-left { + padding-right:.75em +} +.bw-tabs.is-center { + flex:none; + justify-content:center; + padding-left:.75em; + padding-right:.75em +} +.bw-tabs.is-right { + justify-content:flex-end; + padding-left:.75em +} +.bw-tabs .icon:first-child { + margin-right:.5em +} +.bw-tabs .icon:last-child { + margin-left:.5em +} +.bw-tabs.is-centered { + justify-content:center +} +.bw-tabs.is-right { + justify-content:flex-end +} +.bw-tabs.is-boxed a { + border:1px solid transparent; + border-radius:4px 4px 0 0 +} +.bw-tabs.is-boxed a:hover { + background-color:#f5f5f5; + border-bottom-color:#dbdbdb +} +.bw-tabs.is-boxed a.is-active { + background-color:#fff; + border-color:#dbdbdb; + border-bottom-color:#fff!important +} +.bw-tabs.is-fullwidth a { + flex-grow:1; + flex-shrink:0 +} +.bw-tabs.is-toggle a { + border-color:#dbdbdb; + border-style:solid; + border-width:1px; + margin-bottom:0; + position:relative +} +.bw-tabs.is-toggle a:hover { + background-color:#f5f5f5; + border-color:#b5b5b5; + z-index:2 +} +.bw-tabs.is-toggle a+a { + margin-left:-1px +} +.bw-tabs.is-toggle a:first-child { + border-top-left-radius:4px; + border-bottom-left-radius:4px +} +.bw-tabs.is-toggle a:last-child { + border-top-right-radius:4px; + border-bottom-right-radius:4px +} +.bw-tabs.is-toggle a.is-active { + background-color:#3273dc; + border-color:#3273dc; + color:#fff; + z-index:1 +} +.bw-tabs.is-toggle { + border-bottom:none +} +.bw-tabs.is-toggle.is-toggle-rounded a:first-child { + border-bottom-left-radius:290486px; + border-top-left-radius:290486px; + padding-left:1.25em +} +.bw-tabs.is-toggle.is-toggle-rounded a:last-child { + border-bottom-right-radius:290486px; + border-top-right-radius:290486px; + padding-right:1.25em +} +.bw-tabs.is-small { + font-size:.75rem +} +.bw-tabs.is-medium { + font-size:1.25rem +} +.bw-tabs.is-large { + font-size:1.5rem +} + +.bw-tabs.has-aside-text a { + margin-top: 1.5rem; +} + +.bw-tabs a .aside-text { + position: absolute; + top: calc(-.75rem - .75rem); + left: 0; + color: #4a4a4a; +} + /** Details panel ******************************************************************************/ diff --git a/bookwyrm/static/js/vendor/tabs.js b/bookwyrm/static/js/vendor/tabs.js index f9568b29f..0535cc869 100644 --- a/bookwyrm/static/js/vendor/tabs.js +++ b/bookwyrm/static/js/vendor/tabs.js @@ -11,17 +11,17 @@ class TabGroup { this.container = container; this.tablist = this.container.querySelector('[role="tablist"]'); - this.buttons = this.tablist.querySelectorAll('[role="tab"]'); + this.tabs = this.tablist.querySelectorAll('[role="tab"]'); this.panels = this.container.querySelectorAll(':scope > [role="tabpanel"]'); this.delay = this.determineDelay(); - if(!this.tablist || !this.buttons.length || !this.panels.length) { + if(!this.tablist || !this.tabs.length || !this.panels.length) { return; } this.keys = this.keys(); this.direction = this.direction(); - this.initButtons(); + this.initTabs(); this.initPanels(); } @@ -46,17 +46,21 @@ class TabGroup { }; } - initButtons() { + initTabs() { let count = 0; - for(let button of this.buttons) { - let isSelected = button.getAttribute("aria-selected") === "true"; - button.setAttribute("tabindex", isSelected ? "0" : "-1"); + for(let tab of this.tabs) { + let isSelected = tab.getAttribute("aria-selected") === "true"; + tab.setAttribute("tabindex", isSelected ? "0" : "-1"); - button.addEventListener('click', this.clickEventListener.bind(this)); - button.addEventListener('keydown', this.keydownEventListener.bind(this)); - button.addEventListener('keyup', this.keyupEventListener.bind(this)); + tab.addEventListener('click', this.clickEventListener.bind(this)); + tab.addEventListener('keydown', this.keydownEventListener.bind(this)); + tab.addEventListener('keyup', this.keyupEventListener.bind(this)); - button.index = count++; + if (isSelected) { + tab.scrollIntoView(); + } + + tab.index = count++; } } @@ -73,11 +77,11 @@ class TabGroup { } clickEventListener(event) { - let button = event.target.closest('a'); + let tab = event.target.closest('[role="tab"]'); event.preventDefault(); - this.activateTab(button, false); + this.activateTab(tab, false); } // Handle keydown on tabs @@ -88,12 +92,12 @@ class TabGroup { case this.keys.end: event.preventDefault(); // Activate last tab - this.activateTab(this.buttons[this.buttons.length - 1]); + this.activateTab(this.tabs[this.tabs.length - 1]); break; case this.keys.home: event.preventDefault(); // Activate first tab - this.activateTab(this.buttons[0]); + this.activateTab(this.tabs[0]); break; // Up and down are in keydown @@ -147,15 +151,15 @@ class TabGroup { switchTabOnArrowPress(event) { var pressed = event.keyCode; - for (let button of this.buttons) { - button.addEventListener('focus', this.focusEventHandler.bind(this)); + for (let tab of this.tabs) { + tab.addEventListener('focus', this.focusEventHandler.bind(this)); } if (this.direction[pressed]) { var target = event.target; if (target.index !== undefined) { - if (this.buttons[target.index + this.direction[pressed]]) { - this.buttons[target.index + this.direction[pressed]].focus(); + if (this.tabs[target.index + this.direction[pressed]]) { + this.tabs[target.index + this.direction[pressed]].focus(); } else if (pressed === this.keys.left || pressed === this.keys.up) { this.focusLastTab(); @@ -184,8 +188,8 @@ class TabGroup { // Set the tab as selected tab.setAttribute('aria-selected', 'true'); - // Give the tab parent an is-active class - tab.parentNode.classList.add('is-active'); + // Give the tab is-active class + tab.classList.add('is-active'); // Get the value of aria-controls (which is an ID) var controls = tab.getAttribute('aria-controls'); @@ -201,11 +205,11 @@ class TabGroup { // Deactivate all tabs and tab panels deactivateTabs() { - for (let button of this.buttons) { - button.parentNode.classList.remove('is-active'); - button.setAttribute('tabindex', '-1'); - button.setAttribute('aria-selected', 'false'); - button.removeEventListener('focus', this.focusEventHandler.bind(this)); + for (let tab of this.tabs) { + tab.classList.remove('is-active'); + tab.setAttribute('tabindex', '-1'); + tab.setAttribute('aria-selected', 'false'); + tab.removeEventListener('focus', this.focusEventHandler.bind(this)); } for (let panel of this.panels) { @@ -214,11 +218,11 @@ class TabGroup { } focusFirstTab() { - this.buttons[0].focus(); + this.tabs[0].focus(); } focusLastTab() { - this.buttons[this.buttons.length - 1].focus(); + this.tabs[this.tabs.length - 1].focus(); } // Determine whether there should be a delay diff --git a/bookwyrm/templates/discover/large-book.html b/bookwyrm/templates/discover/large-book.html index a6ff0aca0..d227502e2 100644 --- a/bookwyrm/templates/discover/large-book.html +++ b/bookwyrm/templates/discover/large-book.html @@ -30,7 +30,7 @@
+