Skip to content

Commit 48db9f5

Browse files
feat(uui-swatch): ability to overwrite displayed color with a css custom prop (#649)
* ability to overwrite displayed color with a css custom prop * use color prop instead * refactor, get rid of colord and other things * correct css filter implementation --------- Co-authored-by: Jacob Overgaard <[email protected]>
1 parent e03e34c commit 48db9f5

File tree

5 files changed

+65
-82
lines changed

5 files changed

+65
-82
lines changed

.vscode/settings.json

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
11
{
2-
"cSpell.words": ["combobox", "cssprop", "noopener", "noreferrer", "Umbraco"],
2+
"cSpell.words": [
3+
"combobox",
4+
"cssprop",
5+
"deselectable",
6+
"noopener",
7+
"noreferrer",
8+
"Umbraco"
9+
],
310
"npm.enableRunFromFolder": true
411
}

packages/uui-color-swatch/lib/uui-color-swatch.element.ts

Lines changed: 38 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,54 @@
1-
import { Colord } from 'colord';
21
import { defineElement } from '@umbraco-ui/uui-base/lib/registration';
32
import { property } from 'lit/decorators.js';
4-
import { classMap } from 'lit/directives/class-map.js';
53
import { css, html, LitElement, nothing } from 'lit';
64
import { iconCheck } from '@umbraco-ui/uui-icon-registry-essential/lib/svgs';
7-
8-
import { styleMap } from 'lit/directives/style-map.js';
9-
105
import {
116
ActiveMixin,
127
LabelMixin,
138
SelectableMixin,
149
} from '@umbraco-ui/uui-base/lib/mixins';
1510

1611
/**
17-
* Color swatch, can have label and be selectable. Depends on colord library and exposes it's utility functions under color property.
12+
* Color swatch, can have label and be selectable.
1813
*
1914
* @element uui-color-swatch
2015
* @cssprop --uui-swatch-size - The size of the swatch.
2116
* @cssprop --uui-swatch-border-width - The width of the border.
17+
* @cssprop --uui-swatch-color - The width of the border.
2218
* @slot label - Default slot for the label.
2319
*/
2420
@defineElement('uui-color-swatch')
2521
export class UUIColorSwatchElement extends LabelMixin(
2622
'label',
2723
SelectableMixin(ActiveMixin(LitElement))
2824
) {
29-
private _value: string | undefined = '';
30-
3125
/**
32-
* Value of the swatch. Should be a valid hex, hexa, rgb, rgba, hsl or hsla string. Should fulfill this [css spec](https://www.w3.org/TR/css-color-4/#color-type). If not provided element will look at its text content.
33-
*
34-
* @attr
26+
* Value of the swatch. This will become the color value if color is left undefined, see the property `color` for more details.
3527
*/
3628
@property()
3729
get value(): string {
38-
return this._value ? this._value : this.textContent?.trim() || '';
30+
return this._value ?? '';
3931
}
40-
4132
set value(newValue: string) {
4233
const oldValue = this._value;
4334
this._value = newValue;
4435
this.requestUpdate('value', oldValue);
4536
}
37+
private _value?: string;
38+
39+
/**
40+
* Color of the swatch. Should be a valid hex, hexa, rgb, rgba, hsl or hsla string. Should fulfill this [css spec](https://www.w3.org/TR/css-color-4/#color-type). If not provided element will look at its text content.
41+
*/
42+
@property()
43+
get color(): string | undefined {
44+
return this._color;
45+
}
46+
set color(newValue: string) {
47+
const oldValue = this._color;
48+
this._color = newValue;
49+
this.requestUpdate('color', oldValue);
50+
}
51+
private _color?: string;
4652

4753
/**
4854
* Determines if the options is disabled. If true the option can't be selected
@@ -58,62 +64,24 @@ export class UUIColorSwatchElement extends LabelMixin(
5864
* @attr
5965
* @memberof UUIColorSwatchElement
6066
*/
61-
@property({ type: Boolean, attribute: 'show-label' })
67+
@property({ type: Boolean, attribute: 'show-label', reflect: true })
6268
showLabel = false;
63-
/**
64-
* Colord object instance based on the value provided to the element. If the value is not a valid color, it falls back to black (like Amy Winehouse). For more information about Colord, see [Colord](https://omgovich.github.io/colord/)
65-
*
66-
* @memberof UUIColorSwatchElement
67-
*/
68-
get color(): Colord | null {
69-
return this._color;
70-
}
71-
72-
set color(_) {
73-
// do nothing, this is just to prevent the color from being set from outside
74-
return;
75-
}
76-
private _color: Colord | null = null;
77-
78-
/**
79-
* Returns true if the color brightness is >= 0.5
80-
*
81-
* @readonly
82-
* @memberof UUIColorSwatchElement
83-
*/
84-
get isLight() {
85-
return this.color?.isLight() ?? false;
86-
}
8769

8870
constructor() {
8971
super();
9072
this.addEventListener('click', this._setAriaAttributes);
9173
}
9274

93-
private _initializeColor() {
94-
this._color = new Colord(this.value ?? '');
95-
if (!this._color.isValid()) {
96-
this.disabled = true;
97-
console.error(
98-
`Invalid color provided to uui-color-swatch: ${this.value}`
99-
);
100-
}
101-
}
102-
10375
private _setAriaAttributes() {
10476
if (this.selectable)
10577
this.setAttribute('aria-checked', this.selected.toString());
10678
}
10779

10880
firstUpdated() {
109-
this._initializeColor();
11081
this._setAriaAttributes();
11182
}
11283

11384
willUpdate(changedProperties: Map<string, any>) {
114-
if (changedProperties.has('value')) {
115-
this._initializeColor();
116-
}
11785
if (changedProperties.has('disabled')) {
11886
if (this.selectable) {
11987
this.selectable = !this.disabled;
@@ -135,17 +103,16 @@ export class UUIColorSwatchElement extends LabelMixin(
135103
aria-label=${this.label}
136104
aria-disabled="${this.disabled}"
137105
title="${this.label}">
138-
<div
139-
class=${classMap({
140-
'color-swatch': true,
141-
'color-swatch--transparent-bg': true,
142-
'color-swatch--light': this.isLight,
143-
'color-swatch--big': this.showLabel,
144-
})}>
106+
<div class="color-swatch color-swatch--transparent-bg">
145107
<div
146108
class="color-swatch__color"
147-
style=${styleMap({ backgroundColor: this.value })}></div>
148-
<div class="color-swatch__check">${iconCheck}</div>
109+
style="background-color: var(--uui-swatch-color, ${this.color ??
110+
this.value})"></div>
111+
<div
112+
class="color-swatch__check"
113+
style="fill: var(--uui-swatch-color, ${this.color ?? this.value})">
114+
${iconCheck}
115+
</div>
149116
</div>
150117
${this._renderWithLabel()}
151118
</button>
@@ -222,7 +189,7 @@ export class UUIColorSwatchElement extends LabelMixin(
222189
width: calc(100% + calc(var(--uui-swatch-border-width, 1px) * 2));
223190
height: calc(100% + calc(var(--uui-swatch-border-width, 1px) * 2));
224191
box-sizing: border-box;
225-
border: var(--uui-swatch-border-width, 1px) solid
192+
border: var(--uui-swatch-border-width, 2px) solid
226193
var(--uui-color-selected);
227194
border-radius: calc(
228195
var(--uui-border-radius) + var(--uui-swatch-border-width, 1px)
@@ -250,7 +217,13 @@ export class UUIColorSwatchElement extends LabelMixin(
250217
justify-content: center;
251218
align-items: center;
252219
}
253-
.color-swatch--transparent-bg {
220+
221+
:host([show-label]) .color-swatch {
222+
width: 120px;
223+
height: 50px;
224+
}
225+
226+
.color-swatch.color-swatch--transparent-bg {
254227
background-image: linear-gradient(
255228
45deg,
256229
var(--uui-palette-grey) 25%,
@@ -270,7 +243,7 @@ export class UUIColorSwatchElement extends LabelMixin(
270243
box-sizing: border-box;
271244
}
272245
273-
.color-swatch--big .color-swatch__color {
246+
:host([show-label]) .color-swatch__color {
274247
border-radius: 3px 3px 0 0;
275248
}
276249
@@ -280,16 +253,11 @@ export class UUIColorSwatchElement extends LabelMixin(
280253
width: calc(var(--uui-swatch-size, 25px) / 2);
281254
height: calc(var(--uui-swatch-size, 25px) / 2);
282255
line-height: 0;
283-
transition: fill 120ms, opacity 120ms;
284-
fill: #fff;
256+
filter: invert(1) grayscale(1) contrast(9);
285257
pointer-events: none;
286258
opacity: 0;
287259
}
288260
289-
.color-swatch--light .color-swatch__check {
290-
fill: #000;
291-
}
292-
293261
:host([selected]) .color-swatch__check {
294262
opacity: 1;
295263
}
@@ -299,11 +267,6 @@ export class UUIColorSwatchElement extends LabelMixin(
299267
font-size: var(--uui-size-4);
300268
}
301269
302-
.color-swatch--big {
303-
width: 120px;
304-
height: 50px;
305-
}
306-
307270
.color-swatch__label {
308271
max-width: 120px;
309272
box-sizing: border-box;

packages/uui-color-swatch/lib/uui-color-swatch.story.ts

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@ const meta: Meta<UUIColorSwatchElement> = {
1313
},
1414
argTypes: {
1515
value: { control: 'color' },
16-
color: { control: false },
17-
isLight: { control: false },
16+
color: { control: 'color' },
1817
},
1918
parameters: {
2019
readme: {
@@ -94,9 +93,23 @@ export const WithLabel: Story = {
9493
},
9594
};
9695

96+
export const DifferentColorThanValue: Story = {
97+
args: {
98+
value: 'color1',
99+
color: 'green',
100+
},
101+
parameters: {
102+
docs: {
103+
source: {
104+
code: `<uui-color-swatch value="color1" color="green"></uui-color-slider>`,
105+
},
106+
},
107+
},
108+
};
109+
97110
export const Transparent: Story = {
98111
args: {
99-
value: 'rgba(53, 68, 177, 0.5)',
112+
color: 'rgba(53, 68, 177, 0.5)',
100113
},
101114
parameters: {
102115
docs: {

packages/uui-color-swatches/lib/uui-color-swatches.element.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ export class UUIColorSwatchesElement extends LabelMixin('label', LitElement) {
8686
swatch.setAttribute('selectable', 'selectable');
8787
}
8888

89-
if (this.value !== '' && swatch.color?.isEqual(this.value)) {
89+
if (this.value !== '' && swatch.value === this.value) {
9090
swatch.selected = true;
9191
swatch.setAttribute('aria-checked', 'true');
9292
this._selectedElement = swatch;

packages/uui-color-swatches/lib/uui-color-swatches.story.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,8 @@ const Template: Story = {
8484
8585
return html`<uui-color-swatch
8686
label="${label}"
87-
.showLabel=${args.showLabel}>
88-
${value}
87+
.showLabel=${args.showLabel}
88+
.value=${value}>
8989
</uui-color-swatch>`;
9090
})}
9191
</uui-color-swatches>

0 commit comments

Comments
 (0)