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); + } +}