From b735567504fa593662f70c440bde98a6141fb0b7 Mon Sep 17 00:00:00 2001 From: "mr. m" <91018726+mr-cheffy@users.noreply.github.com> Date: Tue, 24 Jun 2025 14:08:40 +0200 Subject: [PATCH] Gradient hue revamp (#9093) --- l10n | 2 +- src/browser/app/profile/features/theme.inc | 1 + src/browser/app/profile/macos.inc | 2 +- .../base/content/zen-assets.jar.inc.mn | 1 - .../content/zen-panels/gradient-generator.inc | 75 +- .../shared/preferences/zen-preferences.css | 31 - src/browser/themes/shared/zen-icons/icons.css | 40 +- .../themes/shared/zen-icons/jar.inc.mn | 51 +- .../themes/shared/zen-icons/lin/face-sun.svg | 1 + .../shared/zen-icons/lin/moon-stars.svg | 1 + .../themes/shared/zen-icons/lin/sparkles.svg | 1 + src/dom/base/Document-cpp.patch | 6 +- src/widget/cocoa/nsCocoaWindow-mm.patch | 13 + .../common/styles/zen-browser-container.css | 2 +- src/zen/common/styles/zen-browser-ui.css | 6 +- src/zen/common/styles/zen-popup.css | 2 +- src/zen/common/styles/zen-theme.css | 78 +- src/zen/images/gradient.png | Bin 68548 -> 0 bytes src/zen/mods/ZenMods.mjs | 6 +- src/zen/workspaces/ZenGradientGenerator.mjs | 704 ++++++++++++------ src/zen/workspaces/ZenWorkspaceIcons.mjs | 1 + src/zen/workspaces/ZenWorkspaces.mjs | 4 +- src/zen/workspaces/overflow-icons.inc.css | 2 + src/zen/workspaces/zen-gradient-generator.css | 209 +++--- 24 files changed, 799 insertions(+), 440 deletions(-) create mode 100644 src/browser/themes/shared/zen-icons/lin/face-sun.svg create mode 100644 src/browser/themes/shared/zen-icons/lin/moon-stars.svg create mode 100644 src/browser/themes/shared/zen-icons/lin/sparkles.svg create mode 100644 src/widget/cocoa/nsCocoaWindow-mm.patch delete mode 100644 src/zen/images/gradient.png diff --git a/l10n b/l10n index 706b33337..7435b28bd 160000 --- a/l10n +++ b/l10n @@ -1 +1 @@ -Subproject commit 706b33337345e4231e18313463259703b3fbc50d +Subproject commit 7435b28bdf962406f7e0ec54ed1774ede5b490a9 diff --git a/src/browser/app/profile/features/theme.inc b/src/browser/app/profile/features/theme.inc index b03c3c405..576c1bb1f 100644 --- a/src/browser/app/profile/features/theme.inc +++ b/src/browser/app/profile/features/theme.inc @@ -7,6 +7,7 @@ pref('zen.theme.content-element-separation', 8); // In pixels pref('zen.theme.gradient', true); pref('zen.theme.gradient.show-custom-colors', false); pref('zen.theme.essentials-favicon-bg', true); +pref('zen.theme.window.scheme', 'auto'); // auto, light, dark #ifdef XP_MACOSX pref('zen.theme.border-radius', 10); // In pixels diff --git a/src/browser/app/profile/macos.inc b/src/browser/app/profile/macos.inc index 67c540dc5..e237e401e 100644 --- a/src/browser/app/profile/macos.inc +++ b/src/browser/app/profile/macos.inc @@ -11,4 +11,4 @@ pref('widget.macos.sidebar-blend-mode.behind-window', true); // 5. toolTip // 6. headerView // 7. underlay -pref('zen.widget.macos.window-material', 3); +pref('zen.widget.macos.window-material', 1); diff --git a/src/browser/base/content/zen-assets.jar.inc.mn b/src/browser/base/content/zen-assets.jar.inc.mn index c0b5488de..7e0ef36d4 100644 --- a/src/browser/base/content/zen-assets.jar.inc.mn +++ b/src/browser/base/content/zen-assets.jar.inc.mn @@ -76,7 +76,6 @@ # Images - content/browser/zen-images/gradient.png (../../zen/images/gradient.png) content/browser/zen-images/brand-header.svg (../../zen/images/brand-header.svg) content/browser/zen-images/layouts/collapsed.png (../../zen/images/layouts/collapsed.png) content/browser/zen-images/layouts/multiple-toolbar.png (../../zen/images/layouts/multiple-toolbar.png) diff --git a/src/browser/base/content/zen-panels/gradient-generator.inc b/src/browser/base/content/zen-panels/gradient-generator.inc index e73cb20ad..0fd734c00 100644 --- a/src/browser/base/content/zen-panels/gradient-generator.inc +++ b/src/browser/base/content/zen-panels/gradient-generator.inc @@ -5,39 +5,66 @@ - - - - - - - - - - - - - - - - - + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + diff --git a/src/browser/themes/shared/preferences/zen-preferences.css b/src/browser/themes/shared/preferences/zen-preferences.css index fecc4fcef..5f350375c 100644 --- a/src/browser/themes/shared/preferences/zen-preferences.css +++ b/src/browser/themes/shared/preferences/zen-preferences.css @@ -249,37 +249,6 @@ groupbox h2 { } } -.zenLooksAndFeelColorOption { - width: 60px; - height: 60px; - border-radius: 50%; - background: var(--zen-primary-color); - position: relative; - overflow: hidden; -} - -.zenLooksAndFeelColorOption::before { - content: ''; - display: block; - width: 50%; - height: 50%; - bottom: 0; - left: 0; - position: absolute; - background: var(--zen-colors-secondary); -} - -.zenLooksAndFeelColorOption::after { - content: ''; - display: block; - width: 50%; - height: 50%; - bottom: 0; - right: 0; - position: absolute; - background: var(--zen-colors-tertiary); -} - /* Workspace */ #category-zen-tabs-management > .category-icon { diff --git a/src/browser/themes/shared/zen-icons/icons.css b/src/browser/themes/shared/zen-icons/icons.css index af7cd472b..b8df66f57 100644 --- a/src/browser/themes/shared/zen-icons/icons.css +++ b/src/browser/themes/shared/zen-icons/icons.css @@ -47,10 +47,6 @@ list-style-image: url('reload.svg') !important; } -#PanelUI-zen-gradient-generator-color-toggle-algo { - list-style-image: url('palette.svg'); -} - .tab-reset-button, #PanelUI-zen-gradient-generator-color-remove { list-style-image: url('unpin.svg') !important; @@ -101,7 +97,8 @@ list-style-image: url('chevron.svg') !important; } -#zen-rice-share-options .options-header { +#zen-rice-share-options .options-header, +#PanelUI-zen-gradient-generator-color-page-right { list-style-image: url('arrow-right.svg'); } @@ -400,7 +397,8 @@ list-style-image: url('expand-sidebar.svg') !important; } -.panel-header > .subviewbutton-back { +.panel-header > .subviewbutton-back, +#PanelUI-zen-gradient-generator-color-page-left { list-style-image: url('arrow-left.svg') !important; } @@ -768,3 +766,33 @@ background: transparent !important; } } + +#PanelUI-zen-gradient-generator-scheme-auto { + list-style-image: url('sparkles.svg'); +} + +@media -moz-pref('zen.theme.window.scheme', 'auto') { + #PanelUI-zen-gradient-generator-scheme-auto { + background: light-dark(rgba(0, 0, 0, 0.1), rgba(255, 255, 255, 0.1)); + } +} + +#PanelUI-zen-gradient-generator-scheme-dark { + list-style-image: url('moon-stars.svg'); +} + +@media -moz-pref('zen.theme.window.scheme', 'dark') { + #PanelUI-zen-gradient-generator-scheme-dark { + background: light-dark(rgba(0, 0, 0, 0.1), rgba(255, 255, 255, 0.1)); + } +} + +#PanelUI-zen-gradient-generator-scheme-light { + list-style-image: url('face-sun.svg'); +} + +@media -moz-pref('zen.theme.window.scheme', 'light') { + #PanelUI-zen-gradient-generator-scheme-light { + background: light-dark(rgba(0, 0, 0, 0.1), rgba(255, 255, 255, 0.1)); + } +} diff --git a/src/browser/themes/shared/zen-icons/jar.inc.mn b/src/browser/themes/shared/zen-icons/jar.inc.mn index 41218fa73..4986753b3 100644 --- a/src/browser/themes/shared/zen-icons/jar.inc.mn +++ b/src/browser/themes/shared/zen-icons/jar.inc.mn @@ -35,15 +35,16 @@ skin/classic/browser/zen-icons/edit-paste.svg (../shared/zen-icons/lin/edit-paste.svg) skin/classic/browser/zen-icons/edit-redo.svg (../shared/zen-icons/lin/edit-redo.svg) skin/classic/browser/zen-icons/edit-select-all.svg (../shared/zen-icons/lin/edit-select-all.svg) - skin/classic/browser/zen-icons/edit.svg (../shared/zen-icons/lin/edit.svg) skin/classic/browser/zen-icons/edit-theme.svg (../shared/zen-icons/lin/edit-theme.svg) skin/classic/browser/zen-icons/edit-undo.svg (../shared/zen-icons/lin/edit-undo.svg) + skin/classic/browser/zen-icons/edit.svg (../shared/zen-icons/lin/edit.svg) skin/classic/browser/zen-icons/essential-add.svg (../shared/zen-icons/lin/essential-add.svg) skin/classic/browser/zen-icons/essential-remove.svg (../shared/zen-icons/lin/essential-remove.svg) skin/classic/browser/zen-icons/expand-sidebar.svg (../shared/zen-icons/lin/expand-sidebar.svg) + skin/classic/browser/zen-icons/ext-link.svg (../shared/zen-icons/lin/ext-link.svg) skin/classic/browser/zen-icons/extension-blocked.svg (../shared/zen-icons/lin/extension-blocked.svg) skin/classic/browser/zen-icons/extension.svg (../shared/zen-icons/lin/extension.svg) - skin/classic/browser/zen-icons/ext-link.svg (../shared/zen-icons/lin/ext-link.svg) + skin/classic/browser/zen-icons/face-sun.svg (../shared/zen-icons/lin/face-sun.svg) skin/classic/browser/zen-icons/firefox.svg (../shared/zen-icons/lin/firefox.svg) skin/classic/browser/zen-icons/folder.svg (../shared/zen-icons/lin/folder.svg) skin/classic/browser/zen-icons/forget.svg (../shared/zen-icons/lin/forget.svg) @@ -80,6 +81,7 @@ skin/classic/browser/zen-icons/microphone-fill.svg (../shared/zen-icons/lin/microphone-fill.svg) skin/classic/browser/zen-icons/microphone.svg (../shared/zen-icons/lin/microphone.svg) skin/classic/browser/zen-icons/midi.svg (../shared/zen-icons/lin/midi.svg) + skin/classic/browser/zen-icons/moon-stars.svg (../shared/zen-icons/lin/moon-stars.svg) skin/classic/browser/zen-icons/move-tab.svg (../shared/zen-icons/lin/move-tab.svg) skin/classic/browser/zen-icons/new-tab-image.svg (../shared/zen-icons/lin/new-tab-image.svg) skin/classic/browser/zen-icons/open.svg (../shared/zen-icons/lin/open.svg) @@ -95,27 +97,28 @@ skin/classic/browser/zen-icons/pocket-outline.svg (../shared/zen-icons/lin/pocket-outline.svg) skin/classic/browser/zen-icons/popup.svg (../shared/zen-icons/lin/popup.svg) skin/classic/browser/zen-icons/print.svg (../shared/zen-icons/lin/print.svg) - skin/classic/browser/zen-icons/privateBrowsing.svg (../shared/zen-icons/lin/privateBrowsing.svg) skin/classic/browser/zen-icons/private-window.svg (../shared/zen-icons/lin/private-window.svg) + skin/classic/browser/zen-icons/privateBrowsing.svg (../shared/zen-icons/lin/privateBrowsing.svg) skin/classic/browser/zen-icons/reader-mode.svg (../shared/zen-icons/lin/reader-mode.svg) - skin/classic/browser/zen-icons/reload.svg (../shared/zen-icons/lin/reload.svg) skin/classic/browser/zen-icons/reload-to-stop.svg (../shared/zen-icons/lin/reload-to-stop.svg) + skin/classic/browser/zen-icons/reload.svg (../shared/zen-icons/lin/reload.svg) skin/classic/browser/zen-icons/report.svg (../shared/zen-icons/lin/report.svg) skin/classic/browser/zen-icons/save.svg (../shared/zen-icons/lin/save.svg) skin/classic/browser/zen-icons/screen-blocked.svg (../shared/zen-icons/lin/screen-blocked.svg) - skin/classic/browser/zen-icons/screenshot.svg (../shared/zen-icons/lin/screenshot.svg) skin/classic/browser/zen-icons/screen.svg (../shared/zen-icons/lin/screen.svg) + skin/classic/browser/zen-icons/screenshot.svg (../shared/zen-icons/lin/screenshot.svg) skin/classic/browser/zen-icons/search-glass.svg (../shared/zen-icons/lin/search-glass.svg) skin/classic/browser/zen-icons/search-page.svg (../shared/zen-icons/lin/search-page.svg) skin/classic/browser/zen-icons/security-broken.svg (../shared/zen-icons/lin/security-broken.svg) - skin/classic/browser/zen-icons/security.svg (../shared/zen-icons/lin/security.svg) skin/classic/browser/zen-icons/security-warning.svg (../shared/zen-icons/lin/security-warning.svg) + skin/classic/browser/zen-icons/security.svg (../shared/zen-icons/lin/security.svg) skin/classic/browser/zen-icons/send-to-device.svg (../shared/zen-icons/lin/send-to-device.svg) skin/classic/browser/zen-icons/settings.svg (../shared/zen-icons/lin/settings.svg) skin/classic/browser/zen-icons/share.svg (../shared/zen-icons/lin/share.svg) - skin/classic/browser/zen-icons/sidebars-right.svg (../shared/zen-icons/lin/sidebars-right.svg) skin/classic/browser/zen-icons/sidebar.svg (../shared/zen-icons/lin/sidebar.svg) + skin/classic/browser/zen-icons/sidebars-right.svg (../shared/zen-icons/lin/sidebars-right.svg) skin/classic/browser/zen-icons/source-code.svg (../shared/zen-icons/lin/source-code.svg) + skin/classic/browser/zen-icons/sparkles.svg (../shared/zen-icons/lin/sparkles.svg) skin/classic/browser/zen-icons/spell-check.svg (../shared/zen-icons/lin/spell-check.svg) skin/classic/browser/zen-icons/split.svg (../shared/zen-icons/lin/split.svg) skin/classic/browser/zen-icons/stop-to-reload.svg (../shared/zen-icons/lin/stop-to-reload.svg) @@ -174,15 +177,16 @@ skin/classic/browser/zen-icons/edit-paste.svg (../shared/zen-icons/lin/edit-paste.svg) skin/classic/browser/zen-icons/edit-redo.svg (../shared/zen-icons/lin/edit-redo.svg) skin/classic/browser/zen-icons/edit-select-all.svg (../shared/zen-icons/lin/edit-select-all.svg) - skin/classic/browser/zen-icons/edit.svg (../shared/zen-icons/lin/edit.svg) skin/classic/browser/zen-icons/edit-theme.svg (../shared/zen-icons/lin/edit-theme.svg) skin/classic/browser/zen-icons/edit-undo.svg (../shared/zen-icons/lin/edit-undo.svg) + skin/classic/browser/zen-icons/edit.svg (../shared/zen-icons/lin/edit.svg) skin/classic/browser/zen-icons/essential-add.svg (../shared/zen-icons/lin/essential-add.svg) skin/classic/browser/zen-icons/essential-remove.svg (../shared/zen-icons/lin/essential-remove.svg) skin/classic/browser/zen-icons/expand-sidebar.svg (../shared/zen-icons/lin/expand-sidebar.svg) + skin/classic/browser/zen-icons/ext-link.svg (../shared/zen-icons/lin/ext-link.svg) skin/classic/browser/zen-icons/extension-blocked.svg (../shared/zen-icons/lin/extension-blocked.svg) skin/classic/browser/zen-icons/extension.svg (../shared/zen-icons/lin/extension.svg) - skin/classic/browser/zen-icons/ext-link.svg (../shared/zen-icons/lin/ext-link.svg) + skin/classic/browser/zen-icons/face-sun.svg (../shared/zen-icons/lin/face-sun.svg) skin/classic/browser/zen-icons/firefox.svg (../shared/zen-icons/lin/firefox.svg) skin/classic/browser/zen-icons/folder.svg (../shared/zen-icons/lin/folder.svg) skin/classic/browser/zen-icons/forget.svg (../shared/zen-icons/lin/forget.svg) @@ -219,6 +223,7 @@ skin/classic/browser/zen-icons/microphone-fill.svg (../shared/zen-icons/lin/microphone-fill.svg) skin/classic/browser/zen-icons/microphone.svg (../shared/zen-icons/lin/microphone.svg) skin/classic/browser/zen-icons/midi.svg (../shared/zen-icons/lin/midi.svg) + skin/classic/browser/zen-icons/moon-stars.svg (../shared/zen-icons/lin/moon-stars.svg) skin/classic/browser/zen-icons/move-tab.svg (../shared/zen-icons/lin/move-tab.svg) skin/classic/browser/zen-icons/new-tab-image.svg (../shared/zen-icons/lin/new-tab-image.svg) skin/classic/browser/zen-icons/open.svg (../shared/zen-icons/lin/open.svg) @@ -234,27 +239,28 @@ skin/classic/browser/zen-icons/pocket-outline.svg (../shared/zen-icons/lin/pocket-outline.svg) skin/classic/browser/zen-icons/popup.svg (../shared/zen-icons/lin/popup.svg) skin/classic/browser/zen-icons/print.svg (../shared/zen-icons/lin/print.svg) - skin/classic/browser/zen-icons/privateBrowsing.svg (../shared/zen-icons/lin/privateBrowsing.svg) skin/classic/browser/zen-icons/private-window.svg (../shared/zen-icons/lin/private-window.svg) + skin/classic/browser/zen-icons/privateBrowsing.svg (../shared/zen-icons/lin/privateBrowsing.svg) skin/classic/browser/zen-icons/reader-mode.svg (../shared/zen-icons/lin/reader-mode.svg) - skin/classic/browser/zen-icons/reload.svg (../shared/zen-icons/lin/reload.svg) skin/classic/browser/zen-icons/reload-to-stop.svg (../shared/zen-icons/lin/reload-to-stop.svg) + skin/classic/browser/zen-icons/reload.svg (../shared/zen-icons/lin/reload.svg) skin/classic/browser/zen-icons/report.svg (../shared/zen-icons/lin/report.svg) skin/classic/browser/zen-icons/save.svg (../shared/zen-icons/lin/save.svg) skin/classic/browser/zen-icons/screen-blocked.svg (../shared/zen-icons/lin/screen-blocked.svg) - skin/classic/browser/zen-icons/screenshot.svg (../shared/zen-icons/lin/screenshot.svg) skin/classic/browser/zen-icons/screen.svg (../shared/zen-icons/lin/screen.svg) + skin/classic/browser/zen-icons/screenshot.svg (../shared/zen-icons/lin/screenshot.svg) skin/classic/browser/zen-icons/search-glass.svg (../shared/zen-icons/lin/search-glass.svg) skin/classic/browser/zen-icons/search-page.svg (../shared/zen-icons/lin/search-page.svg) skin/classic/browser/zen-icons/security-broken.svg (../shared/zen-icons/lin/security-broken.svg) - skin/classic/browser/zen-icons/security.svg (../shared/zen-icons/lin/security.svg) skin/classic/browser/zen-icons/security-warning.svg (../shared/zen-icons/lin/security-warning.svg) + skin/classic/browser/zen-icons/security.svg (../shared/zen-icons/lin/security.svg) skin/classic/browser/zen-icons/send-to-device.svg (../shared/zen-icons/lin/send-to-device.svg) skin/classic/browser/zen-icons/settings.svg (../shared/zen-icons/lin/settings.svg) skin/classic/browser/zen-icons/share.svg (../shared/zen-icons/lin/share.svg) - skin/classic/browser/zen-icons/sidebars-right.svg (../shared/zen-icons/lin/sidebars-right.svg) skin/classic/browser/zen-icons/sidebar.svg (../shared/zen-icons/lin/sidebar.svg) + skin/classic/browser/zen-icons/sidebars-right.svg (../shared/zen-icons/lin/sidebars-right.svg) skin/classic/browser/zen-icons/source-code.svg (../shared/zen-icons/lin/source-code.svg) + skin/classic/browser/zen-icons/sparkles.svg (../shared/zen-icons/lin/sparkles.svg) skin/classic/browser/zen-icons/spell-check.svg (../shared/zen-icons/lin/spell-check.svg) skin/classic/browser/zen-icons/split.svg (../shared/zen-icons/lin/split.svg) skin/classic/browser/zen-icons/stop-to-reload.svg (../shared/zen-icons/lin/stop-to-reload.svg) @@ -313,15 +319,16 @@ skin/classic/browser/zen-icons/edit-paste.svg (../shared/zen-icons/lin/edit-paste.svg) skin/classic/browser/zen-icons/edit-redo.svg (../shared/zen-icons/lin/edit-redo.svg) skin/classic/browser/zen-icons/edit-select-all.svg (../shared/zen-icons/lin/edit-select-all.svg) - skin/classic/browser/zen-icons/edit.svg (../shared/zen-icons/lin/edit.svg) skin/classic/browser/zen-icons/edit-theme.svg (../shared/zen-icons/lin/edit-theme.svg) skin/classic/browser/zen-icons/edit-undo.svg (../shared/zen-icons/lin/edit-undo.svg) + skin/classic/browser/zen-icons/edit.svg (../shared/zen-icons/lin/edit.svg) skin/classic/browser/zen-icons/essential-add.svg (../shared/zen-icons/lin/essential-add.svg) skin/classic/browser/zen-icons/essential-remove.svg (../shared/zen-icons/lin/essential-remove.svg) skin/classic/browser/zen-icons/expand-sidebar.svg (../shared/zen-icons/lin/expand-sidebar.svg) + skin/classic/browser/zen-icons/ext-link.svg (../shared/zen-icons/lin/ext-link.svg) skin/classic/browser/zen-icons/extension-blocked.svg (../shared/zen-icons/lin/extension-blocked.svg) skin/classic/browser/zen-icons/extension.svg (../shared/zen-icons/lin/extension.svg) - skin/classic/browser/zen-icons/ext-link.svg (../shared/zen-icons/lin/ext-link.svg) + skin/classic/browser/zen-icons/face-sun.svg (../shared/zen-icons/lin/face-sun.svg) skin/classic/browser/zen-icons/firefox.svg (../shared/zen-icons/lin/firefox.svg) skin/classic/browser/zen-icons/folder.svg (../shared/zen-icons/lin/folder.svg) skin/classic/browser/zen-icons/forget.svg (../shared/zen-icons/lin/forget.svg) @@ -358,6 +365,7 @@ skin/classic/browser/zen-icons/microphone-fill.svg (../shared/zen-icons/lin/microphone-fill.svg) skin/classic/browser/zen-icons/microphone.svg (../shared/zen-icons/lin/microphone.svg) skin/classic/browser/zen-icons/midi.svg (../shared/zen-icons/lin/midi.svg) + skin/classic/browser/zen-icons/moon-stars.svg (../shared/zen-icons/lin/moon-stars.svg) skin/classic/browser/zen-icons/move-tab.svg (../shared/zen-icons/lin/move-tab.svg) skin/classic/browser/zen-icons/new-tab-image.svg (../shared/zen-icons/lin/new-tab-image.svg) skin/classic/browser/zen-icons/open.svg (../shared/zen-icons/lin/open.svg) @@ -373,27 +381,28 @@ skin/classic/browser/zen-icons/pocket-outline.svg (../shared/zen-icons/lin/pocket-outline.svg) skin/classic/browser/zen-icons/popup.svg (../shared/zen-icons/lin/popup.svg) skin/classic/browser/zen-icons/print.svg (../shared/zen-icons/lin/print.svg) - skin/classic/browser/zen-icons/privateBrowsing.svg (../shared/zen-icons/lin/privateBrowsing.svg) skin/classic/browser/zen-icons/private-window.svg (../shared/zen-icons/lin/private-window.svg) + skin/classic/browser/zen-icons/privateBrowsing.svg (../shared/zen-icons/lin/privateBrowsing.svg) skin/classic/browser/zen-icons/reader-mode.svg (../shared/zen-icons/lin/reader-mode.svg) - skin/classic/browser/zen-icons/reload.svg (../shared/zen-icons/lin/reload.svg) skin/classic/browser/zen-icons/reload-to-stop.svg (../shared/zen-icons/lin/reload-to-stop.svg) + skin/classic/browser/zen-icons/reload.svg (../shared/zen-icons/lin/reload.svg) skin/classic/browser/zen-icons/report.svg (../shared/zen-icons/lin/report.svg) skin/classic/browser/zen-icons/save.svg (../shared/zen-icons/lin/save.svg) skin/classic/browser/zen-icons/screen-blocked.svg (../shared/zen-icons/lin/screen-blocked.svg) - skin/classic/browser/zen-icons/screenshot.svg (../shared/zen-icons/lin/screenshot.svg) skin/classic/browser/zen-icons/screen.svg (../shared/zen-icons/lin/screen.svg) + skin/classic/browser/zen-icons/screenshot.svg (../shared/zen-icons/lin/screenshot.svg) skin/classic/browser/zen-icons/search-glass.svg (../shared/zen-icons/lin/search-glass.svg) skin/classic/browser/zen-icons/search-page.svg (../shared/zen-icons/lin/search-page.svg) skin/classic/browser/zen-icons/security-broken.svg (../shared/zen-icons/lin/security-broken.svg) - skin/classic/browser/zen-icons/security.svg (../shared/zen-icons/lin/security.svg) skin/classic/browser/zen-icons/security-warning.svg (../shared/zen-icons/lin/security-warning.svg) + skin/classic/browser/zen-icons/security.svg (../shared/zen-icons/lin/security.svg) skin/classic/browser/zen-icons/send-to-device.svg (../shared/zen-icons/lin/send-to-device.svg) skin/classic/browser/zen-icons/settings.svg (../shared/zen-icons/lin/settings.svg) skin/classic/browser/zen-icons/share.svg (../shared/zen-icons/lin/share.svg) - skin/classic/browser/zen-icons/sidebars-right.svg (../shared/zen-icons/lin/sidebars-right.svg) skin/classic/browser/zen-icons/sidebar.svg (../shared/zen-icons/lin/sidebar.svg) + skin/classic/browser/zen-icons/sidebars-right.svg (../shared/zen-icons/lin/sidebars-right.svg) skin/classic/browser/zen-icons/source-code.svg (../shared/zen-icons/lin/source-code.svg) + skin/classic/browser/zen-icons/sparkles.svg (../shared/zen-icons/lin/sparkles.svg) skin/classic/browser/zen-icons/spell-check.svg (../shared/zen-icons/lin/spell-check.svg) skin/classic/browser/zen-icons/split.svg (../shared/zen-icons/lin/split.svg) skin/classic/browser/zen-icons/stop-to-reload.svg (../shared/zen-icons/lin/stop-to-reload.svg) diff --git a/src/browser/themes/shared/zen-icons/lin/face-sun.svg b/src/browser/themes/shared/zen-icons/lin/face-sun.svg new file mode 100644 index 000000000..20461bcf1 --- /dev/null +++ b/src/browser/themes/shared/zen-icons/lin/face-sun.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/browser/themes/shared/zen-icons/lin/moon-stars.svg b/src/browser/themes/shared/zen-icons/lin/moon-stars.svg new file mode 100644 index 000000000..7e3698dcc --- /dev/null +++ b/src/browser/themes/shared/zen-icons/lin/moon-stars.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/browser/themes/shared/zen-icons/lin/sparkles.svg b/src/browser/themes/shared/zen-icons/lin/sparkles.svg new file mode 100644 index 000000000..9c0828bd6 --- /dev/null +++ b/src/browser/themes/shared/zen-icons/lin/sparkles.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/dom/base/Document-cpp.patch b/src/dom/base/Document-cpp.patch index 04aa8afd8..c324fda33 100644 --- a/src/dom/base/Document-cpp.patch +++ b/src/dom/base/Document-cpp.patch @@ -1,13 +1,13 @@ diff --git a/dom/base/Document.cpp b/dom/base/Document.cpp -index a16bef739fcde0f14ba7e53e0acfa3aa2ee1dd3a..78b9d112a56b3d909e31eb4351ee9f3b06c4ef92 100644 +index a16bef739fcde0f14ba7e53e0acfa3aa2ee1dd3a..f928c0f1df4e86bd344ab7e57dab112234fb92e8 100644 --- a/dom/base/Document.cpp +++ b/dom/base/Document.cpp @@ -3332,6 +3332,15 @@ void Document::FillStyleSetUserAndUASheets() { ServoStyleSet& styleSet = EnsureStyleSet(); for (StyleSheet* sheet : *sheetService->UserStyleSheets()) { -+ // If the url starts with "chrome://" and ends with 'zen-themes.css', then -+ // skip it if the document is in a chrome docshell. ++ // If the url starts with "file://" and ends with 'zen-themes.css', then ++ // skip it if the document is not in a chrome docshell. + // This is to avoid loading the user chrome stylesheet in the content + // process, which is not allowed. + auto spec = sheet->GetSheetURI()->GetSpecOrDefault(); diff --git a/src/widget/cocoa/nsCocoaWindow-mm.patch b/src/widget/cocoa/nsCocoaWindow-mm.patch new file mode 100644 index 000000000..ce10d5cd6 --- /dev/null +++ b/src/widget/cocoa/nsCocoaWindow-mm.patch @@ -0,0 +1,13 @@ +diff --git a/widget/cocoa/nsCocoaWindow.mm b/widget/cocoa/nsCocoaWindow.mm +index c4627621344d35081f11a7b0e03d02eca2097609..d2e5fe429aaac8b701a03380a67f4ea978d566b3 100644 +--- a/widget/cocoa/nsCocoaWindow.mm ++++ b/widget/cocoa/nsCocoaWindow.mm +@@ -7376,7 +7376,7 @@ - (id)initWithContentRect:(NSRect)aContentRect + + // Returns an autoreleased NSImage. + static NSImage* GetMenuMaskImage() { +- const CGFloat radius = 6.0f; ++ const CGFloat radius = 14.0f; + const NSSize maskSize = {radius * 3.0f, radius * 3.0f}; + NSImage* maskImage = [NSImage imageWithSize:maskSize + flipped:FALSE diff --git a/src/zen/common/styles/zen-browser-container.css b/src/zen/common/styles/zen-browser-container.css index 933bc985e..abf632bd0 100644 --- a/src/zen/common/styles/zen-browser-container.css +++ b/src/zen/common/styles/zen-browser-container.css @@ -17,7 +17,7 @@ } & browser[transparent='true'] { - background: rgba(255, 255, 255, 0.1); + background: light-dark(rgba(255, 255, 255, 0.3), rgba(255, 255, 255, 0.1)); } } } diff --git a/src/zen/common/styles/zen-browser-ui.css b/src/zen/common/styles/zen-browser-ui.css index a8bdeda18..30fdd4b0c 100644 --- a/src/zen/common/styles/zen-browser-ui.css +++ b/src/zen/common/styles/zen-browser-ui.css @@ -46,6 +46,8 @@ pointer-events: none; isolation: isolate; + background: var(--zen-themed-toolbar-bg-transparent); + transition: background-color var(--inactive-window-transition); &::after, &::before { @@ -100,7 +102,7 @@ border: none; } -@supports (-moz-osx-font-smoothing: auto) { +@media (-moz-platform: macos) { #zen-main-app-wrapper, #zen-appcontent-wrapper, #zen-sidebar-splitter { @@ -118,7 +120,7 @@ } #zen-main-app-wrapper { - background: var(--zen-themed-toolbar-bg-transparent); + background: transparent; /* See bug #8814, don't an overflow here as it causes issues * with firefox's rendering of the tab bar */ diff --git a/src/zen/common/styles/zen-popup.css b/src/zen/common/styles/zen-popup.css index 774f5e4c0..35b51684e 100644 --- a/src/zen/common/styles/zen-popup.css +++ b/src/zen/common/styles/zen-popup.css @@ -394,7 +394,6 @@ menuseparator { } & button { - color-scheme: dark; width: min-content; padding: 0 10px !important; min-width: unset !important; @@ -402,6 +401,7 @@ menuseparator { border-radius: calc(var(--zen-native-inner-radius) + 2px) !important; background: light-dark(rgba(255, 255, 255, 0.1), rgba(0, 0, 0, 0.1)) !important; border: 1px solid light-dark(rgba(255, 255, 255, 0.15), rgba(0, 0, 0, 0.15)) !important; + color: var(--toolbar-color); :root[zen-right-side='true'] & { order: -1; diff --git a/src/zen/common/styles/zen-theme.css b/src/zen/common/styles/zen-theme.css index e3a226fcb..bc2970f0a 100644 --- a/src/zen/common/styles/zen-theme.css +++ b/src/zen/common/styles/zen-theme.css @@ -9,12 +9,7 @@ */ :host(:is(.anonymous-content-host, notification-message)), -:root, -.zenLooksAndFeelColorOption { - /** We also add `.zenLooksAndFeelColorOption` so that it recalculates the colors when the theme changes - * in the preferences page. - */ - +:root { /* Default values */ --zen-border-radius: 7px; --zen-primary-color: #ffb787; @@ -92,7 +87,7 @@ --focus-outline-color: var(--button-bgcolor) !important; --toolbarbutton-icon-fill-attention: var(--zen-primary-color) !important; - --toolbarbutton-icon-fill: light-dark(rgba(57, 57, 58, 0.6), rgba(251, 251, 254, 0.6)) !important; + --toolbarbutton-icon-fill: currentColor !important; --button-primary-bgcolor: var(--in-content-primary-button-background) !important; --button-primary-hover-bgcolor: var(--in-content-primary-button-background-hover) !important; @@ -121,7 +116,10 @@ --zen-button-border-radius: 5px; --zen-button-padding: 0.6rem 1.2rem; - --zen-toolbar-element-bg: light-dark(rgba(89, 89, 89, 0.1), rgba(255, 255, 255, 0.1)); + --zen-toolbar-element-bg: light-dark( + color-mix(in srgb, currentColor 5%, transparent 5%), + color-mix(in srgb, currentColor 10%, transparent 90%) + ) !important; /* Toolbar */ --zen-toolbar-height: 38px; @@ -162,27 +160,11 @@ --input-bgcolor: var(--zen-colors-tertiary) !important; --input-border-color: var(--zen-input-border-color) !important; - --zen-themed-toolbar-bg: light-dark(rgb(240, 240, 244), #171717); --zen-themed-toolbar-bg-transparent: light-dark(var(--zen-branding-bg), #171717); --zen-workspace-indicator-height: 48px; - @media (-moz-windows-mica) or (-moz-platform: macos) { - background: transparent; - --zen-themed-toolbar-bg-transparent: transparent; - @media -moz-pref('widget.windows.mica.toplevel-backdrop', 2) { - --zen-themed-toolbar-bg-transparent: color-mix( - in srgb, - var(--zen-themed-toolbar-bg) 35%, - transparent 65% - ); - } - } - - @media (-moz-platform: linux) and -moz-pref('zen.widget.linux.transparency') { - background: transparent; - --zen-themed-toolbar-bg-transparent: transparent; - } + --toolbar-field-color: var(--toolbox-textcolor) !important; &[zen-private-window='true'] { --zen-main-browser-background: linear-gradient( @@ -239,6 +221,52 @@ #main-window:not([chromehidden~='toolbar']) { min-height: 495px !important; + + @media (-moz-windows-mica) or (-moz-platform: macos) { + background: transparent; + --zen-themed-toolbar-bg-transparent: transparent; + &[zen-should-be-dark-mode] { + --zen-themed-toolbar-bg-transparent: var(--zen-themed-browser-overlay-bg); + } + } + + @media (-moz-platform: linux) and -moz-pref('zen.widget.linux.transparency') { + background: transparent; + --zen-themed-toolbar-bg-transparent: transparent; + &[zen-should-be-dark-mode] { + --zen-themed-toolbar-bg-transparent: var(--zen-themed-browser-overlay-bg); + } + } + + &[zen-should-be-dark-mode='true'] #browser { + color-scheme: dark; + --tab-selected-color-scheme: dark; + } + + &[zen-should-be-dark-mode='false'] #browser { + color-scheme: light; + --tab-selected-color-scheme: light; + } + + &, + & #tabbrowser-tabpanels, + & panel, + & menupopup { + @media -moz-pref('zen.theme.window.scheme', 'dark') { + color-scheme: dark; + } + + @media -moz-pref('zen.theme.window.scheme', 'light') { + color-scheme: light; + } + + @media -moz-pref('zen.theme.window.scheme', 'auto') { + color-scheme: light; + @media (-moz-system-dark-theme) { + color-scheme: dark; + } + } + } } @media (prefers-color-scheme: dark) { diff --git a/src/zen/images/gradient.png b/src/zen/images/gradient.png deleted file mode 100644 index b65f34ae5362304b5cd90e124df9f0192c077458..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 68548 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 { + const type = command.charAt(0); + const coordsStr = command.slice(1).trim(); + const coords = coordsStr.split(/[\s,]+/).map(Number); + + switch (type) { + case 'M': + points.push({ x: coords[0], y: coords[1], type: 'M' }); + break; + case 'C': + if (coords.length >= 6 && coords.length % 6 === 0) { + for (let i = 0; i < coords.length; i += 6) { + points.push({ + x1: coords[i], + y1: coords[i + 1], + x2: coords[i + 2], + y2: coords[i + 3], + x: coords[i + 4], + y: coords[i + 5], + type: 'C', + }); + } + } + break; + case 'L': + points.push({ x: coords[0], y: coords[1], type: 'L' }); + break; + } + }); + return points; + } + + class nsZenThemePicker extends ZenMultiWindowFeature { static MAX_DOTS = 3; currentOpacity = 0.5; - currentRotation = -45; dots = []; useAlgo = ''; + #currentLightness = 50; #allowTransparencyOnSidebar = Services.prefs.getBoolPref('zen.theme.acrylic-elements', false); + #linePath = `M 51.373 27.395 L 367.037 27.395`; + #sinePath = `M 51.373 27.395 C 60.14 -8.503 68.906 -8.503 77.671 27.395 C 86.438 63.293 95.205 63.293 103.971 27.395 C 112.738 -8.503 121.504 -8.503 130.271 27.395 C 139.037 63.293 147.803 63.293 156.57 27.395 C 165.335 -8.503 174.101 -8.503 182.868 27.395 C 191.634 63.293 200.4 63.293 209.167 27.395 C 217.933 -8.503 226.7 -8.503 235.467 27.395 C 244.233 63.293 252.999 63.293 261.765 27.395 C 270.531 -8.503 279.297 -8.503 288.064 27.395 C 296.83 63.293 305.596 63.293 314.363 27.395 C 323.13 -8.503 331.896 -8.503 340.662 27.395 M 314.438 27.395 C 323.204 -8.503 331.97 -8.503 340.737 27.395 C 349.503 63.293 358.27 63.293 367.037 27.395`; + + #sinePoints = parseSinePath(this.#sinePath); + + #colorPage = 0; + constructor() { super(); if ( @@ -39,6 +82,10 @@ document.getElementById('PanelUI-zen-gradient-generator-custom-list') ); + ChromeUtils.defineLazyGetter(this, 'sliderWavePath', () => + document.getElementById('PanelUI-zen-gradient-slider-wave').querySelector('path') + ); + this.panel.addEventListener('popupshowing', this.handlePanelOpen.bind(this)); this.panel.addEventListener('popuphidden', this.handlePanelClose.bind(this)); this.panel.addEventListener('command', this.handlePanelCommand.bind(this)); @@ -47,23 +94,53 @@ .getElementById('PanelUI-zen-gradient-generator-opacity') .addEventListener('input', this.onOpacityChange.bind(this)); - this.initCanvas(); + // Call the rest of the initialization + this.initContextMenu(); + this.initPredefinedColors(); + + this._resolveInitialized(); + delete this._resolveInitialized; + this.initCustomColorInput(); this.initTextureInput(); - this.initRotationInput(); + this.initSchemeButtons(); + this.initColorPages(); - window - .matchMedia('(prefers-color-scheme: dark)') - .addListener(this.onDarkModeChange.bind(this)); + const darkModeChange = this.handleDarkModeChange.bind(this); + window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', darkModeChange); + + XPCOMUtils.defineLazyPreferenceGetter( + this, + 'windowSchemeType', + 'zen.theme.window.scheme', + true, + darkModeChange + ); + } + + handleDarkModeChange(event) { + this.updateCurrentWorkspace(); } get isDarkMode() { + switch (this.windowSchemeType) { + case 'dark': + return true; + case 'light': + return false; + default: + } return window.matchMedia('(prefers-color-scheme: dark)').matches; } - async onDarkModeChange(event, skipUpdate = false) { - const currentWorkspace = await gZenWorkspaces.getActiveWorkspace(); - this.onWorkspaceChange(currentWorkspace, skipUpdate); + get colorHarmonies() { + return [ + { type: 'complementary', angles: [180] }, + { type: 'splitComplementary', angles: [150, 210] }, + { type: 'analogous', angles: [50, 310] }, + { type: 'triadic', angles: [120, 240] }, + { type: 'floating', angles: [] }, + ]; } initContextMenu() { @@ -86,43 +163,9 @@ }); } - initCanvas() { - this.image = new Image(); - this.image.src = ZenThemePicker.GRADIENT_IMAGE_URL; - - this.canvas = document.createElement('canvas'); - this.panel.appendChild(this.canvas); - this.canvasCtx = this.canvas.getContext('2d'); - - // wait for the image to load - this.image.onload = this.onImageLoad.bind(this); - } - - onImageLoad() { - // resize the image to fit the panel - const imageSize = 350 - 20; // 20 is the padding (10px) - const scale = imageSize / Math.max(this.image.width, this.image.height); - this.image.width *= scale; - this.image.height *= scale; - - this.canvas.width = this.image.width; - this.canvas.height = this.image.height; - this.canvasCtx.drawImage(this.image, 0, 0); - - this.canvas.setAttribute('hidden', 'true'); - - // Call the rest of the initialization - this.initContextMenu(); - this.initPredefinedColors(); - - this._resolveInitialized(); - delete this._resolveInitialized; - this.onDarkModeChange(null); - } - initPredefinedColors() { document - .getElementById('PanelUI-zen-gradient-generator-predefined') + .getElementById('PanelUI-zen-gradient-generator-color-pages') .addEventListener('click', async (event) => { const target = event.target; const rawPosition = target.getAttribute('data-position'); @@ -130,6 +173,7 @@ return; } const algo = target.getAttribute('data-algo'); + const lightness = target.getAttribute('data-lightness'); const numDots = parseInt(target.getAttribute('data-num-dots')); if (algo == 'float') { for (const dot of this.dots) { @@ -157,6 +201,7 @@ }); } this.useAlgo = algo; + this.#currentLightness = lightness; dots = this.calculateCompliments(dots, 'update', this.useAlgo); if (algo == 'float') { for (const dot of dots) { @@ -173,49 +218,52 @@ this.customColorInput.addEventListener('keydown', this.onCustomColorKeydown.bind(this)); } - initRotationInput() { - const rotationInput = document.getElementById('PanelUI-zen-gradient-generator-rotation-dot'); - this._onRotationMouseDown = this.onRotationMouseDown.bind(this); - this._onRotationMouseMove = this.onRotationMouseMove.bind(this); - this._onRotationMouseUp = this.onRotationMouseUp.bind(this); - rotationInput.addEventListener('mousedown', this._onRotationMouseDown); - } - - onRotationMouseDown(event) { - event.preventDefault(); - event.stopPropagation(); - this._rotating = true; - document.addEventListener('mousemove', this._onRotationMouseMove); - document.addEventListener('mouseup', this._onRotationMouseUp); - } - - onRotationMouseMove(event) { - event.preventDefault(); - event.stopPropagation(); - const rotationInput = document.getElementById('PanelUI-zen-gradient-generator-rotation-dot'); - const containerRect = rotationInput.parentElement.getBoundingClientRect(); - // We calculate the angle based on the mouse position and the center of the container - const rotation = Math.atan2( - event.clientY - containerRect.top - containerRect.height / 2, - event.clientX - containerRect.left - containerRect.width / 2 + initColorPages() { + const leftButton = document.getElementById('PanelUI-zen-gradient-generator-color-page-left'); + const rightButton = document.getElementById( + 'PanelUI-zen-gradient-generator-color-page-right' ); - const endRotation = (rotation * 180) / Math.PI; - // Between 150 and 50, we don't update the rotation - if (!(endRotation < 45 || endRotation > 130)) { - return; - } - this.currentRotation = endRotation; - this.updateCurrentWorkspace(); + const pagesWrapper = document.getElementById('PanelUI-zen-gradient-generator-color-pages'); + const pages = pagesWrapper.children; + pagesWrapper.addEventListener('wheel', (event) => { + event.preventDefault(); + event.stopPropagation(); + }); + leftButton.addEventListener('command', () => { + this.#colorPage = (this.#colorPage - 1 + pages.length) % pages.length; + // Scroll to the next page, by using scrollLeft + pagesWrapper.scrollLeft = (this.#colorPage * pagesWrapper.scrollWidth) / pages.length; + rightButton.disabled = false; + leftButton.disabled = this.#colorPage === 0; + }); + rightButton.addEventListener('command', () => { + this.#colorPage = (this.#colorPage + 1) % pages.length; + // Scroll to the next page, by using scrollLeft + pagesWrapper.scrollLeft = (this.#colorPage * pagesWrapper.scrollWidth) / pages.length; + leftButton.disabled = false; + rightButton.disabled = this.#colorPage === pages.length - 1; + }); } - onRotationMouseUp(event) { - event.preventDefault(); - event.stopPropagation(); - document.removeEventListener('mousemove', this._onRotationMouseMove); - document.removeEventListener('mouseup', this._onRotationMouseUp); - setTimeout(() => { - this._rotating = false; - }, 100); + initSchemeButtons() { + const buttons = document.getElementById('PanelUI-zen-gradient-generator-scheme'); + buttons.addEventListener('click', (event) => { + const target = event.target.closest('.subviewbutton'); + if (!target) { + return; + } + event.preventDefault(); + event.stopPropagation(); + const scheme = target.id.replace('PanelUI-zen-gradient-generator-scheme-', ''); + if (!scheme) { + return; + } + if (this.currentScheme === scheme) { + return; + } + this.currentScheme = scheme; + Services.prefs.setStringPref('zen.theme.window.scheme', scheme); + }); } initTextureInput() { @@ -312,39 +360,110 @@ this._onThemePickerClick = null; } - calculateInitialPosition(color) { - const [r, g, b] = color.c; - const imageData = this.canvasCtx.getImageData(0, 0, this.canvas.width, this.canvas.height); - // Find all pixels that are at least 90% similar to the color - const similarPixels = []; - for (let i = 0; i < imageData.data.length; i += 4) { - const pixelR = imageData.data[i]; - const pixelG = imageData.data[i + 1]; - const pixelB = imageData.data[i + 2]; - if (Math.abs(r - pixelR) < 25 && Math.abs(g - pixelG) < 25 && Math.abs(b - pixelB) < 25) { - similarPixels.push(i); - } + /** + * Converts an HSL color value to RGB. Conversion formula + * adapted from https://en.wikipedia.org/wiki/HSL_color_space. + * Assumes h, s, and l are contained in the set [0, 1] and + * returns r, g, and b in the set [0, 255]. + * + * @param {number} h The hue + * @param {number} s The saturation + * @param {number} l The lightness + * @return {Array} The RGB representation + */ + hslToRgb(h, s, l) { + const { abs, min, max, round } = Math; + let r, g, b; + + if (s === 0) { + r = g = b = l; // achromatic + } else { + const q = l < 0.5 ? l * (1 + s) : l + s - l * s; + const p = 2 * l - q; + r = this.hueToRgb(p, q, h + 1 / 3); + g = this.hueToRgb(p, q, h); + b = this.hueToRgb(p, q, h - 1 / 3); } - // Check if there's an exact match - for (const pixel of similarPixels) { - const x = (pixel / 4) % this.canvas.width; - const y = Math.floor(pixel / 4 / this.canvas.width); - const pixelColor = this.getColorFromPosition(x, y); - if (pixelColor[0] === r && pixelColor[1] === g && pixelColor[2] === b) { - return { x: x / this.canvas.width, y: y / this.canvas.height }; - } - } - // If there's no exact match, return the first similar pixel - const pixel = similarPixels[0]; - const x = (pixel / 4) % this.canvas.width; - const y = Math.floor(pixel / 4 / this.canvas.width); - return { x: x / this.canvas.width, y: y / this.canvas.height }; + + return [round(r * 255), round(g * 255), round(b * 255)]; + } + + rgbToHsl(r, g, b) { + r /= 255; + g /= 255; + b /= 255; + let max = Math.max(r, g, b); + let min = Math.min(r, g, b); + let d = max - min; + let h; + if (d === 0) h = 0; + else if (max === r) h = ((g - b) / d) % 6; + else if (max === g) h = (b - r) / d + 2; + else if (max === b) h = (r - g) / d + 4; + let l = (min + max) / 2; + let s = d === 0 ? 0 : d / (1 - Math.abs(2 * l - 1)); + return [h * 60, s, l]; + } + + hueToRgb(p, q, t) { + if (t < 0) t += 1; + if (t > 1) t -= 1; + if (t < 1 / 6) return p + (q - p) * 6 * t; + if (t < 1 / 2) return q; + if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6; + return p; + } + + calculateInitialPosition([r, g, b]) { + // This function is called before the picker is even rendered, so we hard code the dimensions + // important: If any sort of sizing is changed, make sure changes are reflected here + const padding = 20; + const rect = { + width: 318, + height: 318, + }; + const centerX = rect.width / 2; + const centerY = rect.height / 2; + const radius = (rect.width - padding) / 2; + const [hue, saturation] = this.rgbToHsl(r, g, b); + const angle = (hue / 360) * 2 * Math.PI; // Convert to radians + const normalizedSaturation = saturation / 100; // Convert to [0, 1] + const x = centerX + radius * normalizedSaturation * Math.cos(angle) - padding; + const y = centerY + radius * normalizedSaturation * Math.sin(angle) - padding; + return { x, y }; } getColorFromPosition(x, y) { - // get the color from the x and y from the image - const imageData = this.canvasCtx.getImageData(x, y, 1, 1); - return imageData.data; + // Return a color as hsl based on the position in the gradient + const gradient = this.panel.querySelector('.zen-theme-picker-gradient'); + const rect = gradient.getBoundingClientRect(); + const padding = 20; // each side + rect.width += padding * 2; + rect.height += padding * 2; + const centerX = rect.width / 2; + const centerY = rect.height / 2; + const radius = (rect.width - padding) / 2; + const distance = Math.sqrt((x - centerX) ** 2 + (y - centerY) ** 2); + let angle = Math.atan2(y - centerY, x - centerX); + angle = (angle * 180) / Math.PI; // Convert to degrees + if (angle < 0) { + angle += 360; // Normalize to [0, 360) + } + const normalizedDistance = 1 - Math.min(distance / radius, 1); // Normalize distance to [0, 1] + const hue = (angle / 360) * 360; // Normalize angle to [0, 360) + const saturation = normalizedDistance * 100; // Scale distance to [0, 100] + const lightness = this.#currentLightness; // Fixed lightness for simplicity + const [r, g, b] = this.hslToRgb(hue / 360, saturation / 100, lightness / 100); + return [ + Math.min(255, Math.max(0, r)), + Math.min(255, Math.max(0, g)), + Math.min(255, Math.max(0, b)), + ]; + } + + getJSONPos(x, y) { + // Return a JSON string with the position + return JSON.stringify({ x: Math.round(x), y: Math.round(y) }); } createDot(color, fromWorkspace = false) { @@ -361,13 +480,13 @@ dot.style.opacity = 0; dot.style.setProperty('--zen-theme-picker-dot-color', color.c); } else { - const { x, y } = this.calculateInitialPosition(color); + const { x, y } = color.position || this.calculateInitialPosition([r, g, b]); const dotPad = this.panel.querySelector('.zen-theme-picker-gradient'); dot.classList.add('zen-theme-picker-dot'); - dot.style.left = `${x * 100}%`; - dot.style.top = `${y * 100}%`; + dot.style.left = `${x}px`; + dot.style.top = `${y}px`; if (this.dots.length < 1) { dot.classList.add('primary'); @@ -377,6 +496,7 @@ let id = this.dots.length; dot.style.setProperty('--zen-theme-picker-dot-color', `rgb(${r}, ${g}, ${b})`); + dot.setAttribute('data-position', this.getJSONPos(x, y)); this.dots.push({ ID: id, @@ -474,6 +594,7 @@ '--zen-theme-picker-dot-color', `rgb(${colorFromPos[0]}, ${colorFromPos[1]}, ${colorFromPos[2]})` ); + dot.setAttribute('data-position', this.getJSONPos(relativePosition.x, relativePosition.y)); this.dots.push({ ID: id, @@ -483,13 +604,7 @@ } calculateCompliments(dots, action = 'update', useHarmony = '') { - const colorHarmonies = [ - { type: 'complementary', angles: [180] }, - { type: 'splitComplementary', angles: [150, 210] }, - { type: 'analogous', angles: [30, 330] }, - { type: 'triadic', angles: [120, 240] }, - { type: 'floating', angles: [] }, - ]; + const colorHarmonies = this.colorHarmonies; if (dots.length === 0) { return []; @@ -614,6 +729,8 @@ '--zen-theme-picker-dot-color', `rgb(${colorFromPos[0]}, ${colorFromPos[1]}, ${colorFromPos[2]})` ); + + dot.element.setAttribute('data-position', this.getJSONPos(pixelX, pixelY)); }); return; @@ -630,6 +747,10 @@ '--zen-theme-picker-dot-color', `rgb(${colorFromPos[0]}, ${colorFromPos[1]}, ${colorFromPos[2]})` ); + existingPrimaryDot.element.setAttribute( + 'data-position', + this.getJSONPos(existingPrimaryDot.position.x, existingPrimaryDot.position.y) + ); } colorPositions.forEach((dotPosition) => { @@ -645,6 +766,10 @@ '--zen-theme-picker-dot-color', `rgb(${colorFromPos[0]}, ${colorFromPos[1]}, ${colorFromPos[2]})` ); + existingDot.element.setAttribute( + 'data-position', + this.getJSONPos(dotPosition.position.x, dotPosition.position.y) + ); if (!this.dragging) { gZenUIManager.motion.animate( @@ -673,10 +798,13 @@ if (this._rotating) { return; } + if (event.target.closest('#PanelUI-zen-gradient-generator-scheme')) { + return; + } event.preventDefault(); const target = event.target; if (target.id === 'PanelUI-zen-gradient-generator-color-add') { - if (this.dots.length >= ZenThemePicker.MAX_DOTS) return; + if (this.dots.length >= nsZenThemePicker.MAX_DOTS) return; let colorPositions = this.calculateCompliments(this.dots, 'add', this.useAlgo); this.handleColorPositions(colorPositions); @@ -702,30 +830,6 @@ this.handleColorPositions(colorPositions); this.updateCurrentWorkspace(); return; - } else if (target.id === 'PanelUI-zen-gradient-generator-color-toggle-algo') { - const colorHarmonies = [ - { type: 'complementary', angles: [180] }, - { type: 'splitComplementary', angles: [150, 210] }, - { type: 'analogous', angles: [30, 330] }, - { type: 'triadic', angles: [120, 240] }, - { type: 'floating', angles: [] }, - ]; - - const applicableHarmonies = colorHarmonies.filter( - (harmony) => harmony.angles.length + 1 === this.dots.length || harmony.type === 'floating' - ); - - let currentIndex = applicableHarmonies.findIndex( - (harmony) => harmony.type === this.useAlgo - ); - - let nextIndex = currentIndex === -1 ? 0 : (currentIndex + 1) % applicableHarmonies.length; - this.useAlgo = applicableHarmonies[nextIndex].type; - - let colorPositions = this.calculateCompliments(this.dots, 'update', this.useAlgo); - this.handleColorPositions(colorPositions); - this.updateCurrentWorkspace(); - return; } if (event.button !== 0 || this.dragging || this.recentlyDragged) return; @@ -905,76 +1009,164 @@ } themedColors(colors) { - const isDarkMode = this.isDarkMode; - const factor = isDarkMode ? 0.5 : 1.1; - return colors.map((color) => ({ c: color.isCustom ? color.c - : [ - Math.min(255, color.c[0] * factor), - Math.min(255, color.c[1] * factor), - Math.min(255, color.c[2] * factor), - ], + : [Math.min(255, color.c[0]), Math.min(255, color.c[1]), Math.min(255, color.c[2])], isCustom: color.isCustom, algorithm: color.algorithm, + lightness: color.lightness, + position: color.position, })); } onOpacityChange(event) { - this.currentOpacity = event.target.value; + this.currentOpacity = parseFloat(event.target.value); + // If we reached a whole number (e.g., 0.1, 0.2, etc.), send a haptic feedback + if ((this.currentOpacity * 10) % 1 === 0) { + Services.zen.playHapticFeedback(); + } this.updateCurrentWorkspace(); } - getToolbarModifiedBase() { + getToolbarModifiedBaseRaw() { const opacity = this.#allowTransparencyOnSidebar ? 0.6 : 1; - return this.isDarkMode - ? `color-mix(in srgb, var(--zen-themed-toolbar-bg) 96%, rgba(255,255,255,${opacity}) 4%)` - : `color-mix(in srgb, var(--zen-themed-toolbar-bg) 96%, rgba(0,0,0,${opacity}) 4%)`; + return this.isDarkMode ? [23, 23, 26, opacity] : [240, 240, 244, opacity]; + } + + getToolbarModifiedBase() { + const baseColor = this.getToolbarModifiedBaseRaw(); + return `rgba(${baseColor[0]}, ${baseColor[1]}, ${baseColor[2]}, ${baseColor[3]})`; + } + + get canBeTransparent() { + return window.matchMedia( + '(-moz-windows-mica) or (-moz-platform: macos) or ((-moz-platform: linux) and -moz-pref("zen.widget.linux.transparency"))' + ).matches; } getSingleRGBColor(color, forToolbar = false) { if (color.isCustom) { return color.c; } + const opacity = this.currentOpacity; if (forToolbar) { const toolbarBg = this.getToolbarModifiedBase(); - return `color-mix(in srgb, rgb(${color.c[0]}, ${color.c[1]}, ${color.c[2]}) ${this.currentOpacity * 100}%, ${toolbarBg} ${(1 - this.currentOpacity) * 100}%)`; + return `color-mix(in srgb, rgb(${color.c[0]}, ${color.c[1]}, ${color.c[2]}) ${opacity * 100}%, ${toolbarBg} ${(1 - opacity) * 100}%)`; } - return `rgba(${color.c[0]}, ${color.c[1]}, ${color.c[2]}, ${this.currentOpacity})`; + return `rgba(${color.c[0]}, ${color.c[1]}, ${color.c[2]}, ${opacity})`; + } + + luminance([r, g, b]) { + const a = [r, g, b].map((v) => { + v /= 255; + return v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4); + }); + return a[0] * 0.2126 + a[1] * 0.7152 + a[2] * 0.0722; + } + + contrastRatio(rgb1, rgb2) { + const lum1 = this.luminance(rgb1); + const lum2 = this.luminance(rgb2); + const brightest = Math.max(lum1, lum2); + const darkest = Math.min(lum1, lum2); + return (brightest + 0.05) / (darkest + 0.05); + } + + blendColorsRaw(rgb1, rgb2, percentage) { + const p = percentage / 100; + return [ + Math.round(rgb1[0] * p + rgb2[0] * (1 - p)), + Math.round(rgb1[1] * p + rgb2[1] * (1 - p)), + Math.round(rgb1[2] * p + rgb2[2] * (1 - p)), + ]; + } + + findOptimalBlend(dominantColor, blendTarget, minContrast = 4.5) { + let low = 0; + let high = 100; + let bestMatch = null; + + for (let i = 0; i < 10; i++) { + const mid = (low + high) / 2; + const blended = this.blendColorsRaw(dominantColor, blendTarget, mid); + const contrast = this.contrastRatio(blended, blendTarget); + + if (contrast >= minContrast) { + bestMatch = blended; + high = mid; + } else { + low = mid; + } + } + + return bestMatch || this.blendColorsRaw(dominantColor, blendTarget, 10); // fallback } getGradient(colors, forToolbar = false) { const themedColors = this.themedColors(colors); this.useAlgo = themedColors[0]?.algorithm ?? ''; + this.#currentLightness = themedColors[0]?.lightness ?? 70; + const rotation = -45; // TODO: Detect rotation based on the accent color if (themedColors.length === 0) { return forToolbar - ? 'var(--zen-themed-toolbar-bg)' + ? this.getToolbarModifiedBase() : 'var(--zen-themed-toolbar-bg-transparent)'; } else if (themedColors.length === 1) { return this.getSingleRGBColor(themedColors[0], forToolbar); - } else if (themedColors.length !== 3) { - return `linear-gradient(${this.currentRotation}deg, ${themedColors.map((color) => this.getSingleRGBColor(color, forToolbar)).join(', ')})`; - } else { + } else if (themedColors.length === 2) { + return [ + `linear-gradient(${rotation}deg, ${this.getSingleRGBColor(themedColors[0], forToolbar)} -25%, transparent 100%)`, + `linear-gradient(${rotation + 180}deg, ${this.getSingleRGBColor(themedColors[1], forToolbar)} -25%, transparent 100%)`, + ].join(', '); + } else if (themedColors.length === 3) { let color1 = this.getSingleRGBColor(themedColors[2], forToolbar); let color2 = this.getSingleRGBColor(themedColors[0], forToolbar); let color3 = this.getSingleRGBColor(themedColors[1], forToolbar); - return `linear-gradient(${this.currentRotation}deg, ${color1}, ${color2}, ${color3})`; + if (!forToolbar) { + return [ + `radial-gradient(circle at -30% -30%, ${color1}, transparent 100%)`, + `radial-gradient(circle at 130% -30%, ${color2}, transparent 100%)`, + `linear-gradient(to top, ${color3} -30%, transparent 60%)`, + ].join(', '); + } + return [`linear-gradient(${rotation}deg, ${color1} -30%, ${color3} 100%)`].join(', '); + } else { + // Just return a linear gradient with all colors + const gradientColors = themedColors.map((color) => + this.getSingleRGBColor(color, forToolbar) + ); + return `linear-gradient(${rotation}deg, ${gradientColors.join(', ')})`; } } - static getTheme(colors = [], opacity = 0.5, rotation = -45, texture = 0) { + shouldBeDarkMode(accentColor) { + let minimalLum = this.isDarkMode ? 0.6 : 0.5; + if (!this.canBeTransparent) { + // Blend the color with the toolbar background + const toolbarBg = this.getToolbarModifiedBaseRaw(); + accentColor = this.blendColorsRaw( + toolbarBg.slice(0, 3), + accentColor, + (1 - this.currentOpacity) * 100 + ); + minimalLum = this.isDarkMode ? 0.3 : 0.2; + } + const lum = this.luminance(accentColor); + // Return true if background is dark enough that white text is preferred + return lum < minimalLum; + } + + static getTheme(colors = [], opacity = 0.5, texture = 0) { return { type: 'gradient', gradientColors: colors ? colors.filter((color) => color) : [], // remove undefined opacity, - rotation, texture, }; } - //TODO: add a better noise system that adds noise not just changes transparency updateNoise(texture) { document.documentElement.style.setProperty('--zen-grainy-background-opacity', texture); document.documentElement.setAttribute( @@ -1101,6 +1293,11 @@ return color; } + blendColors(rgb1, rgb2, percentage) { + const blended = this.blendColorsRaw(rgb1, rgb2, percentage); + return `rgb(${blended[0]}, ${blended[1]}, ${blended[2]})`; + } + async onWorkspaceChange(workspace, skipUpdate = false, theme = null) { const uuid = workspace.uuid; // Use theme from workspace object or passed theme @@ -1132,7 +1329,18 @@ } } - const appBackground = browser.document.getElementById('zen-browser-background'); + if (this.isDarkMode) { + browser.document.documentElement.style.setProperty( + '--zen-themed-browser-overlay-bg', + 'rgba(255, 255, 255, 0.3)' + ); + } else { + browser.document.documentElement.style.setProperty( + '--zen-themed-browser-overlay-bg', + 'rgba(0, 0, 0, 0.2)' + ); + } + if (!skipUpdate) { browser.document.documentElement.style.setProperty( '--zen-main-browser-background-old', @@ -1140,7 +1348,7 @@ ); browser.document.documentElement.style.setProperty( '--zen-background-opacity', - browser.gZenThemePicker.previousBackgroundOpacity + browser.gZenThemePicker.previousBackgroundOpacity ?? 1 ); if (browser.gZenThemePicker.previousBackgroundResolve) { browser.gZenThemePicker.previousBackgroundResolve(); @@ -1148,18 +1356,6 @@ delete browser.gZenThemePicker.previousBackgroundOpacity; } - const button = browser.document.getElementById( - 'PanelUI-zen-gradient-generator-color-toggle-algo' - ); - if (browser.gZenThemePicker.useAlgo) { - document.l10n.setAttributes( - button, - `zen-panel-ui-gradient-generator-algo-${browser.gZenThemePicker.useAlgo}` - ); - } else { - button.removeAttribute('data-l10n-id'); - } - browser.gZenThemePicker.resetCustomColorList(); if (!workspaceTheme || workspaceTheme.type !== 'gradient') { const gradient = browser.gZenThemePicker.getGradient([]); @@ -1177,13 +1373,48 @@ '--zen-primary-color', this.getNativeAccentColor() ); + browser.document.documentElement.removeAttribute('zen-should-be-dark-mode'); return; } browser.gZenThemePicker.currentOpacity = workspaceTheme.opacity ?? 0.5; - browser.gZenThemePicker.currentRotation = workspaceTheme.rotation ?? -45; browser.gZenThemePicker.currentTexture = workspaceTheme.texture ?? 0; + const opacitySlider = browser.document.getElementById( + 'PanelUI-zen-gradient-generator-opacity' + ); + + { + let opacity = browser.gZenThemePicker.currentOpacity; + const svg = browser.gZenThemePicker.sliderWavePath; + const [_, secondStop, thirdStop] = document.querySelectorAll( + '#PanelUI-zen-gradient-generator-slider-wave-gradient stop' + ); + // Opacity can only be between 0.15 to 0.85. Make opacity relative to that range + // So 0.15 becomes 0, and 0.85 becomes 1. + if (opacity < 0.15) { + opacity = 0; + } else if (opacity > 0.85) { + opacity = 1; + } else { + opacity = (opacity - 0.15) / (0.85 - 0.15); + } + // Since it's sine waves, we can't just set the offset to the opacity, we need to calculate it + // The offset is the percentage of the wave that is visible, so we need to multiply + // the opacity by 100 to get the percentage. + // Set the offset of the stops + secondStop.setAttribute('offset', `${opacity * 100}%`); + thirdStop.setAttribute('offset', `${opacity * 100}%`); + const interpolatedPath = this.#interpolateWavePath(opacity); + svg.setAttribute('d', interpolatedPath); + opacitySlider.style.setProperty('--zen-thumb-height', `${40 + opacity * 12}px`); + opacitySlider.style.setProperty('--zen-thumb-width', `${10 + opacity * 10}px`); + svg.style.stroke = + interpolatedPath === this.#linePath + ? thirdStop.getAttribute('stop-color') + : 'url(#PanelUI-zen-gradient-generator-slider-wave-gradient)'; + } + for (const button of browser.document.querySelectorAll( '#PanelUI-zen-gradient-generator-color-actions button' )) { @@ -1191,15 +1422,14 @@ button.disabled = workspaceTheme.gradientColors.length === 0 || (button.id === 'PanelUI-zen-gradient-generator-color-add' - ? workspaceTheme.gradientColors.length >= ZenThemePicker.MAX_DOTS + ? workspaceTheme.gradientColors.length >= nsZenThemePicker.MAX_DOTS : false); } document .getElementById('PanelUI-zen-gradient-generator-color-click-to-add') .toggleAttribute('hidden', workspaceTheme.gradientColors.length > 0); - browser.document.getElementById('PanelUI-zen-gradient-generator-opacity').value = - browser.gZenThemePicker.currentOpacity; + opacitySlider.value = browser.gZenThemePicker.currentOpacity; const textureSelectWrapper = browser.document.getElementById( 'PanelUI-zen-gradient-generator-texture-wrapper' ); @@ -1228,35 +1458,6 @@ i = 0; } } - - const numberOfColors = workspaceTheme.gradientColors?.length; - const rotationDot = browser.document.getElementById( - 'PanelUI-zen-gradient-generator-rotation-dot' - ); - const rotationLine = browser.document.getElementById( - 'PanelUI-zen-gradient-generator-rotation-line' - ); - if (numberOfColors > 1) { - rotationDot.style.opacity = 1; - rotationLine.style.opacity = 1; - rotationDot.style.removeProperty('pointer-events'); - const rotationPadding = 20; - const rotationParentWidth = rotationDot.parentElement.getBoundingClientRect().width; - const rotationDotPosition = this.currentRotation; - const rotationDotWidth = 30; - const rotationDotX = - Math.cos((rotationDotPosition * Math.PI) / 180) * - (rotationParentWidth / 2 - rotationDotWidth / 2); - const rotationDotY = - Math.sin((rotationDotPosition * Math.PI) / 180) * - (rotationParentWidth / 2 - rotationDotWidth / 2); - rotationDot.style.left = `${rotationParentWidth / 2 + rotationDotX - rotationPadding + rotationDotWidth / 4}px`; - rotationDot.style.top = `${rotationParentWidth / 2 + rotationDotY - rotationPadding + rotationDotWidth / 4}px`; - } else { - rotationDot.style.opacity = 0; - rotationLine.style.opacity = 0; - rotationDot.style.pointerEvents = 'none'; - } } const gradient = browser.gZenThemePicker.getGradient(workspaceTheme.gradientColors); @@ -1290,6 +1491,25 @@ ? dominantColor : `rgb(${dominantColor[0]}, ${dominantColor[1]}, ${dominantColor[2]})` ); + let isDarkMode = this.isDarkMode; + if (dominantColor !== this.getNativeAccentColor()) { + isDarkMode = browser.gZenThemePicker.shouldBeDarkMode(dominantColor); + browser.document.documentElement.setAttribute('zen-should-be-dark-mode', isDarkMode); + } else { + browser.document.documentElement.removeAttribute('zen-should-be-dark-mode'); + } + // Set `--toolbox-textcolor` to have a contrast with the primary color + const blendTarget = isDarkMode ? [255, 255, 255] : [0, 0, 0]; + const blendedColor = this.blendColors(dominantColor, blendTarget, 15); // 15% dominantColor, 85% target + await gZenUIManager.motion.animate( + browser.document.documentElement, + { + '--toolbox-textcolor': blendedColor, + }, + { + duration: 0.05, + } + ); } if (!skipUpdate) { @@ -1364,19 +1584,18 @@ } const isCustom = dot.classList.contains('custom'); const algorithm = this.useAlgo; + const position = + dot.getAttribute('data-position') && JSON.parse(dot.getAttribute('data-position')); return { c: isCustom ? color : color.match(/\d+/g).map(Number), isCustom, algorithm, isPrimary, + lightness: this.#currentLightness, + position, }; }); - const gradient = ZenThemePicker.getTheme( - colors, - this.currentOpacity, - this.currentRotation, - this.currentTexture - ); + const gradient = nsZenThemePicker.getTheme(colors, this.currentOpacity, this.currentTexture); let currentWorkspace = await gZenWorkspaces.getActiveWorkspace(); if (!skipSave) { @@ -1402,7 +1621,38 @@ this.updateCurrentWorkspace(); }, 200); } + + #interpolateWavePath(progress) { + const linePath = this.#linePath; + const sinePath = this.#sinePath; + const referenceY = 27.3; + if (this.#sinePoints.length === 0) { + return progress < 0.5 ? linePath : sinePath; + } + if (progress <= 0.001) return linePath; + if (progress >= 0.999) return sinePath; + const t = progress; + let newPathData = ''; + this.#sinePoints.forEach((p) => { + switch (p.type) { + case 'M': + const interpolatedY = referenceY + (p.y - referenceY) * t; + newPathData += `M ${p.x} ${interpolatedY} `; + break; + case 'C': + const y1 = referenceY + (p.y1 - referenceY) * t; + const y2 = referenceY + (p.y2 - referenceY) * t; + const y = referenceY + (p.y - referenceY) * t; + newPathData += `C ${p.x1} ${y1} ${p.x2} ${y2} ${p.x} ${y} `; + break; + case 'L': + newPathData += `L ${p.x} ${p.y} `; + break; + } + }); + return newPathData.trim(); + } } - window.ZenThemePicker = ZenThemePicker; + window.nsZenThemePicker = nsZenThemePicker; } diff --git a/src/zen/workspaces/ZenWorkspaceIcons.mjs b/src/zen/workspaces/ZenWorkspaceIcons.mjs index b512fbe49..f04c41b62 100644 --- a/src/zen/workspaces/ZenWorkspaceIcons.mjs +++ b/src/zen/workspaces/ZenWorkspaceIcons.mjs @@ -145,6 +145,7 @@ i++; } buttons[selected].setAttribute('active', true); + this.scrollLeft = buttons[selected].offsetLeft - 10; this.setAttribute('selected', selected); } diff --git a/src/zen/workspaces/ZenWorkspaces.mjs b/src/zen/workspaces/ZenWorkspaces.mjs index 37a0c3967..2bc0a62b6 100644 --- a/src/zen/workspaces/ZenWorkspaces.mjs +++ b/src/zen/workspaces/ZenWorkspaces.mjs @@ -885,7 +885,7 @@ var gZenWorkspaces = new (class extends ZenMultiWindowFeature { this.activeWorkspace = activeWorkspace?.uuid; try { if (activeWorkspace) { - window.gZenThemePicker = new ZenThemePicker(); + window.gZenThemePicker = new nsZenThemePicker(); await gZenThemePicker.onWorkspaceChange(activeWorkspace); } } catch (e) { @@ -2179,7 +2179,7 @@ var gZenWorkspaces = new (class extends ZenMultiWindowFeature { uuid: gZenUIManager.generateUuidv4(), icon: icon, name: name, - theme: ZenThemePicker.getTheme([]), + theme: nsZenThemePicker.getTheme([]), containerTabId, }; if (moveTabs) { diff --git a/src/zen/workspaces/overflow-icons.inc.css b/src/zen/workspaces/overflow-icons.inc.css index 7d966fdd1..930290bda 100644 --- a/src/zen/workspaces/overflow-icons.inc.css +++ b/src/zen/workspaces/overflow-icons.inc.css @@ -6,6 +6,8 @@ &:not(:hover) { width: min(var(--zen-overflowed-workspace-button-width), 25px); + min-width: 10px; + &::after { content: ''; position: absolute; diff --git a/src/zen/workspaces/zen-gradient-generator.css b/src/zen/workspaces/zen-gradient-generator.css index 24564c89d..fff9923d2 100644 --- a/src/zen/workspaces/zen-gradient-generator.css +++ b/src/zen/workspaces/zen-gradient-generator.css @@ -5,7 +5,7 @@ */ #PanelUI-zen-gradient-generator { - --panel-width: 320px; + --panel-width: 340px; --panel-padding: 10px; min-width: var(--panel-width); } @@ -20,6 +20,7 @@ #PanelUI-zen-gradient-generator-controls { align-items: center; gap: var(--panel-padding); + padding-top: 10px; } #zen-theme-picker-color { @@ -62,7 +63,11 @@ padding: 0 var(--panel-padding); @media (-moz-platform: macos) { - gap: 3rem; + gap: 2rem; + } + + #PanelUI-zen-gradient-opacity-wrapper { + position: relative; } & label { @@ -76,46 +81,58 @@ } } -#PanelUI-zen-gradient-generator-predefined { +#PanelUI-zen-gradient-generator-color-pages-wrapper { + align-items: center; +} + +#PanelUI-zen-gradient-generator-color-pages { display: flex; justify-content: space-around; + margin: 0 10px; align-items: center; - margin: 5px auto 10px auto; width: 100%; + overflow: auto; + scrollbar-width: none; + scroll-behavior: smooth; - & > box { - width: 18px; - height: 18px; - border-radius: 50%; - cursor: pointer; - position: relative; - transition: transform 0.1s; - &::after { - content: ''; - position: absolute; + & > hbox { + justify-content: space-around; + min-width: 100%; + + & > box { width: 18px; height: 18px; - top: 0; - left: 0; - outline: 2px solid var(--zen-toolbar-element-bg); border-radius: 50%; - pointer-events: none; + cursor: pointer; + position: relative; transition: transform 0.1s; - } - - &:hover { - transform: scale(1.05); - &::after { - transform: scale(1.05); + content: ''; + position: absolute; + width: 18px; + height: 18px; + top: 0; + left: 0; + outline: 2px solid var(--zen-toolbar-element-bg); + border-radius: 50%; + pointer-events: none; + transition: transform 0.1s; } - } - &:hover:active { - transform: scale(0.95); + &:hover { + transform: scale(1.05); - &::after { + &::after { + transform: scale(1.05); + } + } + + &:hover:active { transform: scale(0.95); + + &::after { + transform: scale(0.95); + } } } } @@ -164,46 +181,72 @@ } } -#PanelUI-zen-gradient-generator-opacity, -#PanelUI-zen-gradient-generator-texture { +#PanelUI-zen-gradient-slider-wave { + position: absolute; + top: 3px; + left: -3px; + width: 100%; + height: 100%; + pointer-events: none; + z-index: 1; + display: flex; + align-items: center; + justify-content: flex-start; + scale: 1.2; + + &::before { + content: ''; + position: absolute; + width: 100%; + height: 16px; + background: light-dark(rgba(0, 0, 0, 0.1), rgba(255, 255, 255, 0.1)); + border-radius: 999px; + pointer-events: none; + z-index: -1; + top: -1px; + left: 4px; + scale: 0.85; + } + + & svg { + overflow: visible; + min-width: calc(100% + 2.5rem); + } +} + +#PanelUI-zen-gradient-generator-opacity { margin: 0 !important; - margin-top: 5px !important; background: transparent; + z-index: 2; &::-moz-range-thumb { - background: var(--zen-colors-tertiary); - border: 2px solid var(--zen-colors-border); - border-radius: 12px; - height: 25px; - width: 13px; + background: light-dark(black, white); + border-radius: 999px; + height: var(--zen-thumb-height); + width: var(--zen-thumb-width); cursor: pointer; + border: none; } &::-moz-range-track { - background: light-dark(rgba(0, 0, 0, 0.3), rgba(255, 255, 255, 0.3)); border-radius: 999px; - height: 6px; + height: 18px; } &::-moz-range-progress { - background: var(--zen-primary-color); - border-radius: 999px; - height: 8px; + background: transparent; } } .zen-theme-picker-gradient { position: relative; - border-radius: calc(var(--zen-border-radius) - 2px); overflow: hidden; border-radius: var(--zen-border-radius); - min-height: calc(var(--panel-width) - var(--panel-padding) * 2); - margin-bottom: 20px; - - background: var(--zen-toolbar-element-bg); + min-height: calc(var(--panel-width) - var(--panel-padding) * 2 - 2px); + background: color-mix(in srgb, var(--zen-toolbar-element-bg) 60%, transparent 40%); background-image: radial-gradient( - light-dark(rgba(0, 0, 0, 0.08), rgba(0, 0, 0, 0.4)) 1px, + light-dark(rgba(0, 0, 0, 0.08), rgba(255, 255, 255, 0.1)) 1px, transparent 0 ); background-position: -19px -19px; @@ -220,7 +263,7 @@ box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.1); } cursor: pointer; - border: 2px solid #ffffff; + border: 3px solid #ffffff; animation: zen-theme-picker-dot-animation 0.5s; transform: translate(-50%, -50%); @@ -229,7 +272,7 @@ height: 36px; border-width: 4px; z-index: 2; - transition: transform 0.1s; + transition: transform 0.2s; &:hover { transform: scale(1.05) translate(-50%, -50%); } @@ -241,6 +284,10 @@ } } +#PanelUI-zen-gradient-generator-view { + gap: 10px; +} + #PanelUI-zen-gradient-generator-color-click-to-add { position: absolute; font-weight: 600; @@ -255,17 +302,15 @@ } } -#PanelUI-zen-gradient-generator-color-actions { +#PanelUI-zen-gradient-generator-color-actions, +#PanelUI-zen-gradient-generator-scheme { display: flex; position: absolute; - bottom: 8px; + bottom: 12px; left: 50%; z-index: 1; transform: translateX(-50%); - & .separator, - & #PanelUI-zen-gradient-generator-color-toggle-algo { - background: light-dark(rgba(0, 0, 0, 0.1), rgba(255, 255, 255, 0.15)); - } + gap: 5px; & button { border: none !important; @@ -273,17 +318,20 @@ min-width: fit-content !important; transition: background 0.2s; appearance: none; + max-height: 26px; + max-width: 26px; + color: light-dark(rgba(0, 0, 0, 0.7), rgba(255, 255, 255, 0.9)); & .button-box { gap: 0.1rem; } - &:not(#PanelUI-zen-gradient-generator-color-toggle-algo) .button-text { + & .button-text { display: none; } &:hover { - background: light-dark(#cfcfcf, #313131); + background: light-dark(rgba(0, 0, 0, 0.1), rgba(255, 255, 255, 0.1)); } &[disabled] { @@ -291,12 +339,11 @@ cursor: not-allowed; } } +} - & .separator { - width: 1px; - margin: 0 0.5rem; - height: 30px; - } +#PanelUI-zen-gradient-generator-scheme { + top: 15px; + max-height: 32px; } @media not -moz-pref('zen.theme.gradient.show-custom-colors') { @@ -311,9 +358,8 @@ position: relative; @media (-moz-platform: macos) { - width: 25%; - aspect-ratio: 1; - height: unset; + width: 5rem; + height: 5rem; } &::after { @@ -381,32 +427,9 @@ } } -#PanelUI-zen-gradient-generator-rotation-line { - border: 1px solid var(--zen-colors-border); - position: absolute; - --rotation-padding: 15px; - width: calc(100% - var(--rotation-padding) * 2); - border-bottom-color: transparent; - height: calc(100% - var(--rotation-padding) * 2); - top: var(--rotation-padding); - left: var(--rotation-padding); - border-radius: 50%; - opacity: 0; - pointer-events: none; -} - -#PanelUI-zen-gradient-generator-rotation-dot { - position: absolute; - width: 25px; - height: 25px; - border-radius: 50%; - border: 1px solid var(--zen-colors-border); - background: var(--zen-colors-tertiary); - opacity: 0; - cursor: pointer; - z-index: 2; - transition: transform 0.1s; - &:hover { - transform: scale(1.1); - } +#PanelUI-zen-gradient-generator-color-page-left, +#PanelUI-zen-gradient-generator-color-page-right { + max-width: 28px; + max-height: 28px; + margin: 0 !important; }