mirror of
https://github.com/Foundry376/Mailspring.git
synced 2026-10-08 19:49:17 +02:00
* Mirror the OS accent / tint color in light and dark themes Adds a SystemAccentWatcher in the main process that reads the accent color via systemPreferences.getAccentColor() (supported on macOS, Windows, and Linux as of Electron 37+) and broadcasts changes over IPC. On Windows/Linux it subscribes to `accent-color-changed`; on macOS it listens for `AppleColorPreferencesChangedNotification`; on all platforms it also refreshes on nativeTheme `updated` events. The renderer-side ThemeManager injects the value as CSS custom properties (`--system-accent`, `--system-accent-dark`) in a managed <style> tag with priority 2, so switching tint doesn't bust the on-disk LESS cache or require recompilation. Accent-chain LESS variables and color-function usages (darken/lighten/ fade/fadeout/mix applied to @accent-primary / @component-active-color) are rewritten to use CSS color-mix() / relative color syntax, which LESS passes through to the browser. Per-theme defaults remain as the var() fallback so themes still look right when system accent is off. A new `core.appearance.useSystemAccent` preference (default on) provides a toggle in Preferences → Appearance → Theme and Style. * Fix LESS compile errors and color-mix transparent shift - Replace LESS color functions (fade, fadeout, desaturate, lighten, darken) on accent-chain variables with native CSS equivalents so LESS doesn't try to evaluate a var() at compile time. - Replace `color-mix(in srgb, transparent, X P%)` with `rgb(from X r g b / P%)` so we only change alpha without dragging RGB channels toward black (CSS `transparent` is rgba(0,0,0,0)). * Replace darken() on color-mix token vars darken(@token-hover-bottom/top, N%) and darken(@token-selected-*) broke LESS compile because those variables now resolve to color-mix() CSS expressions rather than literal colors. LESS's darken() only works on values it can evaluate to a color. The resulting LESS runtime error triggered theme-manager's encountered-theme-error IPC, which opens a blocking dialog.showMessageBoxSync in the main process — causing the test suite to hang for 20 minutes in headless CI. Swap those calls for `color-mix(in srgb, X, black N%)`, which LESS passes through as opaque CSS and composes correctly with color-mix values at runtime. * Replace darken() in text-emphasis/bg-variant LESS mixins .text-emphasis-variant(@color) and .bg-variant(@color) in the static/style/mixins directory call darken(@color, 10%) on their argument. type.less calls both mixins with @accent-primary, which is now a var(--system-accent, ...) expression rather than a literal color — LESS can't evaluate darken() on that and throws during compile of static/style/index.less. The broken compile surfaces via theme-manager's encountered-theme-error IPC which opens a blocking dialog.showMessageBoxSync on the main process, hanging the test suite for 20 minutes in headless CI. Swap for color-mix(in srgb, @color, black 10%) which LESS passes through as CSS. * Place system-accent toggle inline with Change Theme button The useSystemAccent ConfigSchemaItem was rendering on its own line below the large "Change Theme..." button, leaving the space to the right of that button empty. Wrap both in a flex row with a 20px gap so the checkbox sits alongside the button. * Drop useSystemAccent note and prevent button shrink The useSystemAccent setting is self-explanatory from its title. Remove the explanatory note. Add flex-shrink: 0 to the Change Theme button so it keeps its full width when the inline checkbox content grows. The default of true was already in place, so users are opted in. --------- Co-authored-by: Claude <noreply@anthropic.com>
190 lines
4.3 KiB
Plaintext
190 lines
4.3 KiB
Plaintext
@import 'ui-variables';
|
|
@import 'ui-mixins';
|
|
|
|
@count-color: fadeout(@text-color-subtle, 40%);
|
|
|
|
.outline-view {
|
|
order: 1;
|
|
|
|
section {
|
|
margin-bottom: @padding-base-vertical;
|
|
}
|
|
|
|
.item-children {
|
|
padding-left: @padding-base-horizontal;
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
.heading {
|
|
display: flex;
|
|
align-items: center;
|
|
cursor: default;
|
|
color: @text-color-very-subtle;
|
|
font-weight: @font-weight-semi-bold;
|
|
font-size: @font-size-small * 0.9;
|
|
padding-left: @padding-small-horizontal;
|
|
padding-top: @padding-small-horizontal;
|
|
padding-right: @padding-xs-horizontal;
|
|
letter-spacing: -0.2px;
|
|
|
|
span:first-child {
|
|
text-overflow: ellipsis;
|
|
overflow: hidden;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.add-item-button {
|
|
margin-left: @padding-small-horizontal;
|
|
margin-right: @padding-small-horizontal;
|
|
cursor: pointer;
|
|
img {
|
|
background: @text-color-very-subtle;
|
|
}
|
|
display: none;
|
|
}
|
|
|
|
.collapse-button {
|
|
cursor: pointer;
|
|
display: none;
|
|
min-width: 30px;
|
|
margin-left: auto;
|
|
margin-right: 8px;
|
|
}
|
|
}
|
|
|
|
&:hover {
|
|
.heading {
|
|
.collapse-button,
|
|
.add-item-button {
|
|
display: inherit;
|
|
}
|
|
}
|
|
}
|
|
|
|
.item-container {
|
|
display: flex;
|
|
&.dropping {
|
|
background-color: lighten(@source-list-bg, 20%);
|
|
.item {
|
|
color: @source-list-active-color;
|
|
img.content-mask {
|
|
background-color: @source-list-active-color;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
.item {
|
|
color: @text-color-subtle;
|
|
flex: 1;
|
|
display: flex;
|
|
align-items: center;
|
|
font-size: @font-size-base;
|
|
font-weight: 400;
|
|
padding-right: @spacing-standard;
|
|
line-height: @line-height-large;
|
|
clear: both;
|
|
height: 27px;
|
|
|
|
// The overflow needs to be `hidden` in order for the name to flex
|
|
// fit within the contained space.
|
|
overflow: hidden;
|
|
|
|
img.content-mask {
|
|
background-color: @text-color-subtle;
|
|
vertical-align: text-bottom;
|
|
}
|
|
|
|
.icon {
|
|
flex-shrink: 0;
|
|
padding-right: @padding-small-horizontal * 0.85;
|
|
order: 1;
|
|
}
|
|
.name {
|
|
order: 2;
|
|
overflow: hidden;
|
|
line-height: @line-height-small;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
}
|
|
.item-count-box {
|
|
order: 3;
|
|
flex-shrink: 0;
|
|
font-weight: @font-weight-semi-bold;
|
|
color: @count-color;
|
|
margin-left: @padding-small-horizontal * 0.8;
|
|
box-shadow: 0 0.5px 0 @count-color, 0 -0.5px 0 @count-color, 0.5px 0 0 @count-color,
|
|
-0.5px 0 0 @count-color;
|
|
}
|
|
.item-count-box.alt-count {
|
|
color: @source-list-active-bg;
|
|
background: @source-list-active-color;
|
|
box-shadow: none;
|
|
}
|
|
.item-count-box.archive,
|
|
.item-count-box.all,
|
|
.item-count-box.spam {
|
|
display: none;
|
|
}
|
|
.item-action-button {
|
|
order: 4;
|
|
flex-shrink: 0;
|
|
margin-left: auto;
|
|
cursor: pointer;
|
|
font-size: @font-size-base * 0.5;
|
|
letter-spacing: 1px;
|
|
line-height: 18px;
|
|
width: 18px;
|
|
text-align: center;
|
|
border-radius: 3px;
|
|
color: @text-color-very-subtle;
|
|
display: none;
|
|
&:hover {
|
|
color: @text-color-subtle;
|
|
background: fade(@text-color-subtle, 15%);
|
|
}
|
|
}
|
|
|
|
&.selected {
|
|
background: @source-list-active-bg;
|
|
color: @source-list-active-color;
|
|
img.content-mask {
|
|
background-color: @source-list-active-color;
|
|
}
|
|
.item-action-button {
|
|
color: rgb(from @source-list-active-color r g b / 70%);
|
|
&:hover {
|
|
color: @source-list-active-color;
|
|
background: rgb(from @source-list-active-color r g b / 15%);
|
|
}
|
|
}
|
|
}
|
|
&.dropping {
|
|
background-color: lighten(@source-list-bg, 20%);
|
|
color: @source-list-active-color;
|
|
img.content-mask {
|
|
background-color: @source-list-active-color;
|
|
}
|
|
}
|
|
&.editing {
|
|
align-items: center;
|
|
|
|
.item-input {
|
|
order: 2;
|
|
font-size: @font-size-small;
|
|
margin-left: @padding-small-horizontal * 0.3;
|
|
height: 22px;
|
|
padding-left: 0;
|
|
text-indent: @padding-small-horizontal * 0.55;
|
|
width: 85%;
|
|
}
|
|
}
|
|
&:hover {
|
|
cursor: default;
|
|
.item-action-button {
|
|
display: block;
|
|
}
|
|
}
|
|
}
|
|
}
|