Citation Explorer: Update per new design

Switch the layout to use grid instead of flexbox
This commit is contained in:
Adomas Venčkauskas 2025-08-14 17:03:16 +03:00
parent 376e69545b
commit 6bd1da9036
9 changed files with 133 additions and 96 deletions

View file

@ -27,11 +27,11 @@ const React = require('react');
const ReactDOM = require('react-dom');
const diff = require('diff');
const VirtualizedTable = require('components/virtualized-table');
const { getCSSIcon, IconAttachSmall } = require('components/icons');
// TODO: Create a custom row provider for citationExplorer to use with base ItemTree.
// Currently uses changeCollectionTreeRow which only exists on CollectionViewItemTree,
// so this is broken until we either switch to CollectionViewItemTree or create a
// simple row provider that can display arbitrary items.
const { getCSSIcon, CSSIcon } = require('components/icons');
const ItemTree = require('zotero/itemTree');
const { getColumnDefinitionsByDataKey } = require('zotero/itemTreeColumns');
const { makeRowRenderer } = VirtualizedTable;
@ -45,10 +45,15 @@ let disableCitationActivate;
let selectedTab = 0;
const citationColumns = [
{
dataKey: 'title',
label: "Citation",
type: 'html'
},
{
dataKey: 'isLinked',
label: 'Is Linked',
iconLabel: <IconAttachSmall/>,
iconLabel: <CSSIcon name="link" className="icon-16"/>,
width: 26,
staticWidth: true,
fixedWidth: true,
@ -62,18 +67,13 @@ const citationColumns = [
return icon;
}
},
{
dataKey: 'title',
label: "Citation",
type: 'html'
},
];
let itemColumns = getColumnDefinitionsByDataKey(['title', 'firstCreator', 'date']);
itemColumns.push({
dataKey: 'isLinked',
label: 'Is Linked',
iconLabel: <IconAttachSmall/>,
iconLabel: <CSSIcon name="link" className="icon-16"/>,
width: 26,
staticWidth: true,
fixedWidth: true,
@ -149,7 +149,8 @@ window.ZoteroDocumentCitations = {
// init VirtualizedTable
if (!citationList) {
await new Promise((resolve) => {
ReactDOM.createRoot(document.querySelector('#citation-list')).render(<VirtualizedTable
const domElem = document.querySelector('#citation-list-container');
ReactDOM.createRoot(domElem).render(<VirtualizedTable
id="citation-list"
ref={(ref) => {
citationList = ref;
@ -165,6 +166,11 @@ window.ZoteroDocumentCitations = {
onSelectionChange={this.onCitationSelectionChange.bind(this)}
getRowString={index => this._renderedCitationRows[index].title}
/>);
domElem.addEventListener("focusout", (event) => {
if (event.relatedTarget && !event.relatedTarget.closest("#citation-list-container")) {
citationList?.selection.clearSelection()
}
});
});
}
citationList.invalidate();
@ -178,7 +184,7 @@ window.ZoteroDocumentCitations = {
let filteredItems = rows.filter(item => !this._filteredItems.has(item.id));
if (!itemList) {
let domElem = document.querySelector('#item-list');
let domElem = document.querySelector('#item-list-container');
itemList = await ItemTree.init(domElem, {
id: "document-collections",
regularOnly: true,
@ -186,9 +192,15 @@ window.ZoteroDocumentCitations = {
shouldListenForNotifications: false,
onSelectionChange: this.onItemSelectionChange.bind(this),
onActivate: this.onItemActivate.bind(this),
emptyMessage: Zotero.getString('pane.items.loading')
emptyMessage: Zotero.getString('pane.items.loading'),
firstColumnExtraWidth: 28-16,
});
await itemList.waitForLoad();
domElem.addEventListener("focusout", (event) => {
if (event.relatedTarget && !event.relatedTarget.closest("#item-list-container")) {
itemList?.selection.clearSelection()
}
});
}
await itemList.changeCollectionTreeRow({
getItems: async () => filteredItems,

View file

@ -34,9 +34,10 @@
<xul:window
id="zotero-citation-explorer-dialog"
class="zotero-dialog-window"
orient="vertical"
title="Citation Explorer"
width="750" height="450"
width="800" height="600"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
persist="screenX screenY width height"
@ -51,48 +52,53 @@
Services.scriptloader.loadSubScript("chrome://zotero/content/integration/citationExplorer.js", this);
</script>
<div class="vbox flex xul-border-div">
<div class="hbox flex">
<div class="vbox flex">
<div id="citations-label">Citations</div>
<div class="vbox flex panel" style="border-right: none">
<xul:search-textbox id="citation-search" class="search-box" timeout="250" oncommand="ZoteroDocumentCitations.onCitationFilter()" dir="reverse"/>
<div id="citation-list-container" class="virtualized-table-container">
<div id="citation-list"></div>
</div>
<div class="hbox button-container">
<input type="button" id="button-show-in-document" value="Show in Document"/>
<input type="button" id="button-edit-citation" value="Edit Citation"/>
</div>
</div>
</div>
<div class="splitter"></div>
<div class="vbox flex">
<xul:tabbox onselect="ZoteroDocumentCitations.onSelectTab(this.selectedIndex)">
<xul:tabs>
<xul:tab id="tab-cited-items" label="Cited Items"/>
<xul:tab id="tab-uncited-items" label="Uncited Items"/>
</xul:tabs>
<!--We are making our own tabpanel UI, but the onselect event above won't fire without these-->
<xul:tabpanels hidden="true"><xul:tabpanel/><xul:tabpanel/></xul:tabpanels>
</xul:tabbox>
<div id="items-panel" class="vbox flex panel">
<xul:search-textbox id="item-search" class="search-box" timeout="250" oncommand="ZoteroDocumentCitations.onItemFilter()" dir="reverse"/>
<div id="item-list-container" class="virtualized-table-container">
<div id="item-list"></div>
</div>
<div class="hbox button-container">
<input type="button" id="button-show-in-zotero" value="Show in Zotero"/>
<input type="button" id="button-relink-item" value="Relink Item" hidden="true"/>
<button is="split-menu-button" id="button-addTo-library"
onclick="ZoteroDocumentCitations.addToLibraryAndLink()"
popup="item-addTo-menu" style="display: none"/>
<xul:popupset>
<xul:menupopup id="item-addTo-menu" onpopupshowing="ZoteroDocumentCitations.buildAddToLibraryContextMenu(event);"/>
</xul:popupset>
</div>
</div>
</div>
<div class="citation-explorer-grid">
<div class="citation-explorer-grid-left grid-padded-section" id="citations-label">Citations</div>
<div class="tabbox-container grid-padded-section">
<xul:tabbox onselect="ZoteroDocumentCitations.onSelectTab(this.selectedIndex)">
<xul:tabs>
<xul:tab id="tab-cited-items" label="Cited Items"/>
<xul:tab id="tab-uncited-items" label="Uncited Items"/>
</xul:tabs>
<!--We are making our own tabpanel UI, but the onselect event above won't fire without these-->
<xul:tabpanels hidden="true"><xul:tabpanel/><xul:tabpanel/></xul:tabpanels>
</xul:tabbox>
</div>
<div class="searchbox-container citation-explorer-grid-left grid-padded-section">
<xul:search-textbox id="citation-search" placeholder="Citation Content" class="search-box" timeout="250" oncommand="ZoteroDocumentCitations.onCitationFilter()" dir="reverse"/>
</div>
<div class="searchbox-container grid-padded-section">
<xul:search-textbox id="item-search" placeholder="Title, Creator, Year" class="search-box" timeout="250" oncommand="ZoteroDocumentCitations.onItemFilter()" dir="reverse"/>
</div>
<div class="virtualized-table-container citation-explorer-grid-left">
<div id="citation-list-container"></div>
</div>
<div class="virtualized-table-container">
<div id="item-list-container"></div>
</div>
<div class="button-container citation-explorer-grid-left grid-padded-section">
<input type="button" id="button-show-in-document" value="Show in Document"/>
<div class="spacer"></div>
<input type="button" id="button-edit-citation" value="Edit Citation"/>
</div>
<div class="button-container grid-padded-section">
<input type="button" id="button-show-in-zotero" value="Show in Zotero"/>
<div class="spacer"></div>
<input type="button" id="button-relink-item" value="Relink Item" hidden="true"/>
<button is="split-menu-button" id="button-addTo-library"
onclick="ZoteroDocumentCitations.addToLibraryAndLink()"
popup="item-addTo-menu" style="display: none"/>
<xul:popupset>
<xul:menupopup id="item-addTo-menu" onpopupshowing="ZoteroDocumentCitations.buildAddToLibraryContextMenu(event);"/>
</xul:popupset>
</div>
</div>
</xul:dialog>

View file

@ -16,3 +16,7 @@
.flex {
flex: 1
}
.spacer {
flex: 1;
}

View file

@ -1,29 +1,72 @@
#zotero-citation-explorer-dialog {
min-height: 500px;
dialog {
max-height: 100vh;
padding: 0 0 .3em;
background: var(--material-sidepane);
}
search-textbox, input, button {
margin: 0;
}
.virtualized-table-container {
.citation-explorer-grid {
display: grid;
grid-template-columns: 4fr 6fr;
grid-template-rows: auto auto minmax(0, 1fr) auto;
height: 100%;
flex: 1;
}
.xul-border-div {
-moz-box-flex: 1;
.citation-explorer-grid-left {
border-right: solid 1px ThreeDShadow;
}
.grid-padded-section {
padding: 8px 16px;
}
}
#citations-label {
margin: 5px 0 4px;
align-content: center;
}
.panel {
border: solid 1px ThreeDShadow;
padding: 5px;
.tabbox-container {
display: flex;
}
.search-box {
margin: 2px -1px;
.searchbox-container {
border-bottom: 1px solid ThreeDShadow;
}
.virtualized-table-container {
height: 100%;
}
.virtualized-table:focus-within .row.highlighted:not(.selected) {
background: initial !important;
}
.button-container {
border-block: 1px solid ThreeDShadow;
display: flex;
}
@media (-moz-platform: macos) {
tab[visuallyselected="true"]:not(:-moz-window-inactive) {
color: initial !important;
}
#citations-label {
font-size: 1.2em;
}
}
@media (-moz-platform: windows) {
tab:focus-visible > .tab-middle {
outline: none;
}
input[type="button"], button {
margin-top: 7px;
}
}
}

View file

@ -41,6 +41,7 @@ $-icons: (
chevron-6: 8,
filter: 16,
note: 16,
link: 16,
x-8: 16,
play: 16,
pause: 16,

View file

@ -1,14 +0,0 @@
#zotero-citation-explorer-dialog {
tab[visuallyselected="true"]:not(:-moz-window-inactive) {
color: initial !important;
}
#items-panel {
margin-top: 1.5em;
}
#citations-label {
margin: 0.5em 0 0.38em;
font-size: 1.2em;
}
}

View file

@ -1,13 +0,0 @@
#zotero-citation-explorer-dialog {
#citations-label {
margin: 3px 0 2px;
}
tab:focus-visible > .tab-middle {
outline: none;
}
input[type="button"], button {
margin-top: 7px;
}
}

View file

@ -13,6 +13,5 @@
@import "mac/components/input";
@import "mac/components/menupopup";
@import "mac/components/menulist";
@import "mac/citationExplorer";
// Elements

View file

@ -9,7 +9,6 @@
@import "win/createParent";
@import "win/tabBar";
@import "win/titleBar";
@import "win/citationExplorer";
// Elements