diff --git a/chrome/content/zotero/components/button.jsx b/chrome/content/zotero/components/button.jsx index ca4c6c9cab..b809299344 100644 --- a/chrome/content/zotero/components/button.jsx +++ b/chrome/content/zotero/components/button.jsx @@ -27,7 +27,7 @@ const React = require('react') const { PureComponent, createElement: create } = React -const { IconDownChevron } = require('./icons') +const { CSSIcon } = require('./icons') const cx = require('classnames') const { bool, element, func, node, number, oneOf, string @@ -77,7 +77,7 @@ class Button extends PureComponent { if (!Zotero.isNode && Zotero.isLinux) { return this.props.isMenu && } - return this.props.isMenu && + return this.props.isMenu && } get attributes() { diff --git a/chrome/content/zotero/components/tagSelector.jsx b/chrome/content/zotero/components/tagSelector.jsx index 774fe4874d..e98f43067f 100644 --- a/chrome/content/zotero/components/tagSelector.jsx +++ b/chrome/content/zotero/components/tagSelector.jsx @@ -29,7 +29,7 @@ const React = require('react'); const PropTypes = require('prop-types'); const TagList = require('./tagSelector/tagSelectorList'); const { Button } = require('./button'); -const { IconTagSelectorMenu } = require('./icons'); +const { CSSIcon } = require('./icons'); const Search = require('./search'); class TagSelector extends React.PureComponent { @@ -46,21 +46,26 @@ class TagSelector extends React.PureComponent { width={this.props.width} height={this.props.height} fontSize={this.props.fontSize} + lineHeight={this.props.lineHeight} + uiDensity={this.props.uiDensity} /> -
- -
); @@ -88,6 +93,8 @@ TagSelector.propTypes = { width: PropTypes.number.isRequired, height: PropTypes.number.isRequired, fontSize: PropTypes.number.isRequired, + lineHeight: PropTypes.number.isRequired, + uiDensity: PropTypes.string.isRequired, // Search searchBoxRef: PropTypes.object, diff --git a/chrome/content/zotero/components/tagSelector/tagSelectorList.jsx b/chrome/content/zotero/components/tagSelector/tagSelectorList.jsx index d5cf9e51ff..a5940d9175 100644 --- a/chrome/content/zotero/components/tagSelector/tagSelectorList.jsx +++ b/chrome/content/zotero/components/tagSelector/tagSelectorList.jsx @@ -26,21 +26,21 @@ const React = require('react'); const PropTypes = require('prop-types'); var { Collection } = require('react-virtualized'); +const { props } = require("bluebird"); // See also .tag-selector-item in _tag-selector.scss -var filterBarHeight = 32; -var tagPaddingTop = 4; -var tagPaddingLeft = 2; -var tagPaddingRight = 2; -var tagPaddingBottom = 4; -var tagSpaceBetweenX = 7; +var filterBarHeight = 36; +var tagPaddingLeft = 4; +var tagPaddingRight = 4; +var tagSpaceBetweenX = 2; var tagSpaceBetweenY = 4; -var panePaddingTop = 2; -var panePaddingLeft = 2; -var panePaddingRight = 25; +var panePaddingTop = 8; +var panePaddingLeft = 8; +var panePaddingRight = 2; // + scrollbar width //var panePaddingBottom = 2; var minHorizontalPadding = panePaddingLeft + tagPaddingLeft + tagPaddingRight + panePaddingRight; + class TagList extends React.PureComponent { constructor(props) { super(props); @@ -53,11 +53,13 @@ class TagList extends React.PureComponent { // Redraw all tags on every refresh if (this.collectionRef && this.collectionRef.current) { // If width or height changed, recompute positions. It seems like this should happen - // automatically, but it doesn't as of 9.21.0. + // automatically, but it doesn't as of 9.21.0. Also check for density change. + if (prevProps.height != this.props.height || prevProps.width != this.props.width - || prevProps.fontSize != this.props.fontSize - || prevProps.tags != this.props.tags) { + || prevProps.lineHeight != this.props.lineHeight + || prevProps.tags != this.props.tags + || prevProps.uiDensity !== this.props.uiDensity) { this.collectionRef.current.recomputeCellSizesAndPositions(); } // If dimensions didn't change, just redraw at current positions. Without this, clicking @@ -94,8 +96,12 @@ class TagList extends React.PureComponent { * Calculate the x,y coordinates of all tags */ updatePositions() { - var tagMaxWidth = this.props.width - minHorizontalPadding; - var rowHeight = tagPaddingTop + this.props.fontSize + tagPaddingBottom + tagSpaceBetweenY; + const tagPaddingTop = this.props.uiDensity === 'comfortable' ? 2 : 1; + const tagPaddingBottom = tagPaddingTop; + this.scrollbarWidth = Zotero.Utilities.Internal.getScrollbarWidth(); + + var tagMaxWidth = this.props.width - minHorizontalPadding - this.scrollbarWidth; + var rowHeight = tagPaddingTop + this.props.lineHeight + tagPaddingBottom + tagSpaceBetweenY; var positions = []; var row = 0; let rowX = panePaddingLeft; @@ -113,9 +119,11 @@ class TagList extends React.PureComponent { shouldAddSeparator = true; forceNewLine = true; } - let tagWidth = tagPaddingLeft + Math.min(tag.width, tagMaxWidth) + tagPaddingRight; + // size of the colored dot + space between the dot and the tag name always sums up to fontSize (e.g., 8px + 3px at 11px fontSize) + const tagColorWidth = (tag.color && !Zotero.Utilities.Internal.isOnlyEmoji(tag.name)) ? this.props.fontSize : 0; + let tagWidth = tagPaddingLeft + Math.min(tag.width, tagMaxWidth) + tagPaddingRight + tagColorWidth; // If first row or cell fits, add to current row - if (!forceNewLine && (i == 0 || ((rowX + tagWidth) < (this.props.width - panePaddingLeft - panePaddingRight)))) { + if (!forceNewLine && (i == 0 || ((rowX + tagWidth) < (this.props.width - panePaddingRight - this.scrollbarWidth)))) { positions[i] = [rowX, panePaddingTop + (row * rowHeight)]; } // Otherwise, start new row @@ -135,10 +143,10 @@ class TagList extends React.PureComponent { } cellSizeAndPositionGetter = ({ index }) => { - var tagMaxWidth = this.props.width - minHorizontalPadding; + var tagMaxWidth = this.props.width - minHorizontalPadding - this.scrollbarWidth; return { width: Math.min(this.props.tags[index].width, tagMaxWidth), - height: this.props.fontSize, + height: this.props.lineHeight, x: this.positions[index][0], y: this.positions[index][1] }; @@ -149,7 +157,7 @@ class TagList extends React.PureComponent { const { onDragOver, onDragExit, onDrop } = this.props.dragObserver; - var className = 'tag-selector-item zotero-clicky'; + var className = 'tag-selector-item'; if (tag.selected) { className += ' selected'; } @@ -159,6 +167,9 @@ class TagList extends React.PureComponent { if (tag.disabled) { className += ' disabled'; } + if (Zotero.Utilities.Internal.isOnlyEmoji(tag.name)) { + className += ' emoji'; + } let props = { className, @@ -176,7 +187,7 @@ class TagList extends React.PureComponent { // Don't specify explicit width unless we're truncating, because for some reason the width // from canvas can sometimes be slightly smaller than the actual width, resulting in an // unnecessary ellipsis. - var tagMaxWidth = this.props.width - minHorizontalPadding; + var tagMaxWidth = this.props.width - minHorizontalPadding - this.scrollbarWidth; if (props.style.width < tagMaxWidth) { delete props.style.width; } @@ -190,11 +201,12 @@ class TagList extends React.PureComponent { if (tag.color) { props.style.color = tag.color; + props['data-color'] = tag.color.toLowerCase(); } return (
- {tag.name} + {tag.name}
); } @@ -265,6 +277,8 @@ class TagList extends React.PureComponent { width: PropTypes.number.isRequired, height: PropTypes.number.isRequired, fontSize: PropTypes.number.isRequired, + lineHeight: PropTypes.number.isRequired, + uiDensity: PropTypes.string.isRequired }; } diff --git a/chrome/content/zotero/containers/tagSelectorContainer.jsx b/chrome/content/zotero/containers/tagSelectorContainer.jsx index a7e529ac5c..1a443dd974 100644 --- a/chrome/content/zotero/containers/tagSelectorContainer.jsx +++ b/chrome/content/zotero/containers/tagSelectorContainer.jsx @@ -42,6 +42,9 @@ const defaults = { }; const { Cc, Ci } = require('chrome'); +// first n tags will be measured using DOM method for more accurate measurment (at the cost of performance) +const FORCE_DOM_TAGS_FOR_COUNT = 200; + Zotero.TagSelector = class TagSelectorContainer extends React.PureComponent { constructor(props) { super(props); @@ -50,7 +53,10 @@ Zotero.TagSelector = class TagSelectorContainer extends React.PureComponent { ['collection-item', 'item', 'item-tag', 'tag', 'setting'], 'tagSelector' ); - this._prefObserverID = Zotero.Prefs.registerObserver('fontSize', this.handleFontChange.bind(this)); + this._prefObserverID = Zotero.Prefs.registerObserver('fontSize', this.handleUIPropertiesChange.bind(this)); + this._prefObserverID = Zotero.Prefs.registerObserver('uiDensity', this.handleUIPropertiesChange.bind(this)); + this._mediaQueryList = window.matchMedia("(min-resolution: 1.5dppx)"); + this._mediaQueryList.addEventListener("change", this.handleUIPropertiesChange.bind(this)); this.tagListRef = React.createRef(); this.searchBoxRef = React.createRef(); @@ -66,7 +72,8 @@ Zotero.TagSelector = class TagSelectorContainer extends React.PureComponent { this.state = { ...defaults, ...this.getContainerDimensions(), - ...this.getFontInfo() + ...this.getFontInfo(), + isHighDensity: this._mediaQueryList.matches }; } @@ -357,6 +364,7 @@ Zotero.TagSelector = class TagSelectorContainer extends React.PureComponent { container.appendChild(elem); var style = window.getComputedStyle(elem); var props = { + lineHeight: style.getPropertyValue('line-height'), fontSize: style.getPropertyValue('font-size'), fontFamily: style.getPropertyValue('font-family') }; @@ -365,36 +373,61 @@ Zotero.TagSelector = class TagSelectorContainer extends React.PureComponent { } /** - * Recompute tag widths based on the current font settings + * Recompute tag widths when either font, UI density or pixel density changes */ - handleFontChange() { + handleUIPropertiesChange(ev) { this.widths.clear(); this.widthsBold.clear(); + const isHighDensity = ev.target instanceof MediaQueryList ? ev.matches : this.state.isHighDensity; this.setState({ - ...this.getFontInfo() + ...this.getFontInfo(), + uiDensity: Zotero.Prefs.get('uiDensity'), + isHighDensity }); } /** * Uses canvas.measureText to compute and return the width of the given text of given font in pixels. + * Except for emoji tags, where, on high-density screens, we use actual DOM element for more accurate + * measurement (which is 4-5x slower) because canvas method can be off by enough to cause visible artifacts. + * It's possible to force use of DOM method for other tags using forceUseDOM parameter. * * @param {String} text The text to be rendered. * @param {String} font The css font descriptor that text is to be rendered with (e.g. "bold 14px verdana"). + * @param {String} forceUseDOM Force use of DOM method for measuring text width * * @see https://stackoverflow.com/questions/118241/calculate-text-width-with-javascript/21015393#21015393 */ - getTextWidth(text, font) { - // re-use canvas object for better performance - var canvas = this.canvas || (this.canvas = document.createElement("canvas")); - var context = canvas.getContext("2d"); - context.font = font; - // Add a little more to make sure we don't crop - var metrics = context.measureText(text); - return Math.ceil(metrics.width); + getTextWidth(text, font, forceUseDOM = false) { + let width; + const useDOM = forceUseDOM || (this.state.isHighDensity && Zotero.Utilities.Internal.includesEmoji(text)); + if (useDOM) { + if (!this.divMeasure) { + this.divMeasure = document.createElement('div'); + this.divMeasure.style.position = 'absolute'; + this.divMeasure.style.top = '-9999px'; + this.divMeasure.whiteSpace = 'nowrap'; + document.querySelector('#zotero-tag-selector').appendChild(this.divMeasure); + } + + this.divMeasure.style.font = font; + this.divMeasure.textContent = text; + width = this.divMeasure.clientWidth; + this.divMeasure.textContent = ''; + } + else { + // re-use canvas object for better performance + var canvas = this.canvas || (this.canvas = document.createElement("canvas")); + var context = canvas.getContext("2d"); + context.font = font; + var metrics = context.measureText(text); + width = metrics.width; + } + + return width; } - getWidth(name) { - var num = 0; + getWidth(name, forceUseDOM = false) { var font = this.state.fontSize + ' ' + this.state.fontFamily; // Colored tags are shown in bold, which results in a different width var fontBold = 'bold ' + font; @@ -402,8 +435,8 @@ Zotero.TagSelector = class TagSelectorContainer extends React.PureComponent { let widths = hasColor ? this.widthsBold : this.widths; let width = widths.get(name); if (width === undefined) { - width = this.getTextWidth(name, hasColor ? fontBold : font); - //Zotero.debug(`Calculated ${hasColor ? 'bold ' : ''}width of ${width} for tag '${name}'`); + width = this.getTextWidth(name, hasColor ? fontBold : font, forceUseDOM); + // Zotero.debug(`Calculated ${hasColor ? 'bold ' : ''}width of ${width} for tag '${name}' using ${forceUseDOM ? 'DOM' : 'hybrid'} method`); widths.set(name, width); } return width; @@ -460,7 +493,7 @@ Zotero.TagSelector = class TagSelectorContainer extends React.PureComponent { // Prepare tag objects for list component //var d = new Date(); var inTagColors = true; - tags = tags.map((tag) => { + tags = tags.map((tag, i) => { let name = tag.tag; tag = { name, @@ -480,10 +513,14 @@ Zotero.TagSelector = class TagSelectorContainer extends React.PureComponent { if ((this.displayAllTags || inTagColors) && !this.state.scope.has(name)) { tag.disabled = true; } - tag.width = this.getWidth(name); + const forceUseDOM = this.state.isHighDensity && i < FORCE_DOM_TAGS_FOR_COUNT; + tag.width = this.getWidth(name, forceUseDOM); return tag; }); - //Zotero.debug(`Prepared tags in ${new Date() - d} ms`); + // clean up divMeasure, which might have been used for measuring emoji tags + this.divMeasure?.parentNode?.removeChild?.(this.divMeasure); + this.divMeasure = null; + // Zotero.debug(`Prepared ${tags.length} tags in ${new Date() - d} ms`); return ; } diff --git a/chrome/content/zotero/xpcom/utilities_internal.js b/chrome/content/zotero/xpcom/utilities_internal.js index 32d8a5ffbc..1705a2f8e2 100644 --- a/chrome/content/zotero/xpcom/utilities_internal.js +++ b/chrome/content/zotero/xpcom/utilities_internal.js @@ -416,6 +416,12 @@ Zotero.Utilities.Internal = { const re = /\p{Extended_Pictographic}|\u200D|\uFE0F/gu; return !str.replace(re, ''); }, + + includesEmoji: function (str) { + // Remove emoji, Zero Width Joiner, and Variation Selector-16 and compare lengths + const re = /\p{Extended_Pictographic}|\u200D|\uFE0F/gu; + return str.replace(re, '').length !== str.length; + }, /** * Display a prompt from an error with custom buttons and a callback @@ -2304,6 +2310,21 @@ Zotero.Utilities.Internal = { } return false; + }, + + getScrollbarWidth() { + let document = Zotero.getMainWindow().document; + let scrollDiv = document.createElement('div'); + scrollDiv.style.position = 'absolute'; + scrollDiv.style.top = '-9999px'; + scrollDiv.style.width = '50px'; + scrollDiv.style.height = '50px'; + scrollDiv.style.overflow = 'scroll'; + document.documentElement.appendChild(scrollDiv); + const scrollbarWidth = scrollDiv.getBoundingClientRect().width - scrollDiv.clientWidth; + document.documentElement.removeChild(scrollDiv); + + return scrollbarWidth; } } diff --git a/chrome/locale/en-US/zotero/zotero.ftl b/chrome/locale/en-US/zotero/zotero.ftl index b635392579..dc93261945 100644 --- a/chrome/locale/en-US/zotero/zotero.ftl +++ b/chrome/locale/en-US/zotero/zotero.ftl @@ -240,3 +240,6 @@ sidenav-related = abstract-field = .label = Add abstract… + +tagselector-search = + .placeholder = Filter Tags \ No newline at end of file diff --git a/chrome/skin/default/zotero/16/dark/filter.svg b/chrome/skin/default/zotero/16/dark/filter.svg new file mode 100644 index 0000000000..fcb63ce855 --- /dev/null +++ b/chrome/skin/default/zotero/16/dark/filter.svg @@ -0,0 +1,4 @@ + + + diff --git a/chrome/skin/default/zotero/16/light/filter.svg b/chrome/skin/default/zotero/16/light/filter.svg new file mode 100644 index 0000000000..b1f35f8255 --- /dev/null +++ b/chrome/skin/default/zotero/16/light/filter.svg @@ -0,0 +1,4 @@ + + + diff --git a/chrome/skin/default/zotero/8/dark/chevron-6.svg b/chrome/skin/default/zotero/8/dark/chevron-6.svg new file mode 100644 index 0000000000..378c49cc9e --- /dev/null +++ b/chrome/skin/default/zotero/8/dark/chevron-6.svg @@ -0,0 +1,3 @@ + + + diff --git a/chrome/skin/default/zotero/8/light/chevron-6.svg b/chrome/skin/default/zotero/8/light/chevron-6.svg new file mode 100644 index 0000000000..bde2fd825a --- /dev/null +++ b/chrome/skin/default/zotero/8/light/chevron-6.svg @@ -0,0 +1,3 @@ + + + diff --git a/scss/abstracts/_variables.scss b/scss/abstracts/_variables.scss index 9c7f722f45..cf8f10ad8b 100644 --- a/scss/abstracts/_variables.scss +++ b/scss/abstracts/_variables.scss @@ -88,3 +88,15 @@ $item-pane-sections: ( "tags": var(--accent-orange), "related": var(--accent-wood), ); + +$tagColorsLookup: ( + '#ff6666': --tag-red, + '#ff8c19': --tag-orange, + '#999999': --tag-gray, + '#5fb236': --tag-green, + '#009980': --tag-teal, + '#2ea8e5': --tag-blue, + '#576dd9': --tag-indigo, + '#a28ae5': --tag-purple, + '#a6507b': --tag-plum, +); diff --git a/scss/base/_base.scss b/scss/base/_base.scss index f8a330e4af..2784558c89 100644 --- a/scss/base/_base.scss +++ b/scss/base/_base.scss @@ -8,7 +8,7 @@ font-style: normal; } -#zotero-collections-pane { +#zotero-collections-pane, #zotero-item-pane { background: var(--material-sidepane); } @@ -18,4 +18,4 @@ height: 150px; width: 290px; background: var(--material-background); -} \ No newline at end of file +} diff --git a/scss/components/_button.scss b/scss/components/_button.scss index 21efff6e82..bc3a42e70d 100644 --- a/scss/components/_button.scss +++ b/scss/components/_button.scss @@ -3,37 +3,31 @@ // -------------------------------------------------- .btn { - font: { - family: inherit; - size: inherit; - } - line-height: inherit; - color: inherit; - text-align: center; - -moz-appearance: toolbarbutton; + font: { + family: inherit; + size: inherit; + } + line-height: inherit; + color: inherit; + text-align: center; + -moz-appearance: toolbarbutton; - &[disabled], - &.disabled { - opacity: $btn-disabled-opacity; - } + &[disabled], + &.disabled { + opacity: $btn-disabled-opacity; + } } .btn-icon { - .icon { - &:first-child { - margin-left: -5px; - } - &:last-child { - margin-right: -5px; - } - svg, img { - vertical-align: middle; - } - } - span.menu-marker { - -moz-appearance: toolbarbutton-dropdown; - display: inline-block; - margin-right: -5px; - } + .icon { + svg, img { + vertical-align: middle; + } + } + span.menu-marker { + -moz-appearance: toolbarbutton-dropdown; + display: inline-block; + margin-left: 4px; + } } diff --git a/scss/components/_icons.scss b/scss/components/_icons.scss index fb9b5a98df..21dd3fcf74 100644 --- a/scss/components/_icons.scss +++ b/scss/components/_icons.scss @@ -1,26 +1,49 @@ .icon > svg, .icon > img { - width: 16px; + width: 16px; } .icon-bg { - width: 16px; - height: 16px; - display: inline-block; - background-repeat: no-repeat; - background-size: contain; - background-position: center; - vertical-align: middle; + width: 16px; + height: 16px; + display: inline-block; + background-repeat: no-repeat; + background-size: contain; + background-position: center; + vertical-align: middle; } .icon-css { - display: inline-block; - vertical-align: middle; + display: inline-block; + vertical-align: middle; } .icon.icon-downchevron { - width: 7px !important; + width: 7px !important; } .icon { - -moz-appearance: none !important; + -moz-appearance: none !important; } + +.icon-16 { + width: 16px; + height: 16px; +} + +.icon-8 { + width: 8px; + height: 8px; +} + +$-icons: ( + filter: 16, + chevron-6: 8 +); + +@each $icon, $size in $-icons { + .icon-#{$icon} { + @include color-scheme using($color) { + @include svgicon($icon, $color, $size); + } + } +} \ No newline at end of file diff --git a/scss/components/_mainWindow.scss b/scss/components/_mainWindow.scss index db50bfb822..252a56520a 100644 --- a/scss/components/_mainWindow.scss +++ b/scss/components/_mainWindow.scss @@ -133,14 +133,13 @@ #tab-bar-container .tab.selected { background: var(--material-tabbar) } - + .zotero-toolbar { -moz-appearance: none; + } + + #zotero-layout-switcher .zotero-toolbar { background: var(--material-tabbar); border-bottom: var(--material-panedivider); } - - #zotero-collections-tree > div, #zotero-item-pane { - background: var(--material-sidepane); - } } diff --git a/scss/components/_search.scss b/scss/components/_search.scss index cc372840a2..aaf69b8824 100644 --- a/scss/components/_search.scss +++ b/scss/components/_search.scss @@ -4,10 +4,25 @@ } .search input { + background: var(--material-background); + border-radius: 5px; + border: var(--material-border-quinary); + color: var(--fill-primary); flex: 1 0; - font-size: 1em; + margin: 6px 4px; min-width: 40px; - padding-left: 4px; + padding: 3px 7px; + + &::placeholder { + color: var(--fill-tertiary); + opacity: 1.0; + } + + &:focus { + outline: none; + border-color: SelectedItem; + box-shadow: 0 0 0 2px SelectedItem; + } } .search .search-cancel-button { diff --git a/scss/components/_tagSelector.scss b/scss/components/_tagSelector.scss index 9d3c86f827..83b3af4251 100644 --- a/scss/components/_tagSelector.scss +++ b/scss/components/_tagSelector.scss @@ -28,7 +28,6 @@ display: flex; overflow: hidden; height: 100px; - background: var(--material-sidepane); } .tag-selector-list-container > div { @@ -43,18 +42,22 @@ } .tag-selector-list { - list-style: none; display: inline-block; + list-style: none; margin: 0; padding: 0; + scrollbar-color: var(--color-scrollbar) var(--color-scrollbar-background); +} + +.tag-selector-filter-pane { + padding: 0 8px 0; } .tag-selector-filter-container { - height: 30px; - flex: 0 0 1em; + border-top: var(--material-panedivider); display: flex; flex-direction: row; - padding: 0.125em 0 0.125em 0.5em; + flex: 0 0 1em; } .tag-selector-filter-container .search { @@ -63,21 +66,79 @@ } .tag-selector-actions { - flex: 0 1; - display: block; - white-space: nowrap; + align-self: center; background-color: inherit; + border: 0; + display: block; + flex: 0 1; + padding: 3px 4px; + white-space: nowrap; } .tag-selector-item { + border-radius: 4px; cursor: pointer; + font-size: 0.916666667em; + line-height: 1.272727273; overflow: hidden; + padding: 1px 4px; text-overflow: ellipsis; white-space: pre; - padding: 1px 4px 3px; // See also TagSelectorList.jsx + + @include comfortable { + padding: 2px 4px; + } + + &:hover { + background-color: var(--fill-quinary); + } + + &.selected { + background-color: var(--fill-secondary); + + &:hover { + opacity: .75; + } + } &.colored { font-weight: bold; + + &.selected { + background-color: currentcolor; + + @each $colorHex, $colorVar in $tagColorsLookup { + @include state('.tag-selector-item[data-color="#{$colorHex}"]') { + background-color: var($colorVar); + } + } + } + + &:not(.emoji) { + &::before { + content: " "; + display: inline-block; + width: 0.636363636em; // 7px (+ 1px border = 8px) + height: 0.636363636em; + margin-right: .272727273em; + border-radius: 50%; + background-color: currentcolor; // fallback for non-standard colors + vertical-align: -0.363636364em; // -4px + border: var(--material-border-transparent); + + @include state('.tag-selector-item.selected') { + border-color: var(--color-background); + } + } + + @each $colorHex, $colorVar in $tagColorsLookup { + @include state('.tag-selector-item[data-color="#{$colorHex}"]') { + &::before { + background-color: var($colorVar); + } + } + } + } } &.disabled { @@ -89,4 +150,12 @@ color: var(--color-background); background-color: var(--fill-secondary); } + + span { + color: var(--fill-primary); + + @include state('.tag-selector-item.selected') { + color: var(--color-background); + } + } } diff --git a/scss/mac/_search.scss b/scss/mac/_search.scss index 8680b81d2a..78a6732df6 100644 --- a/scss/mac/_search.scss +++ b/scss/mac/_search.scss @@ -1,6 +1,5 @@ .search input { -moz-appearance: searchfield; - height: 24px; } .search .search-cancel-button { diff --git a/scss/mac/_tag-selector.scss b/scss/mac/_tag-selector.scss index 491d4d8a7a..25d00965b1 100644 --- a/scss/mac/_tag-selector.scss +++ b/scss/mac/_tag-selector.scss @@ -2,18 +2,4 @@ // Tag selector // -------------------------------------------------- -.tag-selector-filter-container { - padding: 0.25em 0 0.25em 0.5em; - border-top: var(--material-panedivider); -} -.tag-selector-item { - padding-bottom: .3em; -} - -.tag-selector-actions { - flex: none; - border: 0; - margin-right: 3px; - padding: 1px 6px 0; -} diff --git a/scss/themes/_dark.scss b/scss/themes/_dark.scss index b59bc77193..9b1449822c 100644 --- a/scss/themes/_dark.scss +++ b/scss/themes/_dark.scss @@ -31,6 +31,9 @@ --color-sidepane: #303030; --color-tabbar: #1e1e1e; --color-toolbar: #272727; + --color-scrollbar: rgb(117, 117, 117); + --color-scrollbar-hover: rgb(158, 158, 158); + --color-scrollbar-background: transparent; --tag-blue: #55a6dfd9; --tag-gray: #aaac; --tag-green: #74b04ad9; @@ -59,5 +62,6 @@ --material-border: 1px solid var(--color-border); --material-border50: 1px solid var(--color-border50); --material-panedivider: 1px solid var(--color-panedivider); + --material-border-quinary: 1px solid var(--fill-quinary); } } \ No newline at end of file diff --git a/scss/themes/_light.scss b/scss/themes/_light.scss index b618df29c5..13810c4b3e 100644 --- a/scss/themes/_light.scss +++ b/scss/themes/_light.scss @@ -31,6 +31,9 @@ --color-sidepane: #f2f2f2; --color-tabbar: #f2f2f2; --color-toolbar: #f9f9f9; + --color-scrollbar: rgb(194, 194, 194); + --color-scrollbar-hover: rgb(125, 125, 125); + --color-scrollbar-background: transparent; --tag-blue: #55a6df; --tag-gray: #aaa; --tag-green: #74b04a; @@ -59,5 +62,6 @@ --material-border: 1px solid var(--color-border); --material-border50: 1px solid var(--color-border50); --material-panedivider: 1px solid var(--color-panedivider); + --material-border-quinary: 1px solid var(--fill-quinary); } }