Implement new pane selection algorithm, remove bottom padding
This commit is contained in:
parent
cc9d58e6be
commit
19b78e2b20
18 changed files with 427 additions and 121 deletions
|
@ -255,13 +255,6 @@ treechildren::-moz-tree-image {
|
|||
list-style-image: url('chrome://zotero/skin/mac/toolbar-note-add.png');
|
||||
}
|
||||
|
||||
/* Hide icons on macOS. We use :is() to work around weird behavior in Fx101 where a regular child
|
||||
selector doesn't match the first time the menu is opened. */
|
||||
:is(#zotero-collectionmenu, #zotero-itemmenu) > :is(.menuitem-iconic, .menu-iconic) {
|
||||
list-style-image: none !important;
|
||||
}
|
||||
|
||||
|
||||
/* BEGIN 2X BLOCK -- DO NOT EDIT MANUALLY -- USE 2XIZE */
|
||||
@media (min-resolution: 1.25dppx) {
|
||||
.zotero-tb-button,.zotero-tb-button:first-child,.zotero-tb-button:last-child { background: url("chrome://zotero/skin/mac/menubutton-end@2x.png") right center/auto 24px no-repeat; }
|
||||
|
|
|
@ -47,9 +47,10 @@
|
|||
let open = this.open;
|
||||
if (open === val || this.empty) return;
|
||||
this.render();
|
||||
let openHeight = this._head?.nextSibling?.scrollHeight;
|
||||
if (openHeight) {
|
||||
this.style.setProperty('--open-height', `${openHeight}px`);
|
||||
if (this._head?.nextSibling
|
||||
&& this._head.nextSibling.getBoundingClientRect().height
|
||||
&& this._head.nextSibling.scrollHeight) {
|
||||
this.style.setProperty('--open-height', `${this._head.nextSibling.scrollHeight}px`);
|
||||
}
|
||||
else {
|
||||
this.style.setProperty('--open-height', 'auto');
|
||||
|
@ -80,7 +81,9 @@
|
|||
|
||||
setCount(count) {
|
||||
this.setAttribute('data-l10n-args', JSON.stringify({ count }));
|
||||
this.empty = !count;
|
||||
this._runWithTransitionsDisabled(() => {
|
||||
this.empty = !count;
|
||||
});
|
||||
}
|
||||
|
||||
get label() {
|
||||
|
@ -119,6 +122,7 @@
|
|||
this._head.className = 'head';
|
||||
this._head.addEventListener('click', this._handleClick);
|
||||
this._head.addEventListener('keydown', this._handleKeyDown);
|
||||
this._head.addEventListener('contextmenu', this._handleContextMenu);
|
||||
|
||||
this._title = document.createElement('span');
|
||||
this._title.className = 'title';
|
||||
|
@ -131,13 +135,21 @@
|
|||
});
|
||||
this._head.append(this._addButton);
|
||||
|
||||
this._contextMenu = this._buildContextMenu();
|
||||
let popupset = document.createXULElement('popupset');
|
||||
popupset.append(this._contextMenu);
|
||||
this._head.append(popupset);
|
||||
|
||||
let twisty = document.createXULElement('toolbarbutton');
|
||||
twisty.className = 'twisty';
|
||||
this._head.append(twisty);
|
||||
|
||||
this.prepend(this._head);
|
||||
this._restoreOpenState();
|
||||
this.render();
|
||||
|
||||
this._runWithTransitionsDisabled(() => {
|
||||
this._restoreOpenState();
|
||||
this.render();
|
||||
});
|
||||
|
||||
this._notifierID = Zotero.Prefs.registerObserver(`panes.${this.dataset.pane}.open`, this._restoreOpenState.bind(this));
|
||||
|
||||
|
@ -146,9 +158,79 @@
|
|||
}
|
||||
}
|
||||
|
||||
_buildContextMenu() {
|
||||
let containerRoot = this.closest('.zotero-view-item-container');
|
||||
|
||||
let contextMenu = document.createXULElement('menupopup');
|
||||
let collapseOtherSections = document.createXULElement('menuitem');
|
||||
collapseOtherSections.classList.add('menuitem-iconic', 'zotero-menuitem-collapse-others');
|
||||
collapseOtherSections.setAttribute('data-l10n-id', 'collapse-other-sections');
|
||||
collapseOtherSections.addEventListener('command', () => {
|
||||
for (let section of containerRoot.querySelectorAll('collapsible-section')) {
|
||||
if (section !== this) {
|
||||
section.open = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
contextMenu.append(collapseOtherSections);
|
||||
|
||||
let expandAllSections = document.createXULElement('menuitem');
|
||||
expandAllSections.classList.add('menuitem-iconic', 'zotero-menuitem-expand-all');
|
||||
expandAllSections.setAttribute('data-l10n-id', 'expand-all-sections');
|
||||
expandAllSections.addEventListener('command', () => {
|
||||
for (let section of containerRoot.querySelectorAll('collapsible-section')) {
|
||||
section.open = true;
|
||||
}
|
||||
});
|
||||
contextMenu.append(expandAllSections);
|
||||
|
||||
let pinSection, unpinSection;
|
||||
let pinUnpinSeparator = document.createXULElement('menuseparator');
|
||||
contextMenu.append(pinUnpinSeparator);
|
||||
|
||||
pinSection = document.createXULElement('menuitem');
|
||||
pinSection.classList.add('menuitem-iconic', 'zotero-menuitem-pin');
|
||||
pinSection.setAttribute('data-l10n-id', 'pin-section');
|
||||
pinSection.addEventListener('command', () => {
|
||||
let sidenav = this._getSidenav();
|
||||
sidenav.scrollToPane(this.dataset.pane, 'smooth');
|
||||
sidenav.pinnedPane = this.dataset.pane;
|
||||
});
|
||||
contextMenu.append(pinSection);
|
||||
|
||||
unpinSection = document.createXULElement('menuitem');
|
||||
unpinSection.classList.add('menuitem-iconic', 'zotero-menuitem-unpin');
|
||||
unpinSection.setAttribute('data-l10n-id', 'unpin-section');
|
||||
unpinSection.addEventListener('command', () => {
|
||||
this._getSidenav().pinnedPane = null;
|
||||
});
|
||||
contextMenu.append(unpinSection);
|
||||
|
||||
contextMenu.addEventListener('popupshowing', () => {
|
||||
let sections = Array.from(containerRoot.querySelectorAll('collapsible-section'));
|
||||
collapseOtherSections.disabled = sections.every(section => section === this || !section.open);
|
||||
expandAllSections.disabled = sections.every(section => section.open);
|
||||
|
||||
let sidenav = this._getSidenav();
|
||||
if (sidenav?.isPanePinnable(this.dataset.pane)) {
|
||||
pinUnpinSeparator.hidden = false;
|
||||
pinSection.hidden = sidenav.pinnedPane == this.dataset.pane;
|
||||
unpinSection.hidden = sidenav.pinnedPane != this.dataset.pane;
|
||||
}
|
||||
else {
|
||||
pinUnpinSeparator.hidden = true;
|
||||
pinSection.hidden = true;
|
||||
unpinSection.hidden = true;
|
||||
}
|
||||
});
|
||||
|
||||
return contextMenu;
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this._head.removeEventListener('click', this._handleClick);
|
||||
this._head.removeEventListener('keydown', this._handleKeyDown);
|
||||
this._head.removeEventListener('contextmenu', this._handleContextMenu);
|
||||
|
||||
Zotero.Prefs.unregisterObserver(this._notifierID);
|
||||
}
|
||||
|
@ -160,6 +242,15 @@
|
|||
_restoreOpenState() {
|
||||
this.open = Zotero.Prefs.get(`panes.${this.dataset.pane}.open`) ?? true;
|
||||
}
|
||||
|
||||
_runWithTransitionsDisabled(fn) {
|
||||
this.classList.add('disable-transitions');
|
||||
fn();
|
||||
// Need to wait a tick before re-enabling - forcing style recalculation isn't enough here
|
||||
requestAnimationFrame(() => {
|
||||
this.classList.remove('disable-transitions');
|
||||
});
|
||||
}
|
||||
|
||||
_handleClick = (event) => {
|
||||
if (event.target.closest('.add')) return;
|
||||
|
@ -174,6 +265,16 @@
|
|||
}
|
||||
};
|
||||
|
||||
_handleContextMenu = (event) => {
|
||||
if (event.target.closest('.add')) return;
|
||||
event.preventDefault();
|
||||
this._contextMenu.openPopupAtScreen(event.screenX, event.screenY, true);
|
||||
};
|
||||
|
||||
_getSidenav() {
|
||||
return this.closest('.zotero-view-item-container')?.querySelector('item-pane-sidenav');
|
||||
}
|
||||
|
||||
render() {
|
||||
if (!this.initialized) return;
|
||||
|
||||
|
|
|
@ -28,31 +28,50 @@
|
|||
{
|
||||
class ItemPaneSidenav extends XULElementBase {
|
||||
content = MozXULElement.parseXULToFragment(`
|
||||
<toolbarbutton
|
||||
data-l10n-id="sidenav-info"
|
||||
data-pane="info"/>
|
||||
<toolbarbutton
|
||||
data-l10n-id="sidenav-abstract"
|
||||
data-pane="abstract"/>
|
||||
<toolbarbutton
|
||||
data-l10n-id="sidenav-attachments"
|
||||
data-pane="attachments"/>
|
||||
<toolbarbutton
|
||||
data-l10n-id="sidenav-notes"
|
||||
data-pane="notes"/>
|
||||
<toolbarbutton
|
||||
data-l10n-id="sidenav-tags"
|
||||
data-pane="tags"/>
|
||||
<toolbarbutton
|
||||
data-l10n-id="sidenav-related"
|
||||
data-pane="related"/>
|
||||
<html:div class="toolbarbutton-container">
|
||||
<toolbarbutton
|
||||
data-l10n-id="sidenav-info"
|
||||
data-pane="info"/>
|
||||
</html:div>
|
||||
<html:div class="toolbarbutton-container">
|
||||
<toolbarbutton
|
||||
data-l10n-id="sidenav-abstract"
|
||||
data-pane="abstract"/>
|
||||
</html:div>
|
||||
<html:div class="toolbarbutton-container">
|
||||
<toolbarbutton
|
||||
data-l10n-id="sidenav-attachments"
|
||||
data-pane="attachments"/>
|
||||
</html:div>
|
||||
<html:div class="toolbarbutton-container">
|
||||
<toolbarbutton
|
||||
data-l10n-id="sidenav-notes"
|
||||
data-pane="notes"/>
|
||||
</html:div>
|
||||
<html:div class="toolbarbutton-container">
|
||||
<toolbarbutton
|
||||
data-l10n-id="sidenav-tags"
|
||||
data-pane="tags"/>
|
||||
</html:div>
|
||||
<html:div class="toolbarbutton-container">
|
||||
<toolbarbutton
|
||||
data-l10n-id="sidenav-related"
|
||||
data-pane="related"/>
|
||||
</html:div>
|
||||
|
||||
<popupset>
|
||||
<menupopup class="context-menu">
|
||||
<menuitem class="menuitem-iconic zotero-menuitem-pin" data-l10n-id="pin-section"/>
|
||||
<menuitem class="menuitem-iconic zotero-menuitem-unpin" data-l10n-id="unpin-section"/>
|
||||
</menupopup>
|
||||
</popupset>
|
||||
`, ['chrome://zotero/locale/zotero.dtd']);
|
||||
|
||||
_container = null;
|
||||
|
||||
_currentSmoothScrollTarget = null;
|
||||
|
||||
_smoothScrollTargetTimeout = null;
|
||||
_contextMenuTarget = null;
|
||||
|
||||
_preserveMinScrollHeightTimeout = null;
|
||||
|
||||
get container() {
|
||||
return this._container;
|
||||
|
@ -60,26 +79,33 @@
|
|||
|
||||
set container(val) {
|
||||
if (this._container == val) return;
|
||||
|
||||
this._container?.removeEventListener('scroll', this._updateSelectedPane.bind(this), { passive: true });
|
||||
this._container?.removeEventListener('scroll', this._handleContainerScroll);
|
||||
this._container = val;
|
||||
this._container.addEventListener('scroll', this._updateSelectedPane.bind(this), { passive: true });
|
||||
|
||||
this._updateSelectedPane();
|
||||
this._container.addEventListener('scroll', this._handleContainerScroll);
|
||||
this.render();
|
||||
}
|
||||
|
||||
get selectedPane() {
|
||||
return this.getAttribute('selectedPane');
|
||||
get pinnedPane() {
|
||||
return this.getAttribute('pinnedPane');
|
||||
}
|
||||
|
||||
set selectedPane(val) {
|
||||
this.setAttribute('selectedPane', val);
|
||||
this.render();
|
||||
set pinnedPane(val) {
|
||||
this.setAttribute('pinnedPane', val || '');
|
||||
if (val) {
|
||||
this._pinnedPaneMinScrollHeight = this._getMinScrollHeightForPane(this.getPane(val));
|
||||
}
|
||||
}
|
||||
|
||||
get _minScrollHeight() {
|
||||
return parseFloat(this._container.style.getPropertyValue('--min-scroll-height') || 0);
|
||||
}
|
||||
|
||||
set _minScrollHeight(val) {
|
||||
this._container.style.setProperty('--min-scroll-height', val + 'px');
|
||||
}
|
||||
|
||||
static get observedAttributes() {
|
||||
return ['selectedPane'];
|
||||
return ['pinnedPane'];
|
||||
}
|
||||
|
||||
attributeChangedCallback() {
|
||||
|
@ -87,75 +113,134 @@
|
|||
}
|
||||
|
||||
scrollToPane(id, behavior = 'smooth') {
|
||||
let pane = this._getPane(id);
|
||||
if (pane) {
|
||||
this._currentSmoothScrollTarget = id;
|
||||
pane.scrollIntoView({ block: 'start', behavior });
|
||||
|
||||
if (this._smoothScrollTargetTimeout) {
|
||||
clearTimeout(this._smoothScrollTargetTimeout);
|
||||
let pane = this.getPane(id);
|
||||
if (!pane) return;
|
||||
|
||||
// The pane should always be at the very top
|
||||
// If there isn't enough stuff below it for it to be at the top, we add padding
|
||||
// We use a ::before pseudo-element for this so that we don't need to add another level to the DOM
|
||||
this._makeSpaceForPane(pane);
|
||||
if (behavior == 'smooth' && pane.getBoundingClientRect().top > this._container.getBoundingClientRect().top) {
|
||||
if (this._preserveMinScrollHeightTimeout) {
|
||||
clearTimeout(this._preserveMinScrollHeightTimeout);
|
||||
}
|
||||
this._smoothScrollTargetTimeout = setTimeout(() => {
|
||||
this._currentSmoothScrollTarget = null;
|
||||
this._preserveMinScrollHeightTimeout = setTimeout(() => {
|
||||
this._preserveMinScrollHeightTimeout = null;
|
||||
this._handleContainerScroll();
|
||||
}, 1000);
|
||||
}
|
||||
pane.scrollIntoView({ block: 'start', behavior });
|
||||
pane.focus();
|
||||
}
|
||||
|
||||
_flashPane(id) {
|
||||
let paneSection = this.getPane(id)?.querySelector('collapsible-section');
|
||||
if (paneSection) {
|
||||
paneSection.classList.add('highlight');
|
||||
setTimeout(() => {
|
||||
paneSection.classList.remove('highlight');
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
|
||||
_updateSelectedPane() {
|
||||
let topPane = null;
|
||||
let containerBoundingRect = this.container.getBoundingClientRect();
|
||||
// If not initialized with content, just select the first pane
|
||||
if (containerBoundingRect.height == 0) {
|
||||
this.selectedPane = 'info';
|
||||
return;
|
||||
_makeSpaceForPane(pane) {
|
||||
let oldMinScrollHeight = this._minScrollHeight;
|
||||
let newMinScrollHeight = this._getMinScrollHeightForPane(pane);
|
||||
if (newMinScrollHeight > oldMinScrollHeight) {
|
||||
this._minScrollHeight = newMinScrollHeight;
|
||||
}
|
||||
for (let box of this._getPanes()) {
|
||||
// Allow a little padding to deal with floating-point imprecision
|
||||
if (box.getBoundingClientRect().top > containerBoundingRect.top + 5) {
|
||||
break;
|
||||
}
|
||||
topPane = box.dataset.pane;
|
||||
}
|
||||
if (this._currentSmoothScrollTarget) {
|
||||
if (this._currentSmoothScrollTarget == topPane) {
|
||||
this._currentSmoothScrollTarget = null;
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
this.selectedPane = topPane || 'info';
|
||||
}
|
||||
|
||||
_getPanes() {
|
||||
return Array.from(this.container.querySelectorAll('[data-pane]'));
|
||||
}
|
||||
|
||||
_getPane(id) {
|
||||
return this.container.querySelector(':scope > [data-pane="' + id + '"]');
|
||||
_getMinScrollHeightForPane(pane) {
|
||||
let paneRect = pane.getBoundingClientRect();
|
||||
let containerRect = this._container.getBoundingClientRect();
|
||||
// No offsetTop property for XUL elements
|
||||
let offsetTop = paneRect.top - containerRect.top + this._container.scrollTop;
|
||||
return offsetTop + containerRect.height;
|
||||
}
|
||||
|
||||
_handleContainerScroll = () => {
|
||||
if (this._preserveMinScrollHeightTimeout) return;
|
||||
let minHeight = this._minScrollHeight;
|
||||
if (minHeight) {
|
||||
let newMinScrollHeight = this._container.scrollTop + this._container.clientHeight;
|
||||
if (this.pinnedPane && newMinScrollHeight < this._pinnedPaneMinScrollHeight) {
|
||||
return;
|
||||
}
|
||||
this._minScrollHeight = newMinScrollHeight;
|
||||
}
|
||||
};
|
||||
|
||||
getPanes() {
|
||||
return Array.from(this.container.querySelectorAll(':scope > [data-pane]'));
|
||||
}
|
||||
|
||||
getPane(id) {
|
||||
return this.container.querySelector(`:scope > [data-pane="${CSS.escape(id)}"]`);
|
||||
}
|
||||
|
||||
isPanePinnable(id) {
|
||||
return id !== 'info';
|
||||
}
|
||||
|
||||
init() {
|
||||
if (!this.container) {
|
||||
this.container = document.getElementById('zotero-view-item');
|
||||
}
|
||||
|
||||
for (let toolbarbutton of this.children) {
|
||||
toolbarbutton.addEventListener('command', () => {
|
||||
this.selectedPane = toolbarbutton.dataset.pane;
|
||||
this.scrollToPane(toolbarbutton.dataset.pane);
|
||||
|
||||
for (let toolbarbutton of this.querySelectorAll('toolbarbutton')) {
|
||||
let pane = toolbarbutton.dataset.pane;
|
||||
let pinnable = this.isPanePinnable(pane);
|
||||
toolbarbutton.parentElement.classList.toggle('pinnable', pinnable);
|
||||
|
||||
toolbarbutton.addEventListener('click', (event) => {
|
||||
switch (event.detail) {
|
||||
case 1:
|
||||
this.scrollToPane(pane, 'smooth');
|
||||
this._flashPane(pane);
|
||||
break;
|
||||
case 2:
|
||||
if (this.pinnedPane == pane || !pinnable) {
|
||||
this.pinnedPane = null;
|
||||
}
|
||||
else {
|
||||
this.pinnedPane = pane;
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
if (pinnable) {
|
||||
toolbarbutton.addEventListener('contextmenu', (event) => {
|
||||
this._contextMenuTarget = pane;
|
||||
this.querySelector('.zotero-menuitem-pin').hidden = this.pinnedPane == pane;
|
||||
this.querySelector('.zotero-menuitem-unpin').hidden = this.pinnedPane != pane;
|
||||
this.querySelector('.context-menu')
|
||||
.openPopupAtScreen(event.screenX, event.screenY, true);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
this.querySelector('.zotero-menuitem-pin').addEventListener('command', () => {
|
||||
this.scrollToPane(this._contextMenuTarget, 'smooth');
|
||||
this.pinnedPane = this._contextMenuTarget;
|
||||
});
|
||||
this.querySelector('.zotero-menuitem-unpin').addEventListener('command', () => {
|
||||
this.pinnedPane = null;
|
||||
});
|
||||
|
||||
this.render();
|
||||
}
|
||||
|
||||
render() {
|
||||
let currentPane = this.selectedPane;
|
||||
for (let toolbarbutton of this.children) {
|
||||
let pinnedPane = this.pinnedPane;
|
||||
for (let toolbarbutton of this.querySelectorAll('toolbarbutton')) {
|
||||
let pane = toolbarbutton.dataset.pane;
|
||||
toolbarbutton.hidden = !this._getPane(pane);
|
||||
toolbarbutton.toggleAttribute('selected', pane == currentPane);
|
||||
toolbarbutton.setAttribute('aria-selected', pane == currentPane);
|
||||
toolbarbutton.setAttribute('aria-selected', pane == pinnedPane);
|
||||
toolbarbutton.parentElement.hidden = !this.getPane(pane);
|
||||
|
||||
// Set .pinned on the container, for pin styling
|
||||
toolbarbutton.parentElement.classList.toggle('pinned', pane == pinnedPane);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -84,7 +84,7 @@
|
|||
|
||||
let removeAllItemTags = this._id('remove-all-item-tags');
|
||||
this._id('remove-all-item-tags').addEventListener('command', this.removeAll);
|
||||
this.addEventListener('contextmenu', (event) => {
|
||||
this.querySelector('.body').addEventListener('contextmenu', (event) => {
|
||||
removeAllItemTags.disabled = !this.count;
|
||||
this._id('tags-context-menu').openPopupAtScreen(event.screenX, event.screenY, true);
|
||||
});
|
||||
|
|
|
@ -62,12 +62,8 @@ var ZoteroItemPane = new function() {
|
|||
/*
|
||||
* Load a top-level item
|
||||
*/
|
||||
this.viewItem = Zotero.Promise.coroutine(function* (item, mode, pane) {
|
||||
if (!pane) {
|
||||
pane = 'info';
|
||||
}
|
||||
|
||||
Zotero.debug('Viewing item in pane ' + pane);
|
||||
this.viewItem = Zotero.Promise.coroutine(function* (item, mode, pinnedPane) {
|
||||
Zotero.debug('Viewing item');
|
||||
|
||||
_notesBox.parentItem = item;
|
||||
|
||||
|
@ -108,14 +104,20 @@ var ZoteroItemPane = new function() {
|
|||
box.inTrash = inTrash;
|
||||
}
|
||||
|
||||
_sidenav.selectedPane = pane;
|
||||
_sidenav.scrollToPane(pane, 'instant');
|
||||
_scrollParent.style.paddingBottom = '';
|
||||
if (pinnedPane) {
|
||||
_sidenav.scrollToPane(pinnedPane, 'instant');
|
||||
_sidenav.pinnedPane = pinnedPane;
|
||||
}
|
||||
else if (pinnedPane !== false) {
|
||||
_sidenav.scrollToPane('info', 'instant');
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
this.notify = Zotero.Promise.coroutine(function* (action, type, ids, extraData) {
|
||||
if (action == 'refresh' && _lastItem) {
|
||||
yield this.viewItem(_lastItem, null, _sidenav.selectedPane);
|
||||
yield this.viewItem(_lastItem, null, false);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -250,8 +252,8 @@ var ZoteroItemPane = new function() {
|
|||
};
|
||||
|
||||
|
||||
this.getSidenavSelectedPane = function () {
|
||||
return _sidenav.selectedPane;
|
||||
this.getPinnedPane = function () {
|
||||
return _sidenav.pinnedPane;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -1818,14 +1818,9 @@ var ZoteroPane = new function()
|
|||
var isCommons = collectionTreeRow.isBucket();
|
||||
|
||||
let deck = document.getElementById('zotero-item-pane-content');
|
||||
let pane;
|
||||
if (deck.selectedIndex == 1) {
|
||||
pane = ZoteroItemPane.getSidenavSelectedPane();
|
||||
}
|
||||
else {
|
||||
deck.selectedIndex = 1;
|
||||
pane = ZoteroItemPane.getSidenavSelectedPane();
|
||||
}
|
||||
deck.selectedIndex = 1;
|
||||
|
||||
let pane = ZoteroItemPane.getPinnedPane();
|
||||
|
||||
var button = document.getElementById('zotero-item-show-original');
|
||||
if (isCommons) {
|
||||
|
|
|
@ -267,6 +267,16 @@ sidenav-tags =
|
|||
sidenav-related =
|
||||
.tooltiptext = { pane-related }
|
||||
|
||||
pin-section =
|
||||
.label = Pin Section
|
||||
unpin-section =
|
||||
.label = Unpin Section
|
||||
|
||||
collapse-other-sections =
|
||||
.label = Collapse Other Sections
|
||||
expand-all-sections =
|
||||
.label = Expand All Sections
|
||||
|
||||
abstract-field =
|
||||
.label = Add abstract…
|
||||
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M11.9999 1.70711L8.00004 5.70709L4 1.70711L4.70711 1L8.00004 4.29288L11.2928 1L11.9999 1.70711ZM11.9999 15.2929L8.00004 11.2929L4 15.2929L4.70711 16L8.00004 12.7071L11.2928 16L11.9999 15.2929ZM14 8H2V9H14V8Z" fill="context-fill"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 392 B |
5
chrome/skin/default/zotero/16/universal/expand-all.svg
Normal file
5
chrome/skin/default/zotero/16/universal/expand-all.svg
Normal file
|
@ -0,0 +1,5 @@
|
|||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.00004 0.292908L11.9999 4.29289L11.2928 5L8.00004 1.70712L4.70711 5L4 4.29289L8.00004 0.292908ZM8.00004 15.7071L11.9999 11.7071L11.2928 11L8.00004 14.2929L4.70711 11L4 11.7071L8.00004 15.7071Z" fill="context-fill"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 379 B |
10
chrome/skin/default/zotero/16/universal/pin-remove.svg
Normal file
10
chrome/skin/default/zotero/16/universal/pin-remove.svg
Normal file
|
@ -0,0 +1,10 @@
|
|||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_4465_26581)">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M0 0.70706L15.293 16L16 15.2928L0.707197 0L0 0.70706ZM10.499 12.6203L9.25753 15.1031C8.95228 15.7136 8.13864 15.8457 7.65599 15.363L4.50008 12.2071L0.707182 16L9.87947e-05 16L0 15.2929L3.79297 11.5L0.637052 8.34408C0.15441 7.86144 0.286449 7.04779 0.896946 6.74255L3.37981 5.50111L4.12517 6.24647L1.34416 7.63697L8.3631 14.6559L9.7536 11.8749L10.499 12.6203ZM11.9132 9.79184L12.3489 8.92033L14.8204 8.2142C15.5535 8.00473 15.7919 7.08473 15.2528 6.54558L9.4545 0.747313C8.91534 0.208154 7.99534 0.446553 7.78587 1.1797L7.07974 3.65115L6.20824 4.0869L6.95359 4.83226L7.72368 4.44721L7.92041 4.34885L7.98084 4.13736L8.74739 1.45442L14.5457 7.25268L11.8627 8.01923L11.6512 8.07966L11.5529 8.27639L11.1678 9.04648L11.9132 9.79184Z" fill="context-fill"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_4465_26581">
|
||||
<rect width="16" height="16" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 1 KiB |
10
chrome/skin/default/zotero/16/universal/pin.svg
Normal file
10
chrome/skin/default/zotero/16/universal/pin.svg
Normal file
|
@ -0,0 +1,10 @@
|
|||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_4465_26580)">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M9.45442 0.747313C8.91526 0.208154 7.99526 0.446553 7.78579 1.1797L7.07966 3.65115L0.896869 6.74255C0.286372 7.04779 0.154333 7.86144 0.636975 8.34408L3.79293 11.5L0 15.2929L9.87947e-05 16L0.707182 16L4.50004 12.2071L7.65592 15.363C8.13856 15.8457 8.9522 15.7136 9.25745 15.1031L12.3488 8.92033L14.8203 8.21421C15.5534 8.00474 15.7918 7.08473 15.2527 6.54558L9.45442 0.747313ZM8.74732 1.45442L14.5456 7.25268L11.8626 8.01924L11.6512 8.07966L11.5528 8.27639L8.36302 14.6559L1.34408 7.63697L7.72361 4.44721L7.92034 4.34885L7.98076 4.13736L8.74732 1.45442Z" fill="context-fill"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_4465_26580">
|
||||
<rect width="16" height="16" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 877 B |
3
chrome/skin/default/zotero/8/universal/pin-remove.svg
Normal file
3
chrome/skin/default/zotero/8/universal/pin-remove.svg
Normal file
|
@ -0,0 +1,3 @@
|
|||
<svg width="8" height="8" viewBox="0 0 8 8" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.00002 4L5.68694 4.62617L3.37386 2.31308L4.00002 2L4.50002 0.5L7.50002 3.5L6.00002 4ZM4.97983 6.04038L1.95964 3.02019L1.00002 3.5L2.50002 5L1.00002 6.5V7H1.50002L3.00002 5.5L4.50002 7L4.97983 6.04038ZM1 1.35355L6.64648 7L7.00004 6.64645L1.35355 1L1 1.35355Z" fill="white"/>
|
||||
</svg>
|
After Width: | Height: | Size: 424 B |
5
chrome/skin/default/zotero/8/universal/pin.svg
Normal file
5
chrome/skin/default/zotero/8/universal/pin.svg
Normal file
|
@ -0,0 +1,5 @@
|
|||
<svg width="8" height="8" viewBox="0 0 8 8" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g id="pin">
|
||||
<path id="Vector" d="M7.5 3.5L4.5 0.5L4 2L1 3.5L2.5 5L1 6.5V7H1.5L3 5.5L4.5 7L6 4L7.5 3.5Z" fill="white"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 224 B |
|
@ -15,6 +15,7 @@
|
|||
.zotero-view-item-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
height: 0; /* Prevent overflow, somehow */
|
||||
}
|
||||
|
||||
.zotero-view-item-main {
|
||||
|
@ -24,10 +25,22 @@
|
|||
}
|
||||
|
||||
.zotero-view-item {
|
||||
position: relative;
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
padding: 0 8px;
|
||||
overflow-anchor: none; /* Work around tags box causing scroll to jump - figure this out */
|
||||
scrollbar-color: var(--color-scrollbar) var(--color-scrollbar-background);
|
||||
}
|
||||
|
||||
.zotero-view-item::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: var(--min-scroll-height);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.zotero-view-item-container.feed-item .zotero-view-item > :is(attachments-box, notes-box, tags-box, related-box),
|
||||
|
@ -40,10 +53,6 @@
|
|||
width: 100%;
|
||||
}
|
||||
|
||||
.zotero-view-item > :last-child {
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
.zotero-view-item > vbox
|
||||
{
|
||||
margin-left: 5px;
|
||||
|
|
|
@ -108,3 +108,22 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Hide icons on macOS. We use :is() to work around weird behavior in Fx101 where a regular child
|
||||
selector doesn't match the first time the menu is opened. */
|
||||
@mixin macOS-hide-menu-icons {
|
||||
$selector: &;
|
||||
@at-root {
|
||||
@media (-moz-platform: macos) {
|
||||
// Yes, every single one of these :is-es is necessary!
|
||||
:is(:is(#{$selector}) .menuitem-iconic, :is(#{$selector}) .menu-iconic) {
|
||||
list-style-image: none !important;
|
||||
|
||||
.menu-iconic-left {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,7 +57,10 @@ $menu-icons: (
|
|||
add-to-collection: "new-collection",
|
||||
new-tab: "new-tab",
|
||||
new-window: "new-window",
|
||||
|
||||
pin: "pin",
|
||||
unpin: "pin-remove",
|
||||
expand-all: "expand-all",
|
||||
collapse-others: "collapse-others",
|
||||
);
|
||||
|
||||
@each $cls, $icon in $menu-icons {
|
||||
|
@ -73,3 +76,7 @@ $menu-icons: (
|
|||
}
|
||||
}
|
||||
};
|
||||
|
||||
#zotero-collectionmenu, #zotero-itemmenu {
|
||||
@include macOS-hide-menu-icons;
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ collapsible-section {
|
|||
gap: 4px;
|
||||
color: var(--fill-secondary);
|
||||
font-weight: 590;
|
||||
transition: color 0.2s ease-out;
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
|
@ -59,6 +60,14 @@ collapsible-section {
|
|||
transform-origin: center;
|
||||
transition: transform 0.2s ease-in-out;
|
||||
}
|
||||
|
||||
popupset > menupopup {
|
||||
@include macOS-hide-menu-icons;
|
||||
}
|
||||
}
|
||||
|
||||
&.highlight > .head > .title {
|
||||
color: var(--fill-primary);
|
||||
}
|
||||
|
||||
&[open]:not([empty]) > .head {
|
||||
|
@ -97,4 +106,9 @@ collapsible-section {
|
|||
transition: max-height 0.2s ease-in-out, opacity 0.2s ease-in-out, visibility 0s 0.2s, overflow-y 0s 0.2s;
|
||||
}
|
||||
}
|
||||
|
||||
&.disable-transitions * {
|
||||
transition: none !important;
|
||||
color: red;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,24 +6,53 @@ item-pane-sidenav {
|
|||
gap: 6px;
|
||||
border-left: var(--material-panedivider);
|
||||
|
||||
.toolbarbutton-container {
|
||||
position: relative;
|
||||
// Disable pointer events here, re-enable on the button, so that :hover styles are only applied
|
||||
// when the button itself is hovered
|
||||
pointer-events: none;
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 1px;
|
||||
inset-inline-end: 1px;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
&.pinnable {
|
||||
&.pinned::after {
|
||||
background-color: var(--accent-blue);
|
||||
background-image: icon-url("8/universal/pin.svg");
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
toolbarbutton {
|
||||
// TODO: Extract button styles?
|
||||
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
margin: 0;
|
||||
padding: 4px;
|
||||
flex-shrink: 0;
|
||||
border-radius: 5px;
|
||||
-moz-context-properties: fill, fill-opacity, stroke, stroke-opacity;
|
||||
|
||||
pointer-events: all;
|
||||
|
||||
&:hover {
|
||||
background-color: var(--fill-quinary);
|
||||
}
|
||||
|
||||
&:active, &[selected] {
|
||||
|
||||
&:active {
|
||||
background-color: var(--fill-quarternary);
|
||||
}
|
||||
|
||||
|
||||
&:disabled {
|
||||
background-color: transparent;
|
||||
fill: var(--fill-tertiary);
|
||||
|
@ -37,4 +66,8 @@ item-pane-sidenav {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
menupopup {
|
||||
@include macOS-hide-menu-icons;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue