Mercurial > addons > firefox-addons > set-aside
changeset 2:49ec0da1e698
Replace tab list scroll bar with scroll buttons
author | Guido Berhoerster <guido+set-aside@berhoerster.name> |
---|---|
date | Wed, 21 Nov 2018 11:39:07 +0100 |
parents | b0827360b8e4 |
children | 48b036902118 |
files | sidebar/images/scroll-arrow.svg sidebar/js/tab-collection-manager.js sidebar/style/tab-collection-manager.css sidebar/tab-collection-manager.html |
diffstat | 4 files changed, 118 insertions(+), 4 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sidebar/images/scroll-arrow.svg Wed Nov 21 11:39:07 2018 +0100 @@ -0,0 +1,11 @@ +<!-- +Copyright (C) 2018 Guido Berhoerster <guido+set-aside@berhoerster.name> + +This Source Code Form is subject to the terms of the Mozilla Public +License, v. 2.0. If a copy of the MPL was not distributed with this +file, You can obtain one at http://mozilla.org/MPL/2.0/. +--> +<svg version="1.1" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> + <path fill="none" stroke="#0c0c0d" stroke-width="2" stroke-linecap="round" + d="m18 2l-12 10l12 10"/> +</svg>
--- a/sidebar/js/tab-collection-manager.js Mon Nov 19 17:26:17 2018 +0100 +++ b/sidebar/js/tab-collection-manager.js Wed Nov 21 11:39:07 2018 +0100 @@ -38,6 +38,8 @@ document.body.addEventListener('click', this); + window.addEventListener('optimizedResize', this); + this.isInitialized = true; } @@ -104,6 +106,7 @@ 'to tab collections'); this.tabCollectionsElement .prepend(this.createTabCollectionNode(tabCollection)); + this.handleResize(); } replaceTabCollection(tabCollection) { @@ -111,6 +114,7 @@ this.tabCollectionsElement.querySelector(`[data-tab-collection-uuid=` + `"${tabCollection.uuid}"]`) .replaceWith(this.createTabCollectionNode(tabCollection)); + this.handleResize(); } removeTabCollection(tabCollectionUuid) { @@ -158,6 +162,31 @@ this.sortTabCollections(); } + handleTabCollectionChanged(tabCollectionContainerElement) { + let tabsElement = tabCollectionContainerElement + .querySelector('.tab-collection-tabs'); + let scrollLeftElement = tabCollectionContainerElement + .querySelector('.scroll-left'); + let scrollRightElement = tabCollectionContainerElement + .querySelector('.scroll-right'); + if (tabsElement.scrollWidth > tabsElement.clientWidth) { + scrollLeftElement.classList.add('scroll-visible'); + scrollRightElement.classList.add('scroll-visible'); + } else { + scrollLeftElement.classList.remove('scroll-visible'); + scrollRightElement.classList.remove('scroll-visible'); + } + } + + handleResize() { + let tabCollectionContainerElements = + document.querySelectorAll('.tab-collection-tabs-container'); + for (let tabCollectionContainerElement of + tabCollectionContainerElements) { + this.handleTabCollectionChanged(tabCollectionContainerElement); + } + } + handleEvent(ev) { console.log('DOM event', ev); if (ev.type === 'click') { @@ -191,6 +220,19 @@ tabCollectionUuid, tabUuid }); + } else if (ev.target.classList.contains('tabs-scroll-button')) { + // scroll tab list + let tabsElement = ev.target + .closest('.tab-collection-tabs-container') + .querySelector('.tab-collection-tabs'); + if (ev.target.classList.contains('scroll-left')) { + tabsElement.scrollLeft = Math.max(tabsElement.scrollLeft - + tabsElement.clientWidth * .75, 0); + } else { + tabsElement.scrollLeft = Math.min(tabsElement.scrollLeft + + tabsElement.clientWidth * .75, + tabsElement.scrollLeftMax); + } } else { let tabItemElement = ev.target.closest('.tab-item'); if (tabItemElement !== null) { @@ -207,6 +249,9 @@ }); } } + } else if (ev.type === 'optimizedResize') { + // window has been resized + this.handleResize(); } } } @@ -219,5 +264,23 @@ return; } + function throttleResize(type, name, obj) { + obj = obj || window; + var isRunning = false; + var func = function() { + if (isRunning) { + return; + } + + isRunning = true; + requestAnimationFrame(function() { + obj.dispatchEvent(new CustomEvent(name)); + isRunning = false; + }); + }; + obj.addEventListener(type, func); + }; + throttleResize('resize', 'optimizedResize'); + tabManager = new TabManager(); });
--- a/sidebar/style/tab-collection-manager.css Mon Nov 19 17:26:17 2018 +0100 +++ b/sidebar/style/tab-collection-manager.css Wed Nov 21 11:39:07 2018 +0100 @@ -18,6 +18,14 @@ --font-size-body-20: 15px; --font-size-body-10: 13px; + --scroll-button-image-width: 24px; + --scroll-button-image-height: var(--scroll-button-image-width); + --scroll-button-padding: 4px; + --scroll-button-width: calc(2 * var(--scroll-button-padding) + + var(--scroll-button-image-width)); + --scroll-button-height: var(--scroll-button-width); + --scroll-button-highlight: var(--grey-90-a10); + --thumbnail-width: 224px; --thumbnail-height: 128px; --thumbnail-shadow: var(--box-shadow-border), 0 1px 4px var(--grey-90-a30); @@ -112,7 +120,6 @@ padding-left: 0; margin: 0; list-style: none; - overflow: auto; } .tab-collection-actions { @@ -146,8 +153,37 @@ text-decoration: underline; } +.tabs-scroll-button { + visibility: hidden; + position: absolute; + margin-top: calc(var(--remove-tab-overlap) + var(--thumbnail-height) / 2 - + var(--scroll-button-height) / 2); + width: var(--scroll-button-width); + height: var(--scroll-button-height); + background: url(../images/scroll-arrow.svg) + var(--scroll-button-padding)/var(--scroll-button-image-width) no-repeat + var(--scroll-button-highlight); + border-radius: 4px; + z-index: 999; + transition: visibility 300ms; +} + +.tab-collection-tabs-container:hover .tabs-scroll-button.scroll-visible { + visibility: visible; +} + +.tabs-scroll-button.scroll-left { + left: 0; +} + +.tabs-scroll-button.scroll-right { + transform: scaleX(-1); + right: 0; +} + .tab-collection-tabs { - margin: 4px 0 0 0; + overflow: hidden; + scroll-behavior: smooth; } .tab-item {
--- a/sidebar/tab-collection-manager.html Mon Nov 19 17:26:17 2018 +0100 +++ b/sidebar/tab-collection-manager.html Wed Nov 21 11:39:07 2018 +0100 @@ -23,8 +23,12 @@ <li><div class="restore-tab-collection" title=""></div></li> <li><div class="remove-tab-collection" title=""></div></li> </ul> - <ul class="tab-collection-tabs"> - </ul> + <div class="tab-collection-tabs-container"> + <div class="tabs-scroll-button scroll-left scroll-invisible"></div> + <div class="tabs-scroll-button scroll-right scroll-invisible"></div> + <ul class="tab-collection-tabs"> + </ul> + </div> </div> </template> <template id="tab-item-template">