Make opened tabs menu scrollable (#3833)
- If there are too many tabs opened to fit onto the screen, the tabs menu can be scrolled - When tabs menu is opened, scroll to the selected tab - Use margins instead of padding to that the scrollbar does not overlap with the cross button - Make sure that if the tabs menu is long, there will be a gap between it's top/bottom and the edge of the screen - On linux, screen.availTop and screen.availHeight are not always correct and the menu can go outside of what is supposed to be the available screen area. Special treatment for those edge cases
This commit is contained in:
parent
9f453b55ad
commit
adaa61f2cf
3 changed files with 61 additions and 4 deletions
|
@ -979,12 +979,62 @@ var Zotero_Tabs = new function () {
|
|||
let menuFilter = document.getElementById('zotero-tabs-menu-filter');
|
||||
menuFilter.value = "";
|
||||
this._tabsMenuFilter = "";
|
||||
this.tabsMenuList.closest("panel").style.removeProperty('max-height');
|
||||
};
|
||||
|
||||
this.handleTabsMenuShown = function (_) {
|
||||
focusTabsMenuEntry(0);
|
||||
};
|
||||
|
||||
this.handleTabsMenuShowing = function (_) {
|
||||
this.refreshTabsMenuList();
|
||||
|
||||
// Make sure that if the menu is very long, there is a small
|
||||
// gap left between the top/bottom of the menu and the edge of the screen
|
||||
let valuesAreWithinMargin = (valueOne, valueTwo, margin) => {
|
||||
return Math.abs(valueOne - valueTwo) <= margin;
|
||||
};
|
||||
let panel = document.getElementById("zotero-tabs-menu-panel");
|
||||
let panelRect = panel.getBoundingClientRect();
|
||||
const gapBeforeScreenEdge = 25;
|
||||
let absoluteTabsMenuTop = window.screenY - panelRect.height + panelRect.bottom;
|
||||
let absoluteTabsMenuBottom = window.screenY + panelRect.height + panelRect.top;
|
||||
|
||||
// On windows, getBoundingClientRect does not give us correct top and bottom values
|
||||
// until popupshown, so instead use the anchor's position
|
||||
if (Zotero.isWin) {
|
||||
let anchor = document.getElementById("zotero-tb-tabs-menu");
|
||||
let anchorRect = anchor.getBoundingClientRect();
|
||||
absoluteTabsMenuTop = window.screenY - panelRect.height + anchorRect.top;
|
||||
absoluteTabsMenuBottom = window.screenY + panelRect.height + anchorRect.bottom;
|
||||
}
|
||||
// screen.availTop is not always right on Linux, so ignore it
|
||||
let availableTop = Zotero.isLinux ? 0 : screen.availTop;
|
||||
|
||||
// Check if the end of the tabs menu is close to the edge of the screen
|
||||
let atTopScreenEdge = valuesAreWithinMargin(absoluteTabsMenuTop, availableTop, gapBeforeScreenEdge);
|
||||
let atBottomScreenEdge = valuesAreWithinMargin(absoluteTabsMenuBottom, screen.availHeight + availableTop, gapBeforeScreenEdge);
|
||||
|
||||
let gap;
|
||||
// Limit max height of the menu to leave the specified gap till the screen's edge.
|
||||
// Due to screen.availTop behavior on linux, the menu can go outside of what is supposed
|
||||
// to be the available screen area, so special treatment for those edge cases.
|
||||
if (atTopScreenEdge || (Zotero.isLinux && absoluteTabsMenuTop < 0)) {
|
||||
gap = gapBeforeScreenEdge - (absoluteTabsMenuTop - availableTop);
|
||||
}
|
||||
if (atBottomScreenEdge || (Zotero.isLinux && absoluteTabsMenuBottom > screen.availHeight)) {
|
||||
gap = gapBeforeScreenEdge - (screen.availHeight + availableTop - absoluteTabsMenuBottom);
|
||||
}
|
||||
if (gap) {
|
||||
panel.style.maxHeight = `${panelRect.height - gap}px`;
|
||||
}
|
||||
// Try to scroll selected tab into the center
|
||||
let selectedTab = this.tabsMenuList.querySelector(".selected");
|
||||
if (selectedTab) {
|
||||
selectedTab.scrollIntoView({ block: 'center' });
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Record the value of the filter
|
||||
*/
|
||||
|
|
|
@ -840,7 +840,7 @@
|
|||
<div xmlns="http://www.w3.org/1999/xhtml" class="zotero-tb-separator"></div>
|
||||
<panel id="zotero-tabs-menu-panel" type="arrow"
|
||||
onpopuphiding="Zotero_Tabs.handleTabsMenuHiding(event)"
|
||||
onpopupshowing="Zotero_Tabs.refreshTabsMenuList()"
|
||||
onpopupshowing="Zotero_Tabs.handleTabsMenuShowing(event)"
|
||||
onpopupshown="Zotero_Tabs.handleTabsMenuShown(event)"
|
||||
onkeydown="Zotero_Tabs.handleTabsMenuKeyPress(event)"
|
||||
tabindex="-1"
|
||||
|
|
|
@ -6,13 +6,16 @@
|
|||
#zotero-tabs-menu-wrapper {
|
||||
width: 350px;
|
||||
background: var(--material-sidepane);
|
||||
padding: 7px;
|
||||
padding: 0;
|
||||
border-radius: 5px;
|
||||
--width-focus-border: 2px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
#zotero-tabs-menu-filter {
|
||||
margin: 0 0 7px 0;
|
||||
margin: 7px 7px 2px 7px;
|
||||
border-radius: 5px;
|
||||
border: 1px solid transparent;
|
||||
padding-inline-start: 5px !important;
|
||||
|
@ -26,10 +29,14 @@
|
|||
#zotero-tabs-menu-list {
|
||||
appearance: none;
|
||||
margin: 0;
|
||||
overflow-x: hidden;
|
||||
overflow-y: scroll;
|
||||
scrollbar-width: thin;
|
||||
padding: 5px 0;
|
||||
|
||||
.row {
|
||||
display: flex;
|
||||
padding-inline-start: 4px;
|
||||
padding-inline: 4px;
|
||||
}
|
||||
|
||||
.zotero-tabs-menu-entry {
|
||||
|
|
Loading…
Reference in a new issue