+
+
(null);
- type ColorType = 'RGB' | 'HSL';
+ type ColorType = 'RGB' | 'HSL' | 'RGBA' | 'HSLA';
- const colorTypes = ['RGB', 'HSL'] as ColorType[];
- const colorType = ref('RGB');
+ let colorTypes = props.opacity ? ref(['RGBA', 'HSLA']) : ref(['RGB', 'HSL']);
+ const colorType = ref(props.opacity ? 'RGBA' : 'RGB');
function unsetColor() {
emit('input', null);
@@ -164,6 +243,25 @@ export default defineComponent({
(htmlColorInput.value?.$el as HTMLElement).getElementsByTagName('input')[0].click();
}
+ function setShowAlpha(val: boolean) {
+ if (val) {
+ colorTypes.value = ['RGBA', 'HSLA'];
+ if (colorType.value === 'RGB' || colorType.value === 'RGBA') {
+ colorType.value = 'RGBA';
+ } else {
+ colorType.value = 'HSLA';
+ }
+ } else {
+ setValue('alpha', 0, 100);
+ if (colorType.value === 'RGB' || colorType.value === 'RGBA') {
+ colorType.value = 'RGB';
+ } else {
+ colorType.value = 'HSL';
+ }
+ colorTypes.value = ['RGB', 'HSL'];
+ }
+ }
+
const isValidColor = computed(() => rgb.value !== null && props.value !== null);
const lowContrast = computed(() => {
@@ -175,7 +273,7 @@ export default defineComponent({
return color.value.contrast(pageColor) < 1.1;
});
- const { hsl, rgb, hex, color } = useColor();
+ const { hsl, rgb, hex, alpha, color } = useColor();
return {
t,
@@ -184,30 +282,50 @@ export default defineComponent({
rgb,
hsl,
hex,
+ alpha,
htmlColorInput,
activateColorPicker,
isValidColor,
Color,
setValue,
+ setSwatchValue,
lowContrast,
unsetColor,
+ setShowAlpha,
};
- function setValue(type: 'rgb' | 'hsl', i: number, val: number) {
+ function setValue(type: 'rgb' | 'hsl' | 'alpha', i: number, val: number) {
if (type === 'rgb') {
const newArray = [...rgb.value];
newArray[i] = val;
rgb.value = newArray;
- } else {
+ } else if (type === 'hsl') {
const newArray = [...hsl.value];
newArray[i] = val;
hsl.value = newArray;
+ } else {
+ alpha.value = val;
}
}
+ function setSwatchValue(color: string) {
+ hex.value = `${color}${hex.value !== null && hex.value.length === 9 ? hex.value.substr(-2) : ''}`;
+ }
+
function useColor() {
const color = ref(null);
+ const getHexa = (): string | null => {
+ if (color.value !== null) {
+ let alpha = Math.round(255 * color.value.alpha())
+ .toString(16)
+ .toUpperCase();
+ alpha = alpha.padStart(2, '0');
+ return color.value.rgb().array().length === 4 ? `${color.value.hex()}${alpha}` : color.value.hex();
+ }
+ return null;
+ };
+
watch(
() => props.value,
(newValue) => {
@@ -218,25 +336,27 @@ export default defineComponent({
const rgb = computed({
get() {
- return color.value !== null ? color.value.rgb().array().map(Math.round) : [0, 0, 0];
+ const arr = color.value !== null ? color.value.rgb().array() : props.opacity ? [0, 0, 0, 1] : [0, 0, 0];
+ return arr.length === 4 ? [...arr.slice(0, -1).map(Math.round), arr[3]] : arr.map(Math.round);
},
set(newRGB) {
- setColor(Color.rgb(newRGB));
+ setColor(Color.rgb(newRGB).alpha(newRGB.length === 4 ? newRGB[3] : 1));
},
});
const hsl = computed({
get() {
- return color.value !== null ? color.value.hsl().array().map(Math.round) : [0, 0, 0];
+ const arr = color.value !== null ? color.value.hsl().array() : props.opacity ? [0, 0, 0, 1] : [0, 0, 0];
+ return arr.length === 4 ? [...arr.slice(0, -1).map(Math.round), arr[3]] : arr.map(Math.round);
},
set(newHSL) {
- setColor(Color.hsl(newHSL));
+ setColor(Color.hsl(newHSL).alpha(newHSL.length === 4 ? newHSL[3] : 1));
},
});
const hex = computed({
get() {
- return color.value !== null ? color.value.hex() : null;
+ return getHexa();
},
set(newHex) {
if (newHex === null || newHex === '') {
@@ -248,7 +368,20 @@ export default defineComponent({
},
});
- return { rgb, hsl, hex, color };
+ const alpha = computed({
+ get() {
+ return color.value !== null ? Math.round(color?.value?.alpha() * 100) : 100;
+ },
+ set(newAlpha) {
+ if (newAlpha === null) {
+ return;
+ }
+ const newColor = color.value !== null ? color.value.rgb().array() : [0, 0, 0];
+ setColor(Color(newColor).alpha(newAlpha / 100));
+ },
+ });
+
+ return { rgb, hsl, hex, alpha, color };
function setColor(newColor: Color | null) {
color.value = newColor;
@@ -256,7 +389,7 @@ export default defineComponent({
if (newColor === null) {
unsetColor();
} else {
- emit('input', newColor.hex());
+ emit('input', getHexa());
}
}
}
@@ -314,15 +447,10 @@ export default defineComponent({
.color-data-inputs {
display: grid;
grid-gap: 0px;
- grid-template-columns: repeat(5, 1fr);
width: 100%;
padding: 12px 10px;
}
-.color-data-inputs .color-type {
- grid-column: 1 / span 2;
-}
-
.color-data-inputs .color-data-input {
--border-radius: 0px;
}
@@ -351,14 +479,6 @@ export default defineComponent({
--border-radius: 0px 4px 4px 0px;
}
-.color-data-inputs.stacked {
- grid-template-columns: repeat(3, 1fr);
-}
-
-.color-data-inputs.stacked .color-type {
- grid-column: 1 / span 3;
-}
-
.color-data-inputs.stacked .color-data-input:not(:first-child) :deep(.input) {
margin-top: calc(-2 * var(--border-width));
margin-left: initial;
@@ -379,4 +499,21 @@ export default defineComponent({
.color-data-inputs.stacked .color-data-input:last-child {
--border-radius: 0px 0px 4px 0px;
}
+
+.color-data-alphas {
+ display: grid;
+ grid-gap: 12px;
+ align-items: baseline;
+ width: 100%;
+ height: 45px;
+ padding: 12px 14px;
+}
+
+.color-data-alphas .color-data-alpha {
+ display: grid;
+}
+
+.color-data-alphas .color-data-alpha .slider input {
+ background-color: transparent;
+}
diff --git a/app/src/lang/translations/en-US.yaml b/app/src/lang/translations/en-US.yaml
index cf486ffccd..fc85583123 100644
--- a/app/src/lang/translations/en-US.yaml
+++ b/app/src/lang/translations/en-US.yaml
@@ -1301,6 +1301,7 @@ interfaces:
description: Enter or select a color value
placeholder: Choose a color...
preset_colors: Preset Colors
+ opacity: Opacity
preset_colors_add_label: Add new color...
name_placeholder: Enter color name...
datetime:
diff --git a/app/src/lang/translations/ru-RU.yaml b/app/src/lang/translations/ru-RU.yaml
index 8df27e2346..300eb5d616 100644
--- a/app/src/lang/translations/ru-RU.yaml
+++ b/app/src/lang/translations/ru-RU.yaml
@@ -1257,6 +1257,7 @@ interfaces:
description: Введите или выберите значение цвета
placeholder: Выберите цвет...
preset_colors: Предустановленные цвета
+ opacity: Альфа канал
preset_colors_add_label: Добавить новый цвет...
name_placeholder: Введите название цвета...
datetime:
diff --git a/app/src/styles/_base.scss b/app/src/styles/_base.scss
index af4069be19..296839d7cc 100644
--- a/app/src/styles/_base.scss
+++ b/app/src/styles/_base.scss
@@ -143,6 +143,7 @@ dd a {
@include form-grid;
}
+input[type='number']::-webkit-inner-spin-button,
input[type='search']::-webkit-search-decoration,
input[type='search']::-webkit-search-cancel-button,
input[type='search']::-webkit-search-results-button,