diff --git a/ghost/admin/app/components/modals/newsletters/components/color-picker.hbs b/ghost/admin/app/components/modals/newsletters/components/color-picker.hbs
index 66fc3a05f9..c6f225744b 100644
--- a/ghost/admin/app/components/modals/newsletters/components/color-picker.hbs
+++ b/ghost/admin/app/components/modals/newsletters/components/color-picker.hbs
@@ -1,17 +1,16 @@
-
diff --git a/ghost/admin/app/components/modals/newsletters/components/color-picker.js b/ghost/admin/app/components/modals/newsletters/components/color-picker.js
index c61b6ca6a1..5f4e9d83c7 100644
--- a/ghost/admin/app/components/modals/newsletters/components/color-picker.js
+++ b/ghost/admin/app/components/modals/newsletters/components/color-picker.js
@@ -1,7 +1,17 @@
import Component from '@glimmer/component';
import {action} from '@ember/object';
+import {tracked} from '@glimmer/tracking';
export default class ColorPicker extends Component {
+ @tracked
+ orderedPresetColors = [];
+ @tracked
+ mouseOver = false;
+ @tracked
+ lastSelectedCustomColor = null;
+
+ timer;
+
get presetColors() {
return this.args.presetColors ?? [];
}
@@ -19,8 +29,81 @@ export default class ColorPicker extends Component {
this.currentColor = value;
}
- get availablePresetColors() {
- return this.presetColors.filter(preset => preset.value !== this.currentColor);
+ @action
+ onMouseEnter() {
+ this.mouseOver = true;
+
+ if (this.timer) {
+ clearTimeout(this.timer);
+ this.timer = null;
+ }
+ }
+
+ @action
+ onMouseLeave() {
+ this.mouseOver = false;
+
+ if (this.timer) {
+ clearTimeout(this.timer);
+ }
+
+ // Wait 200ms after the animation to update
+ // we need to do this on mouse leave, because on mouse enter it breaks the animations
+ this.timer = setTimeout(() => {
+ if (!this.mouseOver) {
+ this.updateOrderedPresetColors();
+ }
+ this.timer = null;
+ }, 500);
+ }
+
+ @action
+ updateOrderedPresetColors() {
+ const customColorSelected = !this.presetColors.find(c => c.value === this.currentColor);
+ const orderedPresetColors = this.presetColors.filter(c => c.value !== this.currentColor);
+ if (!customColorSelected) {
+ // Never append custom colors here
+ orderedPresetColors.push(this.currentColorObject);
+ } else {
+ // Append custom
+ //orderedPresetColors.push({
+ }
+ this.orderedPresetColors = orderedPresetColors;
+ }
+
+ get dynamicOrderedPresetColors() {
+ // Createa deep clone so we don't update anything
+ const arr = [...this.orderedPresetColors.map((c) => {
+ return {...c};
+ })];
+
+ // Make sure all preset colors are presents
+ for (const preset of this.presetColors) {
+ if (!arr.find(c => c.value === preset.value)) {
+ arr.push({...preset});
+ }
+ }
+
+ return arr;
+ }
+
+ get customColorSelected() {
+ if (!this.dynamicOrderedPresetColors.find(c => c.value === this.currentColor)) {
+ return true;
+ }
+ return false;
+ }
+
+ get customColorStyle() {
+ // Make sure the current color is present
+ if (!this.dynamicOrderedPresetColors.find(c => c.value === this.currentColor)) {
+ return 'background: ' + this.currentColor + ' !important;';
+ } else {
+ if (this.lastSelectedCustomColor) {
+ return 'background: ' + this.lastSelectedCustomColor + ' !important;';
+ }
+ }
+ return '';
}
get currentColorObject() {
@@ -33,11 +116,14 @@ export default class ColorPicker extends Component {
value: this.currentColor,
name: this.currentColor,
class: 'custom-value',
- style: 'background-color: ' + this.currentColor + ' !important;'
+ style: 'background: ' + this.currentColor + ' !important;'
};
}
get colorInputValue() {
+ if (this.lastSelectedCustomColor) {
+ return this.lastSelectedCustomColor;
+ }
if (!this.currentColorObject.value || !this.currentColorObject.value.startsWith('#')) {
return '#000000';
}
@@ -65,6 +151,7 @@ export default class ColorPicker extends Component {
}
if (newColor.match(/#[0-9A-Fa-f]{6}$/)) {
+ this.lastSelectedCustomColor = newColor.toUpperCase();
this.setCurrentColor(newColor.toUpperCase());
}
}
diff --git a/ghost/admin/app/styles/layouts/members.css b/ghost/admin/app/styles/layouts/members.css
index 43fbe8ee0b..51d5125b8d 100644
--- a/ghost/admin/app/styles/layouts/members.css
+++ b/ghost/admin/app/styles/layouts/members.css
@@ -1738,6 +1738,11 @@ p.gh-members-import-errordetail:first-of-type {
.gh-email-design-color-picker .gh-btn-group {
vertical-align: middle;
+
+ /* Required to remove glitches in mouseover during animations */
+ overflow: hidden;
+ padding: 4px;
+ margin-right: -4px;
}
.gh-email-design-color-picker .gh-btn-group p {
@@ -1775,7 +1780,7 @@ p.gh-members-import-errordetail:first-of-type {
width: 22px;
height: 22px;
margin: 0 0 0 5px;
- border: 1px solid transparent;
+ /*border: 1px solid transparent;*/
transition: all .15s ease-in-out;
transition-delay: .05s;
}
@@ -1785,7 +1790,7 @@ p.gh-members-import-errordetail:first-of-type {
width: 22px;
height: 22px;
margin: 0 0 0 5px;
- border: 1px solid transparent;
+ /*border: 1px solid transparent;*/
}
.gh-email-design-color.gh-btn-group-selected::before {
@@ -1810,7 +1815,7 @@ p.gh-members-import-errordetail:first-of-type {
.gh-btn-group .gh-email-design-color.transparent {
background: transparent;
- border: 1px solid var(--lightgrey);
+ /*border: 1px solid var(--lightgrey);*/
}
.gh-email-design-color.transparent::after {
@@ -1828,7 +1833,7 @@ p.gh-members-import-errordetail:first-of-type {
.gh-btn-group .gh-email-design-color.white {
background: var(--white) !important;
- border: 1px solid var(--lightgrey-l1);
+ /*border: 1px solid var(--lightgrey-l1);*/
}
.gh-btn-group .gh-email-design-color.black {