From 8c0d4cde8637ed995d8052b741728ced775b0e61 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Mon, 26 Jan 2026 23:02:14 +0200 Subject: [PATCH 1/9] feat(desktop): basic vibrancy support --- apps/client/src/desktop.ts | 4 ++++ apps/server/src/services/window.ts | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/apps/client/src/desktop.ts b/apps/client/src/desktop.ts index cb90e998f2..69fff6e96b 100644 --- a/apps/client/src/desktop.ts +++ b/apps/client/src/desktop.ts @@ -108,6 +108,10 @@ function initTransparencyEffects(style: CSSStyleDeclaration, currentWindow: Elec currentWindow.setBackgroundMaterial(foundBgMaterialOption); } } + + if (window.glob.platform === "darwin") { + currentWindow.setVibrancy("under-window"); + } } /** diff --git a/apps/server/src/services/window.ts b/apps/server/src/services/window.ts index 019ec58e8b..af18dafb89 100644 --- a/apps/server/src/services/window.ts +++ b/apps/server/src/services/window.ts @@ -241,7 +241,8 @@ function getWindowExtraOpts() { // Window effects (Mica) if (optionService.getOptionBool("backgroundEffects")) { if (isMac) { - // Vibrancy not yet supported. + extraOpts.transparent = true; + extraOpts.visualEffectState = "active"; } else if (isWindows) { extraOpts.backgroundMaterial = "auto"; } else { From 120b767a68b742d1084bd979c9cf85a504c38b4b Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Mon, 26 Jan 2026 23:10:19 +0200 Subject: [PATCH 2/9] fix(desktop): background effects not applied correctly --- apps/server/src/routes/index.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/apps/server/src/routes/index.ts b/apps/server/src/routes/index.ts index 7bc59411a0..8f96e5124b 100644 --- a/apps/server/src/routes/index.ts +++ b/apps/server/src/routes/index.ts @@ -12,7 +12,7 @@ import log from "../services/log.js"; import optionService from "../services/options.js"; import protectedSessionService from "../services/protected_session.js"; import sql from "../services/sql.js"; -import { isDev, isElectron, isWindows11 } from "../services/utils.js"; +import { isDev, isElectron, isMac, isWindows11 } from "../services/utils.js"; import { generateToken as generateCsrfToken } from "./csrf_protection.js"; @@ -43,7 +43,10 @@ export function bootstrap(req: Request, res: Response) { platform: process.platform, isElectron, hasNativeTitleBar: isElectron && nativeTitleBarVisible, - hasBackgroundEffects: isElectron && isWindows11 && !nativeTitleBarVisible && options.backgroundEffects === "true", + hasBackgroundEffects: options.backgroundEffects === "true" + && isElectron + && (isWindows11 || isMac) + && !nativeTitleBarVisible, maxEntityChangeIdAtLoad: sql.getValue("SELECT COALESCE(MAX(id), 0) FROM entity_changes"), maxEntityChangeSyncIdAtLoad: sql.getValue("SELECT COALESCE(MAX(id), 0) FROM entity_changes WHERE isSynced = 1"), instanceName: config.General ? config.General.instanceName : null, From 6856a98d50272d9d6f606ff132aa4e46cdae01d2 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Mon, 26 Jan 2026 23:21:40 +0200 Subject: [PATCH 3/9] feat(desktop): integrate vibrancy --- apps/client/src/desktop.ts | 9 +++++--- .../src/stylesheets/theme-next/shell.css | 22 +++++++++++-------- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/apps/client/src/desktop.ts b/apps/client/src/desktop.ts index 69fff6e96b..3917dda84c 100644 --- a/apps/client/src/desktop.ts +++ b/apps/client/src/desktop.ts @@ -99,9 +99,8 @@ function initFullScreenDetection(currentWindow: Electron.BrowserWindow) { } function initTransparencyEffects(style: CSSStyleDeclaration, currentWindow: Electron.BrowserWindow) { + const material = style.getPropertyValue("--background-material"); if (window.glob.platform === "win32") { - const material = style.getPropertyValue("--background-material"); - // TriliumNextTODO: find a nicer way to make TypeScript happy – unfortunately TS did not like Array.includes here const bgMaterialOptions = ["auto", "none", "mica", "acrylic", "tabbed"] as const; const foundBgMaterialOption = bgMaterialOptions.find((bgMaterialOption) => material === bgMaterialOption); if (foundBgMaterialOption) { @@ -110,7 +109,11 @@ function initTransparencyEffects(style: CSSStyleDeclaration, currentWindow: Elec } if (window.glob.platform === "darwin") { - currentWindow.setVibrancy("under-window"); + const bgMaterialOptions = [ "popover", "tooltip", "titlebar", "selection", "menu", "sidebar", "header", "sheet", "window", "hud", "fullscreen-ui", "content", "under-window", "under-page" ] as const; + const foundBgMaterialOption = bgMaterialOptions.find((bgMaterialOption) => material === bgMaterialOption); + if (foundBgMaterialOption) { + currentWindow.setVibrancy(foundBgMaterialOption); + } } } diff --git a/apps/client/src/stylesheets/theme-next/shell.css b/apps/client/src/stylesheets/theme-next/shell.css index f81e8fcf72..483b117d52 100644 --- a/apps/client/src/stylesheets/theme-next/shell.css +++ b/apps/client/src/stylesheets/theme-next/shell.css @@ -46,7 +46,11 @@ body.background-effects.platform-win32 { --background-material: tabbed; } -body.background-effects.theme-supports-background-effects.platform-win32 { +body.background-effects.platform-darwin { + --background-material: under-window; +} + +body.background-effects.theme-supports-background-effects { --launcher-pane-horiz-border-color: var(--launcher-pane-horiz-border-color-bgfx); --launcher-pane-horiz-background-color: var(--launcher-pane-horiz-background-color-bgfx); --launcher-pane-vert-background-color: var(--launcher-pane-vert-background-color-bgfx); @@ -60,29 +64,29 @@ body.background-effects.platform-win32.layout-vertical { --background-material: mica; } -body.background-effects.theme-supports-background-effects.platform-win32.layout-vertical { +body.background-effects.theme-supports-background-effects.layout-vertical { --left-pane-background-color: var(--window-background-color-bgfx); --center-pane-background-color-bgfx: var(--center-pane-vert-layout-background-color-bgfx); --right-pane-background-color: var(--right-pane-background-color-bgfx); } -body.background-effects.theme-supports-background-effects.platform-win32.layout-horizontal { +body.background-effects.theme-supports-background-effects.layout-horizontal { --center-pane-background-color-bgfx: var(--center-pane-horiz-layout-background-color-bgfx); --gutter-color: var(--left-pane-background-color); } -body.background-effects.theme-supports-background-effects.platform-win32, -body.background-effects.theme-supports-background-effects.platform-win32 #root-widget { +body.background-effects.theme-supports-background-effects, +body.background-effects.theme-supports-background-effects #root-widget { background: var(--window-background-color-bgfx) !important; } -body.background-effects.theme-supports-background-effects.platform-win32.layout-horizontal #horizontal-main-container, -body.background-effects.theme-supports-background-effects.platform-win32.layout-vertical #vertical-main-container { +body.background-effects.theme-supports-background-effects.layout-horizontal #horizontal-main-container, +body.background-effects.theme-supports-background-effects.layout-vertical #vertical-main-container { background-color: var(--root-background); } /* Note split with background effects */ -body.background-effects.theme-supports-background-effects.platform-win32 #center-pane .note-split.bgfx { +body.background-effects.theme-supports-background-effects #center-pane .note-split.bgfx { --note-split-background-color: var(--center-pane-background-color-bgfx); } @@ -1054,7 +1058,7 @@ body.layout-horizontal .tab-row-widget-container { overflow: hidden; } -body.desktop:not(.background-effects.platform-win32) #root-widget.horizontal-layout { +body.desktop:not(.background-effects) #root-widget.horizontal-layout { background-color: var(--root-background) !important; } From 3c8a066f7605a4c2582a65f544b5bcdd3c7ed0b9 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Mon, 26 Jan 2026 23:28:29 +0200 Subject: [PATCH 4/9] feat(desktop): handle both vertical and horizontal layouts --- .../src/stylesheets/theme-next/shell.css | 25 +++++++++++++------ 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/apps/client/src/stylesheets/theme-next/shell.css b/apps/client/src/stylesheets/theme-next/shell.css index 483b117d52..1dd2432f72 100644 --- a/apps/client/src/stylesheets/theme-next/shell.css +++ b/apps/client/src/stylesheets/theme-next/shell.css @@ -40,14 +40,27 @@ body.mobile { /* #region Mica */ +/* Quirk: --background-material is read before "theme-supports-background-effects" class + * is applied. Apply the matterial even if the theme doesn't support it. */ body.background-effects.platform-win32 { - /* Quirk: --background-material is read before "theme-supports-background-effects" class - * is applied. Apply the matterial even if the theme doesn't support it. */ - --background-material: tabbed; + &.layout-vertical { + --background-material: mica; + } + + &.layout-horizontal { + --background-material: tabbed; + } } body.background-effects.platform-darwin { - --background-material: under-window; + /** Reference: https://developer.apple.com/documentation/appkit/nsvisualeffectview?preferredLanguage=objc **/ + &.layout-vertical { + --background-material: under-window; + } + + &.layout-horizontal { + --background-material: header; + } } body.background-effects.theme-supports-background-effects { @@ -60,10 +73,6 @@ body.background-effects.theme-supports-background-effects { --root-background: transparent; } -body.background-effects.platform-win32.layout-vertical { - --background-material: mica; -} - body.background-effects.theme-supports-background-effects.layout-vertical { --left-pane-background-color: var(--window-background-color-bgfx); --center-pane-background-color-bgfx: var(--center-pane-vert-layout-background-color-bgfx); From 51131433d3219794c7205d643dd16f06e133b902 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Tue, 27 Jan 2026 15:56:57 +0200 Subject: [PATCH 5/9] chore(client): address requested changes --- apps/client/src/desktop.ts | 2 +- apps/client/src/stylesheets/theme-next/shell.css | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/client/src/desktop.ts b/apps/client/src/desktop.ts index 3917dda84c..bba3b6b90b 100644 --- a/apps/client/src/desktop.ts +++ b/apps/client/src/desktop.ts @@ -99,7 +99,7 @@ function initFullScreenDetection(currentWindow: Electron.BrowserWindow) { } function initTransparencyEffects(style: CSSStyleDeclaration, currentWindow: Electron.BrowserWindow) { - const material = style.getPropertyValue("--background-material"); + const material = style.getPropertyValue("--background-material").trim(); if (window.glob.platform === "win32") { const bgMaterialOptions = ["auto", "none", "mica", "acrylic", "tabbed"] as const; const foundBgMaterialOption = bgMaterialOptions.find((bgMaterialOption) => material === bgMaterialOption); diff --git a/apps/client/src/stylesheets/theme-next/shell.css b/apps/client/src/stylesheets/theme-next/shell.css index 1dd2432f72..1b131a6a2b 100644 --- a/apps/client/src/stylesheets/theme-next/shell.css +++ b/apps/client/src/stylesheets/theme-next/shell.css @@ -41,7 +41,7 @@ body.mobile { /* #region Mica */ /* Quirk: --background-material is read before "theme-supports-background-effects" class - * is applied. Apply the matterial even if the theme doesn't support it. */ + * is applied. Apply the material even if the theme doesn't support it. */ body.background-effects.platform-win32 { &.layout-vertical { --background-material: mica; From a1cb3b8371ccd7e892cd6ad3b842cd1077a11afc Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Tue, 27 Jan 2026 16:42:52 +0200 Subject: [PATCH 6/9] style(desktop): change material for horizontal layout --- apps/client/src/stylesheets/theme-next/shell.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/client/src/stylesheets/theme-next/shell.css b/apps/client/src/stylesheets/theme-next/shell.css index 1b131a6a2b..7ff132e1af 100644 --- a/apps/client/src/stylesheets/theme-next/shell.css +++ b/apps/client/src/stylesheets/theme-next/shell.css @@ -41,7 +41,7 @@ body.mobile { /* #region Mica */ /* Quirk: --background-material is read before "theme-supports-background-effects" class - * is applied. Apply the material even if the theme doesn't support it. */ + * is applied. Apply the matterial even if the theme doesn't support it. */ body.background-effects.platform-win32 { &.layout-vertical { --background-material: mica; @@ -59,7 +59,7 @@ body.background-effects.platform-darwin { } &.layout-horizontal { - --background-material: header; + --background-material: hud; } } From ff46493775c309a717e3fd1599136b4d0d396321 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Tue, 27 Jan 2026 23:17:38 +0200 Subject: [PATCH 7/9] feat(options): add platform indicator --- apps/client/src/widgets/react/Icon.tsx | 2 +- .../type_widgets/options/appearance.tsx | 21 +++++++----- .../options/components/PlatformIndicator.css | 5 +++ .../options/components/PlatformIndicator.tsx | 34 +++++++++++++++++++ 4 files changed, 53 insertions(+), 9 deletions(-) create mode 100644 apps/client/src/widgets/type_widgets/options/components/PlatformIndicator.css create mode 100644 apps/client/src/widgets/type_widgets/options/components/PlatformIndicator.tsx diff --git a/apps/client/src/widgets/react/Icon.tsx b/apps/client/src/widgets/react/Icon.tsx index 8d12548334..4bae69c460 100644 --- a/apps/client/src/widgets/react/Icon.tsx +++ b/apps/client/src/widgets/react/Icon.tsx @@ -1,7 +1,7 @@ import clsx from "clsx"; import { HTMLAttributes } from "preact"; -interface IconProps extends Pick, "className" | "onClick"> { +interface IconProps extends Pick, "className" | "onClick" | "title"> { icon?: string; className?: string; } diff --git a/apps/client/src/widgets/type_widgets/options/appearance.tsx b/apps/client/src/widgets/type_widgets/options/appearance.tsx index fd8412a69a..3cff63ed66 100644 --- a/apps/client/src/widgets/type_widgets/options/appearance.tsx +++ b/apps/client/src/widgets/type_widgets/options/appearance.tsx @@ -18,6 +18,7 @@ import FormTextBox, { FormTextBoxWithUnit } from "../../react/FormTextBox"; import { useTriliumOption, useTriliumOptionBool } from "../../react/hooks"; import Icon from "../../react/Icon"; import OptionsSection from "./components/OptionsSection"; +import PlatformIndicator from "./components/PlatformIndicator"; import RadioWithIllustration from "./components/RadioWithIllustration"; import RelatedSettings from "./components/RelatedSettings"; @@ -174,13 +175,13 @@ function LayoutIllustration({ isNewLayout }: { isNewLayout?: boolean }) { ) : ( -
-
- - Title - +
+
+ + Title + +
-
)} {!isNewLayout &&
@@ -192,7 +193,7 @@ function LayoutIllustration({ isNewLayout }: { isNewLayout?: boolean }) {
-
+
} @@ -356,7 +357,11 @@ function ElectronIntegration() { + {t("electron_integration.background-effects")} + {" "} + + } currentValue={backgroundEffects} onChange={setBackgroundEffects} disabled={nativeTitleBarVisible} /> diff --git a/apps/client/src/widgets/type_widgets/options/components/PlatformIndicator.css b/apps/client/src/widgets/type_widgets/options/components/PlatformIndicator.css new file mode 100644 index 0000000000..e91e873559 --- /dev/null +++ b/apps/client/src/widgets/type_widgets/options/components/PlatformIndicator.css @@ -0,0 +1,5 @@ +.platform-indicator { + display: inline-flex; + gap: 0.25em; + color: var(--muted-text-color); +} diff --git a/apps/client/src/widgets/type_widgets/options/components/PlatformIndicator.tsx b/apps/client/src/widgets/type_widgets/options/components/PlatformIndicator.tsx new file mode 100644 index 0000000000..bb95e8d9ce --- /dev/null +++ b/apps/client/src/widgets/type_widgets/options/components/PlatformIndicator.tsx @@ -0,0 +1,34 @@ +import "./PlatformIndicator.css"; + +import { useRef } from "preact/hooks"; + +import { t } from "../../../../services/i18n"; +import { useStaticTooltip } from "../../../react/hooks"; +import Icon from "../../../react/Icon"; + +interface PlatformIndicatorProps { + windows?: boolean | "11"; + mac: boolean; +} + +export default function PlatformIndicator({ windows, mac }: PlatformIndicatorProps) { + const containerRef = useRef(null); + useStaticTooltip(containerRef, { + selector: "span", + animation: false, + title() { return this.title; }, + }); + + return ( +
+ {windows && } + {mac && } +
+ ); +} From 8fc889ae081668042339b183bf6be59125d07ba6 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Tue, 27 Jan 2026 23:22:31 +0200 Subject: [PATCH 8/9] chore(options): change description --- apps/client/src/translations/en/translation.json | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/apps/client/src/translations/en/translation.json b/apps/client/src/translations/en/translation.json index f112508c1e..5637ab8473 100644 --- a/apps/client/src/translations/en/translation.json +++ b/apps/client/src/translations/en/translation.json @@ -1958,8 +1958,8 @@ "desktop-application": "Desktop Application", "native-title-bar": "Native title bar", "native-title-bar-description": "For Windows and macOS, keeping the native title bar off makes the application look more compact. On Linux, keeping the native title bar on integrates better with the rest of the system.", - "background-effects": "Enable background effects (Windows 11 only)", - "background-effects-description": "The Mica effect adds a blurred, stylish background to app windows, creating depth and a modern look. \"Native title bar\" must be disabled.", + "background-effects": "Enable background effects", + "background-effects-description": "Adds a blurred, stylish background to app windows, creating depth and a modern look. \"Native title bar\" must be disabled.", "restart-app-button": "Restart the application to view the changes", "zoom-factor": "Zoom factor" }, @@ -2267,5 +2267,8 @@ "pages_other": "{{count}} pages", "pages_alt": "Page {{pageNumber}}", "pages_loading": "Loading..." + }, + "platform_indicator": { + "available_on": "Available on {{platform}}" } } From 5d5947f676d98333ab3e5db9f9fc6a6e3d8daac4 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Tue, 27 Jan 2026 23:31:05 +0200 Subject: [PATCH 9/9] feat(call_to_action): enable background effects CTA on macOS --- apps/client/src/translations/en/translation.json | 2 +- .../src/widgets/dialogs/call_to_action_definitions.ts | 10 +++------- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/apps/client/src/translations/en/translation.json b/apps/client/src/translations/en/translation.json index 5637ab8473..88ed7ac752 100644 --- a/apps/client/src/translations/en/translation.json +++ b/apps/client/src/translations/en/translation.json @@ -2152,7 +2152,7 @@ "next_theme_message": "You are currently using the legacy theme, would you like to try the new theme?", "next_theme_button": "Try the new theme", "background_effects_title": "Background effects are now stable", - "background_effects_message": "On Windows devices, background effects are now fully stable. The background effects adds a touch of color to the user interface by blurring the background behind it. This technique is also used in other applications such as Windows Explorer.", + "background_effects_message": "On Windows and macOS devices, background effects are now stable. The background effects adds a touch of color to the user interface by blurring the background behind it.", "background_effects_button": "Enable background effects", "new_layout_title": "New layout", "new_layout_message": "We’ve introduced a modernized layout for Trilium. The ribbon has been removed and seamlessly integrated into the main interface, with a new status bar and expandable sections (such as promoted attributes) taking over key functions.\n\nThe new layout is enabled by default, and can be temporarily disabled via Options → Appearance.", diff --git a/apps/client/src/widgets/dialogs/call_to_action_definitions.ts b/apps/client/src/widgets/dialogs/call_to_action_definitions.ts index d783b1dbba..afaecbdfa3 100644 --- a/apps/client/src/widgets/dialogs/call_to_action_definitions.ts +++ b/apps/client/src/widgets/dialogs/call_to_action_definitions.ts @@ -1,7 +1,7 @@ import appContext from "../../components/app_context"; import { t } from "../../services/i18n"; import options from "../../services/options"; -import utils from "../../services/utils"; +import utils, { isMac } from "../../services/utils"; /** * A "call-to-action" is an interactive message for the user, generally to present new features. @@ -41,10 +41,6 @@ export interface CallToAction { }[]; } -function isNextTheme() { - return [ "next", "next-light", "next-dark" ].includes(options.get("theme")); -} - const CALL_TO_ACTIONS: CallToAction[] = [ { id: "new_layout", @@ -63,7 +59,7 @@ const CALL_TO_ACTIONS: CallToAction[] = [ id: "background_effects", title: t("call_to_action.background_effects_title"), message: t("call_to_action.background_effects_message"), - enabled: () => false, + enabled: () => (isMac() && !options.is("backgroundEffects")), buttons: [ { text: t("call_to_action.background_effects_button"), @@ -78,7 +74,7 @@ const CALL_TO_ACTIONS: CallToAction[] = [ id: "next_theme", title: t("call_to_action.next_theme_title"), message: t("call_to_action.next_theme_message"), - enabled: () => !isNextTheme(), + enabled: () => ![ "next", "next-light", "next-dark" ].includes(options.get("theme")), buttons: [ { text: t("call_to_action.next_theme_button"),