diff --git a/src/browser/base/content/zen-panels/gradient-generator.inc b/src/browser/base/content/zen-panels/gradient-generator.inc
index b5f87468b..6bc5830d2 100644
--- a/src/browser/base/content/zen-panels/gradient-generator.inc
+++ b/src/browser/base/content/zen-panels/gradient-generator.inc
@@ -12,10 +12,9 @@
-
-
+
+
+
@@ -78,6 +77,27 @@
+
+# Start from black to white in a span on 8 steps and.
+# They must all go from the middle to the right side. They must always stay verically centered.
+# And reach to 180 on the right side, meaning we must divide the width in 16 segments.
+
+
+
+
+
+
+
+
+
diff --git a/src/browser/themes/shared/zen-icons/icons.css b/src/browser/themes/shared/zen-icons/icons.css
index 258f007f3..80db0d71d 100644
--- a/src/browser/themes/shared/zen-icons/icons.css
+++ b/src/browser/themes/shared/zen-icons/icons.css
@@ -692,6 +692,10 @@
list-style-image: url('container-tab.svg') !important;
}
+#PanelUI-zen-gradient-generator-color-toggle-algo {
+ list-style-image: url('algorithm.svg');
+}
+
#appMenuClearRecentHistory {
list-style-image: url('edit-delete.svg') !important;
}
diff --git a/src/browser/themes/shared/zen-icons/jar.inc.mn b/src/browser/themes/shared/zen-icons/jar.inc.mn
index 485933c80..2efa99098 100644
--- a/src/browser/themes/shared/zen-icons/jar.inc.mn
+++ b/src/browser/themes/shared/zen-icons/jar.inc.mn
@@ -3,6 +3,7 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifdef XP_WIN
+* skin/classic/browser/zen-icons/algorithm.svg (../shared/zen-icons/lin/algorithm.svg)
* skin/classic/browser/zen-icons/arrow-down.svg (../shared/zen-icons/lin/arrow-down.svg)
* skin/classic/browser/zen-icons/arrow-left.svg (../shared/zen-icons/lin/arrow-left.svg)
* skin/classic/browser/zen-icons/arrow-right.svg (../shared/zen-icons/lin/arrow-right.svg)
@@ -131,6 +132,7 @@
* skin/classic/browser/zen-icons/zoom-out.svg (../shared/zen-icons/lin/zoom-out.svg)
#endif
#ifdef XP_MACOSX
+* skin/classic/browser/zen-icons/algorithm.svg (../shared/zen-icons/lin/algorithm.svg)
* skin/classic/browser/zen-icons/arrow-down.svg (../shared/zen-icons/lin/arrow-down.svg)
* skin/classic/browser/zen-icons/arrow-left.svg (../shared/zen-icons/lin/arrow-left.svg)
* skin/classic/browser/zen-icons/arrow-right.svg (../shared/zen-icons/lin/arrow-right.svg)
@@ -259,6 +261,7 @@
* skin/classic/browser/zen-icons/zoom-out.svg (../shared/zen-icons/lin/zoom-out.svg)
#endif
#ifdef XP_LINUX
+* skin/classic/browser/zen-icons/algorithm.svg (../shared/zen-icons/lin/algorithm.svg)
* skin/classic/browser/zen-icons/arrow-down.svg (../shared/zen-icons/lin/arrow-down.svg)
* skin/classic/browser/zen-icons/arrow-left.svg (../shared/zen-icons/lin/arrow-left.svg)
* skin/classic/browser/zen-icons/arrow-right.svg (../shared/zen-icons/lin/arrow-right.svg)
diff --git a/src/browser/themes/shared/zen-icons/lin/algorithm.svg b/src/browser/themes/shared/zen-icons/lin/algorithm.svg
new file mode 100644
index 000000000..f35991ccc
--- /dev/null
+++ b/src/browser/themes/shared/zen-icons/lin/algorithm.svg
@@ -0,0 +1,5 @@
+#filter dumbComments emptyLines substitution
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
\ No newline at end of file
diff --git a/src/browser/themes/shared/zen-icons/lin/face-sun.svg b/src/browser/themes/shared/zen-icons/lin/face-sun.svg
index 432970d42..543e131a0 100644
--- a/src/browser/themes/shared/zen-icons/lin/face-sun.svg
+++ b/src/browser/themes/shared/zen-icons/lin/face-sun.svg
@@ -2,4 +2,4 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
\ No newline at end of file
+
\ 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
index 031c60f8e..f4739fbae 100644
--- a/src/browser/themes/shared/zen-icons/lin/moon-stars.svg
+++ b/src/browser/themes/shared/zen-icons/lin/moon-stars.svg
@@ -2,4 +2,4 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
\ No newline at end of file
+
\ 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
index 77cc7d3ff..63f0bf063 100644
--- a/src/browser/themes/shared/zen-icons/lin/sparkles.svg
+++ b/src/browser/themes/shared/zen-icons/lin/sparkles.svg
@@ -2,4 +2,4 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/src/zen/common/styles/zen-animations.css b/src/zen/common/styles/zen-animations.css
index ae77e9502..1c2bd3c69 100644
--- a/src/zen/common/styles/zen-animations.css
+++ b/src/zen/common/styles/zen-animations.css
@@ -18,13 +18,13 @@
@keyframes zen-theme-picker-dot-animation {
from {
- transform: scale(0.8) translate(-50%, -50%);
+ transform: scale(0.8) translate(-25%, -25%);
}
50% {
- transform: scale(1.2) translate(-50%, -50%);
+ transform: scale(1.2) translate(-25%, -25%);
}
to {
- transform: scale(1) translate(-50%, -50%);
+ transform: scale(1) translate(-25%, -25%);
}
}
diff --git a/src/zen/workspaces/ZenGradientGenerator.mjs b/src/zen/workspaces/ZenGradientGenerator.mjs
index ba3f1edbe..377765efb 100644
--- a/src/zen/workspaces/ZenGradientGenerator.mjs
+++ b/src/zen/workspaces/ZenGradientGenerator.mjs
@@ -45,6 +45,7 @@ const MAX_OPACITY = 0.9;
const MIN_OPACITY = AppConstants.platform === 'macosx' ? 0.25 : 0.35;
const EXPLICIT_LIGHTNESS_TYPE = 'explicit-lightness';
+const EXPLICIT_BLACKWHITE_TYPE = 'explicit-black-white';
export class nsZenThemePicker extends nsZenMultiWindowFeature {
static MAX_DOTS = 3;
@@ -146,6 +147,7 @@ export class nsZenThemePicker extends nsZenMultiWindowFeature {
get colorHarmonies() {
return [
{ type: 'complementary', angles: [180] },
+ { type: 'singleAnalogous', angles: [310] },
{ type: 'splitComplementary', angles: [150, 210] },
{ type: 'analogous', angles: [50, 310] },
{ type: 'triadic', angles: [120, 240] },
@@ -198,6 +200,7 @@ export class nsZenThemePicker extends nsZenMultiWindowFeature {
}
this.dots = this.dots.slice(0, numDots);
}
+ const type = target.getAttribute('data-type') || EXPLICIT_LIGHTNESS_TYPE;
// Generate new gradient from the single color given
const [x, y] = rawPosition.split(',').map((pos) => parseInt(pos));
let dots = [
@@ -205,18 +208,18 @@ export class nsZenThemePicker extends nsZenMultiWindowFeature {
ID: 0,
position: { x, y },
isPrimary: true,
- type: EXPLICIT_LIGHTNESS_TYPE,
+ type,
},
];
for (let i = 1; i < numDots; i++) {
dots.push({
ID: i,
position: { x: 0, y: 0 },
- type: EXPLICIT_LIGHTNESS_TYPE,
+ type,
});
}
this.useAlgo = algo;
- this.#currentLightness = lightness;
+ if (lightness !== null) this.#currentLightness = lightness;
dots = this.calculateCompliments(dots, 'update', this.useAlgo);
this.handleColorPositions(dots, true);
this.updateCurrentWorkspace();
@@ -416,10 +419,10 @@ export class nsZenThemePicker extends nsZenMultiWindowFeature {
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 = 30;
+ const padding = 0;
const rect = {
- width: 338,
- height: 338,
+ width: 380 + padding * 2,
+ height: 380 + padding * 2,
};
const centerX = rect.width / 2;
const centerY = rect.height / 2;
@@ -437,7 +440,7 @@ export class nsZenThemePicker extends nsZenMultiWindowFeature {
const gradient = this.panel.querySelector('.zen-theme-picker-gradient');
const rect = gradient.getBoundingClientRect();
const padding = 30; // each side
- const dotHalfSize = 36 / 2; // half the size of the dot
+ const dotHalfSize = 38 / 2; // half the size of the dot
x += dotHalfSize;
y += dotHalfSize;
rect.width += padding * 2; // Adjust width and height for padding
@@ -452,7 +455,7 @@ export class nsZenThemePicker extends nsZenMultiWindowFeature {
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)
+ let hue = (angle / 360) * 360; // Normalize angle to [0, 360)
let saturation = normalizedDistance * 100; // stays high even in center
if (type !== EXPLICIT_LIGHTNESS_TYPE) {
saturation = 80 + (1 - normalizedDistance) * 20;
@@ -460,7 +463,12 @@ export class nsZenThemePicker extends nsZenMultiWindowFeature {
// For example, moving the dot outside will have higher lightness, while moving it inside will have lower lightness
this.#currentLightness = Math.round((1 - normalizedDistance) * 100);
}
- const lightness = this.#currentLightness; // Fixed lightness for simplicity
+ let lightness = this.#currentLightness; // Fixed lightness for simplicity
+ if (type === EXPLICIT_BLACKWHITE_TYPE) {
+ // We can only get grayscales from white to black
+ saturation = 0;
+ lightness = Math.round((1 - normalizedDistance) * 100);
+ }
const [r, g, b] = this.hslToRgb(hue / 360, saturation / 100, lightness / 100);
return [
Math.min(255, Math.max(0, r)),
@@ -675,7 +683,13 @@ export class nsZenThemePicker extends nsZenMultiWindowFeature {
}
if (action === 'remove') {
- return colorHarmonies.find((harmony) => harmony.angles.length === numDots);
+ let harmony = colorHarmonies.find((harmony) => harmony.angles.length === numDots);
+ // If we are coming from 3 analogous dots, we should now go to singleAnalogous if
+ // there are 2 dots left
+ if (harmony.type === 'analogous' && numDots === 1) {
+ harmony = colorHarmonies.find((harmony) => harmony.type === 'singleAnalogous');
+ }
+ return harmony;
}
if (action === 'add') {
return colorHarmonies.find((harmony) => harmony.angles.length + 1 === numDots);
@@ -700,7 +714,7 @@ export class nsZenThemePicker extends nsZenMultiWindowFeature {
const dotPad = this.panel.querySelector('.zen-theme-picker-gradient');
const rect = dotPad.getBoundingClientRect();
- const padding = 30;
+ const padding = 0;
let updatedDots = [...dots];
const centerPosition = { x: rect.width / 2, y: rect.height / 2 };
@@ -843,16 +857,30 @@ export class nsZenThemePicker extends nsZenMultiWindowFeature {
this.handleColorPositions(colorPositions);
this.updateCurrentWorkspace();
return;
+ } else if (target.id === 'PanelUI-zen-gradient-generator-color-toggle-algo') {
+ const applicableHarmonies = this.colorHarmonies.filter(
+ (harmony) => harmony.angles.length + 1 === this.dots.length
+ );
+
+ let currentIndex = applicableHarmonies.findIndex((harmony) => harmony.type === this.useAlgo);
+
+ const 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;
const gradient = this.panel.querySelector('.zen-theme-picker-gradient');
const rect = gradient.getBoundingClientRect();
- const padding = 30;
+ const padding = 0;
- const centerX = rect.left + rect.width / 2;
- const centerY = rect.top + rect.height / 2;
+ const centerX = rect.left + rect.width / 2 - padding;
+ const centerY = rect.top + rect.height / 2 - padding;
const radius = (rect.width - padding) / 2;
let pixelX = event.clientX;
let pixelY = event.clientY;
@@ -982,7 +1010,7 @@ export class nsZenThemePicker extends nsZenMultiWindowFeature {
if (this.dragging) {
event.preventDefault();
const rect = this.panel.querySelector('.zen-theme-picker-gradient').getBoundingClientRect();
- const padding = 30; // each side
+ const padding = 0; // each side
// do NOT let the ball be draged outside of an imaginary circle. You can drag it anywhere inside the circle
// if the distance between the center of the circle and the dragged ball is bigger than the radius, then the ball
// should be placed on the edge of the circle. If it's inside the circle, then the ball just follows the mouse
@@ -1164,7 +1192,7 @@ export class nsZenThemePicker extends nsZenMultiWindowFeature {
if (!forToolbar) {
return [
`linear-gradient(${rotation}deg, ${this.getSingleRGBColor(themedColors[1], forToolbar)} 0%, transparent 100%)`,
- `linear-gradient(${rotation + 180}deg, ${this.getSingleRGBColor(themedColors[0], forToolbar)} 0%, transparent 80%)`,
+ `linear-gradient(${rotation + 180}deg, ${this.getSingleRGBColor(themedColors[0], forToolbar)} 0%, transparent 100%)`,
]
.reverse()
.join(', ');
@@ -1175,8 +1203,8 @@ export class nsZenThemePicker extends nsZenMultiWindowFeature {
let color2 = this.getSingleRGBColor(themedColors[0], forToolbar);
let color3 = this.getSingleRGBColor(themedColors[1], forToolbar);
return [
+ `radial-gradient(circle at 0% 0%, ${color2} -10%, transparent 100%)`,
`linear-gradient(to top, ${color1} -50%, transparent 125%)`,
- `radial-gradient(circle at 0% 0%, ${color2} 10%, transparent 80%)`,
`radial-gradient(circle at 100% -100%, ${color3} -100%, transparent 400%)`,
].join(', ');
}
@@ -1389,6 +1417,9 @@ export class nsZenThemePicker extends nsZenMultiWindowFeature {
workspaceTheme.gradientColors.length === 0 ||
(button.id === 'PanelUI-zen-gradient-generator-color-add'
? workspaceTheme.gradientColors.length >= nsZenThemePicker.MAX_DOTS
+ : false) ||
+ (button.id === 'PanelUI-zen-gradient-generator-color-toggle-algo'
+ ? workspaceTheme.gradientColors.length < 2
: false);
}
const clickToAdd = browser.document.getElementById(
diff --git a/src/zen/workspaces/zen-gradient-generator.css b/src/zen/workspaces/zen-gradient-generator.css
index 24004a1d5..3e4ca8911 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: 360px;
+ --panel-width: 380px;
--panel-padding: 10px;
min-width: var(--panel-width);
}
@@ -102,15 +102,16 @@
overflow: auto;
scrollbar-width: none;
scroll-behavior: smooth;
- mask-image: linear-gradient(to right, transparent 0%, black 2.5%, black 97.5%, transparent 100%);
& > hbox {
- justify-content: space-around;
+ justify-content: space-between;
min-width: 100%;
+ padding: 0 1px;
& > box {
- width: 22px;
- height: 22px;
+ width: 26px;
+ height: 26px;
+ box-shadow: 0 0 1px 1px rgba(0, 0, 0, 0.1);
border-radius: 50%;
cursor: pointer;
position: relative;
@@ -251,17 +252,17 @@
min-height: calc(var(--panel-width) - var(--panel-padding) * 2 - 2px);
background: light-dark(rgba(0, 0, 0, 0.05), rgba(255, 255, 255, 0.03));
background-image: radial-gradient(
- light-dark(rgba(0, 0, 0, 0.2), rgba(255, 255, 255, 0.1)) 1px,
+ light-dark(rgba(0, 0, 0, 0.2), rgba(255, 255, 255, 0.1)) 0.5px,
transparent 0
);
background-position: -23px -23px;
background-size: 6px 6px;
& .zen-theme-picker-dot {
- position: absolute;
+ position: fixed;
z-index: 2;
- width: 18px;
- height: 18px;
+ width: 20px;
+ height: 20px;
border-radius: 50%;
background: var(--zen-theme-picker-dot-color);
@media (-prefers-color-scheme: dark) {
@@ -270,25 +271,25 @@
cursor: pointer;
border: 3px solid #ffffff;
animation: zen-theme-picker-dot-animation 0.5s;
- transform: translate(-50%, -50%);
+ transform: translate(-25%, -25%);
pointer-events: none;
transform-origin: center center;
&:first-of-type {
- width: 36px;
- height: 36px;
+ width: 38px;
+ height: 38px;
border-width: 4px;
z-index: 2;
pointer-events: all;
transition: transform 0.2s;
z-index: 999;
&:hover {
- transform: scale(1.05) translate(-50%, -50%);
+ transform: scale(1.05) translate(-25%, -25%);
}
}
&[dragging='true'] {
- transform: scale(1.2) translate(-50%, -50%) !important;
+ transform: scale(1.2) translate(-25%, -25%) !important;
}
}
}
@@ -329,10 +330,10 @@
min-width: fit-content !important;
transition: background 0.2s;
appearance: none;
- max-height: 26px;
- max-width: 26px;
- min-height: 26px;
- min-width: 26px !important;
+ max-height: 30px;
+ max-width: 30px;
+ min-height: 30px;
+ min-width: 30px !important;
color: light-dark(rgba(0, 0, 0, 0.7), rgba(255, 255, 255, 0.9));
& .button-box {