74b86a7033
And include in stylesheets that have been updated. Have to make sure not to include this mixin in the global scope in stylesheets that are themselves imported elsewhere (i.e., filename begins with an underscore).
355 lines
8.5 KiB
SCSS
355 lines
8.5 KiB
SCSS
@use 'sass:color';
|
|
@use "sass:map";
|
|
//
|
|
// Mixins
|
|
// --------------------------------------------------
|
|
|
|
@mixin compact {
|
|
$selector: &;
|
|
@at-root [zoteroUIDensity="compact"] {
|
|
@if $selector {
|
|
#{$selector} {
|
|
@content;
|
|
}
|
|
}
|
|
|
|
@else {
|
|
@content;
|
|
}
|
|
}
|
|
}
|
|
|
|
@mixin comfortable {
|
|
$selector: &;
|
|
@at-root [zoteroUIDensity="comfortable"] {
|
|
@if $selector {
|
|
#{$selector} {
|
|
@content;
|
|
}
|
|
}
|
|
|
|
@else {
|
|
@content;
|
|
}
|
|
}
|
|
}
|
|
|
|
// @NOTE: this mixin uses `state` mixin, therefore must be used in a selector nested
|
|
// underneath selectors listed in arguments, e.g., .virtualized-table .row
|
|
// by default. See `state` mixin for more details.
|
|
@mixin focus-states(
|
|
$selectedState: '.row.selected',
|
|
$focused: '.virtualized-table:focus-within'
|
|
) {
|
|
@media (prefers-color-scheme: light) {
|
|
@content("light");
|
|
|
|
@include state($selectedState) {
|
|
@include state($focused) {
|
|
@content("white");
|
|
}
|
|
}
|
|
}
|
|
|
|
@media (prefers-color-scheme: dark) {
|
|
@content("dark");
|
|
|
|
@include state($selectedState) {
|
|
@include state($focused) {
|
|
@content("white");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// An implementation of Firefox light-dark() CSS mixin, which is not supported in 102
|
|
@mixin light-dark($prop, $light-color, $dark-color) {
|
|
@media (prefers-color-scheme: light) {
|
|
#{$prop}: $light-color;
|
|
}
|
|
@media (prefers-color-scheme: dark) {
|
|
#{$prop}: $dark-color;
|
|
}
|
|
}
|
|
|
|
@mixin color-scheme {
|
|
@media (prefers-color-scheme: light) {
|
|
@content("light");
|
|
}
|
|
|
|
@media (prefers-color-scheme: dark) {
|
|
@content("dark");
|
|
}
|
|
}
|
|
|
|
@mixin clicky-item {
|
|
display: flex;
|
|
align-items: flex-start;
|
|
gap: 4px;
|
|
padding-inline-start: 4px;
|
|
overflow: hidden;
|
|
border-radius: 5px;
|
|
|
|
&:not([disabled]):hover {
|
|
background-color: var(--fill-quinary);
|
|
}
|
|
|
|
&:not([disabled]):active {
|
|
background-color: var(--fill-quarternary);
|
|
}
|
|
|
|
.icon {
|
|
height: calc(1.3333333333 * var(--zotero-font-size));
|
|
}
|
|
|
|
.label {
|
|
display: -webkit-box;
|
|
-webkit-box-orient: vertical;
|
|
-webkit-line-clamp: 10;
|
|
width: 0; // Needed to allow the label to shrink for some reason
|
|
flex: 1;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.icon, .label {
|
|
padding-block: 2px;
|
|
}
|
|
}
|
|
|
|
@mixin meta-table {
|
|
display: grid;
|
|
grid-template-columns: max-content 1fr;
|
|
column-gap: 8px;
|
|
row-gap: 2px;
|
|
width: inherit;
|
|
|
|
.meta-row {
|
|
display: grid;
|
|
grid-template-columns: subgrid;
|
|
grid-column: span 2;
|
|
|
|
&[hidden] {
|
|
display: none;
|
|
}
|
|
|
|
&:not(:hover):not(:focus-within) .show-on-hover,
|
|
&.noHover .show-on-hover {
|
|
clip-path: inset(50%);
|
|
&.no-display {
|
|
width: 0;
|
|
height: 0;
|
|
padding: 0;
|
|
}
|
|
}
|
|
.meta-data {
|
|
width: 0;
|
|
min-width: 100%;
|
|
display: flex;
|
|
toolbarbutton {
|
|
margin-inline-start: 4px;
|
|
}
|
|
|
|
}
|
|
editable-text {
|
|
flex: 1; // stretch value field as much as possible
|
|
max-width: 100%; // stay within .meta-data when the itemBox is narrow
|
|
.input {
|
|
// allow input to be shrunk by other elements when the itemBox is narrow
|
|
min-width: 0;
|
|
}
|
|
}
|
|
|
|
.meta-label {
|
|
display: flex;
|
|
font-weight: normal;
|
|
text-align: end;
|
|
color: var(--fill-secondary);
|
|
|
|
&[fieldname^="creator"] {
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
}
|
|
> label {
|
|
margin-top: 2px;
|
|
@include comfortable {
|
|
margin-top: 3px;
|
|
}
|
|
}
|
|
}
|
|
|
|
.key {
|
|
width: 100%;
|
|
}
|
|
|
|
toolbarbutton {
|
|
@include focus-ring;
|
|
|
|
// needed to have the outline appear on all platforms
|
|
appearance: none;
|
|
-moz-appearance: none;
|
|
align-self: center;
|
|
// Make all buttons tigher to not stretch the rows
|
|
height: auto;
|
|
width: auto;
|
|
padding: 1px;
|
|
border-radius: 2px;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* 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;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
@mixin macOS-inactive-opacity {
|
|
$selector: &;
|
|
@at-root {
|
|
@media (-moz-platform: macos) {
|
|
#{$selector} {
|
|
&:-moz-window-inactive {
|
|
opacity: 0.6;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Normalize margins/paddings for form controls on macOS
|
|
@mixin macOS-normalize-controls {
|
|
:is(button, toolbarbutton) .button-text {
|
|
@media (-moz-platform: macos) {
|
|
margin-block: 1px 0;
|
|
margin-inline: 3px;
|
|
}
|
|
}
|
|
|
|
radiogroup {
|
|
@media (-moz-platform: macos) {
|
|
margin: 0;
|
|
column-gap: 8px;
|
|
}
|
|
}
|
|
|
|
radio, checkbox {
|
|
@media (-moz-platform: macos) {
|
|
margin: 0;
|
|
gap: 6px;
|
|
}
|
|
}
|
|
|
|
radio :is(.radio-check, .radio-check[checked], .radio-icon, .radio-label),
|
|
checkbox :is(.checkbox-check, .checkbox-check[checked], .checkbox-icon, .checkbox-label) {
|
|
@media (-moz-platform: macos) {
|
|
margin: 0;
|
|
|
|
// Can't break these out into separate rules because of specificity:
|
|
|
|
&:is(.radio-check, .checkbox-check) {
|
|
margin-inline-start: -2px;
|
|
}
|
|
|
|
&:is(.checkbox-label) {
|
|
margin-top: -1px;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
This mixin replaces the default focus-rings - those are platform-specific, do not show up on some
|
|
components (e.g. toolbarbutton) and sometimes are too wide (e.g. around textfield on macOS).
|
|
Box-shadow is used to be able to set the radius.
|
|
*/
|
|
@mixin focus-ring($thin: false, $selector: focus-visible) {
|
|
&:#{$selector} {
|
|
@media (-moz-platform: windows) {
|
|
outline: var(--color-focus-outer-border) solid var(--width-focus-outer-border);
|
|
outline-offset: var(--width-focus-border);
|
|
box-shadow: 0 0 0 var(--width-focus-border) var(--color-focus-border);
|
|
}
|
|
|
|
@media not (-moz-platform: windows) {
|
|
// fx115: Necessary to hide default focus ring
|
|
outline: none;
|
|
box-shadow: 0 0 0 var(--width-focus-border) var(--color-focus-border);
|
|
|
|
@if $thin {
|
|
--width-focus-border: 1px;
|
|
--color-focus-border: var(--color-accent);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
@mixin derive-colors($colors) {
|
|
@each $name, $color in $colors {
|
|
--#{$name}: #{$color};
|
|
}
|
|
|
|
// composite (opaque) colors
|
|
--color-quinary-on-background: #{color.mix(
|
|
map.get($colors, "color-background"), color.change(map.get($colors, "fill-quinary"), $alpha: 1), 100% * (1 - color.alpha(map.get($colors, "fill-quinary")))
|
|
)};
|
|
--color-quarternary-on-background: #{color.mix(
|
|
map.get($colors, "color-background"), color.change(map.get($colors, "fill-quarternary"), $alpha: 1), 100% * (1 - color.alpha(map.get($colors, "fill-quarternary")))
|
|
)};
|
|
--color-quinary-on-sidepane: #{color.mix(
|
|
map.get($colors, "color-sidepane"), color.change(map.get($colors, "fill-quinary"), $alpha: 1), 100% * (1 - color.alpha(map.get($colors, "fill-quinary")))
|
|
)};
|
|
--color-quarternary-on-sidepane: #{color.mix(
|
|
map.get($colors, "color-sidepane"), color.change(map.get($colors, "fill-quarternary"), $alpha: 1), 100% * (1 - color.alpha(map.get($colors, "fill-quarternary")))
|
|
)};
|
|
--color-stripe-on-background: #{color.mix(
|
|
map.get($colors, "color-background"), color.change(map.get($colors, "color-stripe"), $alpha: 1), 100% * (1 - color.alpha(map.get($colors, "color-stripe")))
|
|
)};
|
|
--color-menu-opaque: rgb(
|
|
#{color.alpha(map.get($colors, "color-menu")) * color.red(map.get($colors, "color-menu"))},
|
|
#{color.alpha(map.get($colors, "color-menu")) * color.green(map.get($colors, "color-menu"))},
|
|
#{color.alpha(map.get($colors, "color-menu")) * color.blue(map.get($colors, "color-menu"))}
|
|
);
|
|
|
|
// background materials
|
|
--material-background: var(--color-background);
|
|
--material-background50: var(--color-background50);
|
|
--material-background70: var(--color-background70);
|
|
--material-button: var(--color-button);
|
|
--material-control: var(--color-control);
|
|
--material-menu: var(--color-menu);
|
|
--material-sidepane: var(--color-sidepane);
|
|
--material-tabbar: var(--color-tabbar);
|
|
--material-toolbar: var(--color-toolbar);
|
|
--material-mix-quinary: var(--color-quinary-on-background);
|
|
--material-mix-quarternary: var(--color-quarternary-on-background);
|
|
--material-stripe: var(--color-stripe-on-background);
|
|
|
|
// border materials
|
|
--material-border-transparent: 1px solid transparent;
|
|
--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);
|
|
--material-border-quarternary: 1px solid var(--fill-quarternary);
|
|
}
|
|
|
|
@mixin contain-richlistbox {
|
|
// richlistbox elements are crazy and will expand beyond the window size
|
|
// unless all/most elements in the hierarchy that contain that
|
|
// richlistbox have a min-height: 0 set
|
|
vbox, hbox {
|
|
min-height: 0;
|
|
}
|
|
}
|