diff --git a/chrome/content/zotero/components/icons.jsx b/chrome/content/zotero/components/icons.jsx
index c9ebc938ba..e1b996d3e3 100644
--- a/chrome/content/zotero/components/icons.jsx
+++ b/chrome/content/zotero/components/icons.jsx
@@ -20,7 +20,36 @@ Icon.propTypes = {
style: object
}
-module.exports = { Icon }
+const CSSIcon = (props) => {
+ props = Object.assign({}, props);
+ props.className = `icon icon-css icon-${props.name} ${props.className || ""}`;
+ delete props.name;
+ // Pass the props forward
+ return ;
+};
+
+CSSIcon.propTypes = {
+ children: element,
+ className: string,
+ name: string.isRequired,
+ style: object
+};
+
+const CSSItemTypeIcon = (props) => {
+ props = Object.assign({}, props);
+ let itemType = props.itemType;
+ delete props.itemType;
+ return ;
+};
+
+CSSItemTypeIcon.propTypes = {
+ children: element,
+ className: string,
+ itemType: string.isRequired,
+ style: object
+};
+
+module.exports = { Icon, CSSIcon, CSSItemTypeIcon };
function i(name, svgOrSrc, hasHiDPI = true) {
@@ -231,4 +260,10 @@ module.exports.getCSSIcon = function (key) {
}
return cssIconsCache.get(key).cloneNode(true);
-};
\ No newline at end of file
+};
+
+module.exports.getCSSItemTypeIcon = function (itemType) {
+ let icon = module.exports.getCSSIcon('icon-item-type');
+ icon.dataset.itemType = itemType;
+ return icon;
+};
diff --git a/chrome/content/zotero/components/itemPane/notesList.jsx b/chrome/content/zotero/components/itemPane/notesList.jsx
index 98c9ce0007..ba6db84770 100644
--- a/chrome/content/zotero/components/itemPane/notesList.jsx
+++ b/chrome/content/zotero/components/itemPane/notesList.jsx
@@ -25,6 +25,7 @@
import React, { forwardRef, useImperativeHandle, useState, memo } from 'react';
import cx from 'classnames';
+import { CSSItemTypeIcon } from 'components/icons';
const MAX_UNEXPANDED_ALL_NOTES = 7;
@@ -40,7 +41,7 @@ const NoteRow = memo(({ id, title, body, date, onClick, onKeyDown, onContextMenu
{ parentItemType
?
-
})
+
{parentTitle}
: null
diff --git a/chrome/content/zotero/contextPane.js b/chrome/content/zotero/contextPane.js
index dd3bed4348..4115d01466 100644
--- a/chrome/content/zotero/contextPane.js
+++ b/chrome/content/zotero/contextPane.js
@@ -28,6 +28,7 @@
var React = require('react');
var ReactDOM = require('react-dom');
var NotesList = require('components/itemPane/notesList').default;
+var { getCSSItemTypeIcon } = require('components/icons');
var ZoteroContextPane = new function () {
var _tabCover;
@@ -850,13 +851,12 @@ var ZoteroContextPane = new function () {
var parentItem = item.parentItem;
if (parentItem) {
var container = document.createElement('div');
- var img = document.createElement('img');
- img.src = Zotero.ItemTypes.getImageSrc(parentItem.itemType);
- img.className = 'parent-item-type';
+ var icon = getCSSItemTypeIcon(parentItem.getItemTypeIconName());
+ icon.classList.add('parent-item-type');
var title = document.createElement('div');
title.append(parentItem.getDisplayTitle());
title.className = 'parent-title';
- container.append(img, title);
+ container.append(icon, title);
parentTitleContainer.append(container);
}
_updateAddToNote();
diff --git a/chrome/content/zotero/elements/notesBox.js b/chrome/content/zotero/elements/notesBox.js
index b69c1964db..1ce5ab1566 100644
--- a/chrome/content/zotero/elements/notesBox.js
+++ b/chrome/content/zotero/elements/notesBox.js
@@ -25,6 +25,8 @@
"use strict";
+import { getCSSItemTypeIcon } from 'components/icons';
+
{
class NotesBox extends XULElement {
constructor() {
@@ -123,8 +125,7 @@
let notes = Zotero.Items.get(this._item.getNotes());
for (let item of notes) {
let id = item.id;
- let icon = document.createElement("img");
- icon.src = item.getImageSrc();
+ let icon = getCSSItemTypeIcon(item.getItemTypeIconName());
let label = document.createElement("label");
label.append(item.getDisplayTitle());
diff --git a/chrome/content/zotero/integration/addCitationDialog.js b/chrome/content/zotero/integration/addCitationDialog.js
index 9c9f45b16e..3d06436ca3 100644
--- a/chrome/content/zotero/integration/addCitationDialog.js
+++ b/chrome/content/zotero/integration/addCitationDialog.js
@@ -23,6 +23,8 @@
***** END LICENSE BLOCK *****
*/
+import { getCSSItemTypeIcon } from 'components/icons';
+
Components.utils.import("resource://gre/modules/Services.jsm");
var Zotero_Citation_Dialog = new function () {
@@ -835,8 +837,7 @@ var Zotero_Citation_Dialog = new function () {
}
itemNode.setAttribute("value", itemDataID);
- let image = document.createXULElement('image');
- image.src = item.getImageSrc();
+ let image = getCSSItemTypeIcon(item.getItemTypeIconName());
itemNode.append(image);
itemNode.setAttribute("class", "listitem-iconic");
itemNode.append(item.getDisplayTitle());
diff --git a/chrome/content/zotero/integration/editBibliographyDialog.js b/chrome/content/zotero/integration/editBibliographyDialog.js
index 85a44f942d..94a8669e05 100644
--- a/chrome/content/zotero/integration/editBibliographyDialog.js
+++ b/chrome/content/zotero/integration/editBibliographyDialog.js
@@ -23,6 +23,8 @@
***** END LICENSE BLOCK *****
*/
+import { getCSSItemTypeIcon } from 'components/icons';
+
var Zotero_Bibliography_Dialog = new function () {
var bibEditInterface;
var _lastSelectedItemID = false;
@@ -325,8 +327,7 @@ var Zotero_Bibliography_Dialog = new function () {
for(var i=0; i
+
+
+
+
+
+
diff --git a/chrome/skin/default/zotero/item-type/16/dark/attachment-epub-link@2x.svg b/chrome/skin/default/zotero/item-type/16/dark/attachment-epub-link@2x.svg
new file mode 100644
index 0000000000..29a3643416
--- /dev/null
+++ b/chrome/skin/default/zotero/item-type/16/dark/attachment-epub-link@2x.svg
@@ -0,0 +1,7 @@
+
diff --git a/chrome/skin/default/zotero/item-type/16/light/attachment-epub-link.svg b/chrome/skin/default/zotero/item-type/16/light/attachment-epub-link.svg
new file mode 100644
index 0000000000..ab5f26e3ad
--- /dev/null
+++ b/chrome/skin/default/zotero/item-type/16/light/attachment-epub-link.svg
@@ -0,0 +1,10 @@
+
diff --git a/chrome/skin/default/zotero/item-type/16/light/attachment-epub-link@2x.svg b/chrome/skin/default/zotero/item-type/16/light/attachment-epub-link@2x.svg
new file mode 100644
index 0000000000..ab5f26e3ad
--- /dev/null
+++ b/chrome/skin/default/zotero/item-type/16/light/attachment-epub-link@2x.svg
@@ -0,0 +1,10 @@
+
diff --git a/chrome/skin/default/zotero/item-type/16/white/attachment-epub-link.svg b/chrome/skin/default/zotero/item-type/16/white/attachment-epub-link.svg
new file mode 100644
index 0000000000..465d186d8c
--- /dev/null
+++ b/chrome/skin/default/zotero/item-type/16/white/attachment-epub-link.svg
@@ -0,0 +1,13 @@
+
diff --git a/chrome/skin/default/zotero/item-type/16/white/attachment-epub-link@2x.svg b/chrome/skin/default/zotero/item-type/16/white/attachment-epub-link@2x.svg
new file mode 100644
index 0000000000..7d417b2458
--- /dev/null
+++ b/chrome/skin/default/zotero/item-type/16/white/attachment-epub-link@2x.svg
@@ -0,0 +1,13 @@
+
diff --git a/chrome/skin/default/zotero/item-type/28/dark/attachment-epub-link.svg b/chrome/skin/default/zotero/item-type/28/dark/attachment-epub-link.svg
new file mode 100644
index 0000000000..107ee6fabc
--- /dev/null
+++ b/chrome/skin/default/zotero/item-type/28/dark/attachment-epub-link.svg
@@ -0,0 +1,14 @@
+
diff --git a/chrome/skin/default/zotero/item-type/28/light/attachment-epub-link.svg b/chrome/skin/default/zotero/item-type/28/light/attachment-epub-link.svg
new file mode 100644
index 0000000000..a301c33f38
--- /dev/null
+++ b/chrome/skin/default/zotero/item-type/28/light/attachment-epub-link.svg
@@ -0,0 +1,17 @@
+
diff --git a/chrome/skin/default/zotero/item-type/28/white/attachment-epub-link.svg b/chrome/skin/default/zotero/item-type/28/white/attachment-epub-link.svg
new file mode 100644
index 0000000000..b556365e7a
--- /dev/null
+++ b/chrome/skin/default/zotero/item-type/28/white/attachment-epub-link.svg
@@ -0,0 +1,7 @@
+
diff --git a/scss/components/_item-tree.scss b/scss/components/_item-tree.scss
index f3af76c51e..cbe32de2df 100644
--- a/scss/components/_item-tree.scss
+++ b/scss/components/_item-tree.scss
@@ -48,10 +48,12 @@
.cell.numNotes {
text-align: center;
}
+}
- $itemTypesIcons: (
+$-itemTypesIcons: (
artwork,
attachment-epub,
+ attachment-epub-link,
attachment-file, // mapped to document below
attachment-link,
attachment-pdf-link,
@@ -96,35 +98,46 @@
tv-broadcast,
video-recording,
webpage
- );
-
- $itemTypesMap: (
+);
+
+$-itemTypesMap: (
"attachment-file": "document"
- );
-
-
- .virtualized-table .row {
- .icon-item-type {
- width: 16px;
- height: 16px;
+);
+
+.icon-item-type {
+ width: 16px;
+ height: 16px;
+}
+
+// Due to quirks of the state() mixin, we need two sets of .icon-item-type rules:
+// one when the icon is within a virtualized-table, and one when it isn't. We declare
+// a mixin here to avoid duplication.
+
+@mixin -icon-item-type-rules($color) {
+ .icon-item-type {
+ // default icon, for known item types more specific selectors below will apply
+ @include svgicon("document", $color, "16", "item-type", true);
+ }
+
+ @each $itemTypeIcon in $-itemTypesIcons {
+ $itemType: camelCase(str-replace(str-replace($itemTypeIcon, "pdf", "PDF"), "epub", "EPUB"));
+
+ @if map.has-key($-itemTypesMap, $itemTypeIcon) {
+ $itemTypeIcon: map.get($-itemTypesMap, $itemTypeIcon);
}
-
- @include focus-states using ($color) {
- .icon-item-type {
- // default icon, for known item types more specific selectors below will apply
- @include svgicon("document", $color, "16", "item-type", true);
- }
- @each $itemTypeIcon in $itemTypesIcons {
- $itemType: camelCase(str-replace(str-replace($itemTypeIcon, "pdf", "PDF"), "epub", "EPUB"));
-
- @if map.has-key($itemTypesMap, $itemTypeIcon) {
- $itemTypeIcon: map.get($itemTypesMap, $itemTypeIcon);
- }
-
- .icon-item-type[data-item-type=#{$itemType}] {
- @include svgicon($itemTypeIcon, $color, "16", "item-type", true);
- }
- }
+
+ .icon-item-type[data-item-type=#{$itemType}] {
+ @include svgicon($itemTypeIcon, $color, "16", "item-type", true);
}
}
}
+
+@include focus-states using($color) {
+ @include -icon-item-type-rules($color);
+}
+
+.virtualized-table .row {
+ @include focus-states using($color) {
+ @include -icon-item-type-rules($color);
+ }
+}