Skip to content

Commit

Permalink
feat(uui-swatch): ability to overwrite displayed color with a css cus…
Browse files Browse the repository at this point in the history
…tom 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]>
  • Loading branch information
nielslyngsoe and iOvergaard authored Nov 7, 2023
1 parent e03e34c commit 48db9f5
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 82 deletions.
9 changes: 8 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
{
"cSpell.words": ["combobox", "cssprop", "noopener", "noreferrer", "Umbraco"],
"cSpell.words": [
"combobox",
"cssprop",
"deselectable",
"noopener",
"noreferrer",
"Umbraco"
],
"npm.enableRunFromFolder": true
}
113 changes: 38 additions & 75 deletions packages/uui-color-swatch/lib/uui-color-swatch.element.ts
Original file line number Diff line number Diff line change
@@ -1,48 +1,54 @@
import { Colord } from 'colord';
import { defineElement } from '@umbraco-ui/uui-base/lib/registration';
import { property } from 'lit/decorators.js';
import { classMap } from 'lit/directives/class-map.js';
import { css, html, LitElement, nothing } from 'lit';
import { iconCheck } from '@umbraco-ui/uui-icon-registry-essential/lib/svgs';

import { styleMap } from 'lit/directives/style-map.js';

import {
ActiveMixin,
LabelMixin,
SelectableMixin,
} from '@umbraco-ui/uui-base/lib/mixins';

/**
* Color swatch, can have label and be selectable. Depends on colord library and exposes it's utility functions under color property.
* Color swatch, can have label and be selectable.
*
* @element uui-color-swatch
* @cssprop --uui-swatch-size - The size of the swatch.
* @cssprop --uui-swatch-border-width - The width of the border.
* @cssprop --uui-swatch-color - The width of the border.
* @slot label - Default slot for the label.
*/
@defineElement('uui-color-swatch')
export class UUIColorSwatchElement extends LabelMixin(
'label',
SelectableMixin(ActiveMixin(LitElement))
) {
private _value: string | undefined = '';

/**
* 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.
*
* @attr
* Value of the swatch. This will become the color value if color is left undefined, see the property `color` for more details.
*/
@property()
get value(): string {
return this._value ? this._value : this.textContent?.trim() || '';
return this._value ?? '';
}

set value(newValue: string) {
const oldValue = this._value;
this._value = newValue;
this.requestUpdate('value', oldValue);
}
private _value?: string;

/**
* 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.
*/
@property()
get color(): string | undefined {
return this._color;
}
set color(newValue: string) {
const oldValue = this._color;
this._color = newValue;
this.requestUpdate('color', oldValue);
}
private _color?: string;

/**
* Determines if the options is disabled. If true the option can't be selected
Expand All @@ -58,62 +64,24 @@ export class UUIColorSwatchElement extends LabelMixin(
* @attr
* @memberof UUIColorSwatchElement
*/
@property({ type: Boolean, attribute: 'show-label' })
@property({ type: Boolean, attribute: 'show-label', reflect: true })
showLabel = false;
/**
* 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/)
*
* @memberof UUIColorSwatchElement
*/
get color(): Colord | null {
return this._color;
}

set color(_) {
// do nothing, this is just to prevent the color from being set from outside
return;
}
private _color: Colord | null = null;

/**
* Returns true if the color brightness is >= 0.5
*
* @readonly
* @memberof UUIColorSwatchElement
*/
get isLight() {
return this.color?.isLight() ?? false;
}

constructor() {
super();
this.addEventListener('click', this._setAriaAttributes);
}

private _initializeColor() {
this._color = new Colord(this.value ?? '');
if (!this._color.isValid()) {
this.disabled = true;
console.error(
`Invalid color provided to uui-color-swatch: ${this.value}`
);
}
}

private _setAriaAttributes() {
if (this.selectable)
this.setAttribute('aria-checked', this.selected.toString());
}

firstUpdated() {
this._initializeColor();
this._setAriaAttributes();
}

willUpdate(changedProperties: Map<string, any>) {
if (changedProperties.has('value')) {
this._initializeColor();
}
if (changedProperties.has('disabled')) {
if (this.selectable) {
this.selectable = !this.disabled;
Expand All @@ -135,17 +103,16 @@ export class UUIColorSwatchElement extends LabelMixin(
aria-label=${this.label}
aria-disabled="${this.disabled}"
title="${this.label}">
<div
class=${classMap({
'color-swatch': true,
'color-swatch--transparent-bg': true,
'color-swatch--light': this.isLight,
'color-swatch--big': this.showLabel,
})}>
<div class="color-swatch color-swatch--transparent-bg">
<div
class="color-swatch__color"
style=${styleMap({ backgroundColor: this.value })}></div>
<div class="color-swatch__check">${iconCheck}</div>
style="background-color: var(--uui-swatch-color, ${this.color ??
this.value})"></div>
<div
class="color-swatch__check"
style="fill: var(--uui-swatch-color, ${this.color ?? this.value})">
${iconCheck}
</div>
</div>
${this._renderWithLabel()}
</button>
Expand Down Expand Up @@ -222,7 +189,7 @@ export class UUIColorSwatchElement extends LabelMixin(
width: calc(100% + calc(var(--uui-swatch-border-width, 1px) * 2));
height: calc(100% + calc(var(--uui-swatch-border-width, 1px) * 2));
box-sizing: border-box;
border: var(--uui-swatch-border-width, 1px) solid
border: var(--uui-swatch-border-width, 2px) solid
var(--uui-color-selected);
border-radius: calc(
var(--uui-border-radius) + var(--uui-swatch-border-width, 1px)
Expand Down Expand Up @@ -250,7 +217,13 @@ export class UUIColorSwatchElement extends LabelMixin(
justify-content: center;
align-items: center;
}
.color-swatch--transparent-bg {
:host([show-label]) .color-swatch {
width: 120px;
height: 50px;
}
.color-swatch.color-swatch--transparent-bg {
background-image: linear-gradient(
45deg,
var(--uui-palette-grey) 25%,
Expand All @@ -270,7 +243,7 @@ export class UUIColorSwatchElement extends LabelMixin(
box-sizing: border-box;
}
.color-swatch--big .color-swatch__color {
:host([show-label]) .color-swatch__color {
border-radius: 3px 3px 0 0;
}
Expand All @@ -280,16 +253,11 @@ export class UUIColorSwatchElement extends LabelMixin(
width: calc(var(--uui-swatch-size, 25px) / 2);
height: calc(var(--uui-swatch-size, 25px) / 2);
line-height: 0;
transition: fill 120ms, opacity 120ms;
fill: #fff;
filter: invert(1) grayscale(1) contrast(9);
pointer-events: none;
opacity: 0;
}
.color-swatch--light .color-swatch__check {
fill: #000;
}
:host([selected]) .color-swatch__check {
opacity: 1;
}
Expand All @@ -299,11 +267,6 @@ export class UUIColorSwatchElement extends LabelMixin(
font-size: var(--uui-size-4);
}
.color-swatch--big {
width: 120px;
height: 50px;
}
.color-swatch__label {
max-width: 120px;
box-sizing: border-box;
Expand Down
19 changes: 16 additions & 3 deletions packages/uui-color-swatch/lib/uui-color-swatch.story.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ const meta: Meta<UUIColorSwatchElement> = {
},
argTypes: {
value: { control: 'color' },
color: { control: false },
isLight: { control: false },
color: { control: 'color' },
},
parameters: {
readme: {
Expand Down Expand Up @@ -94,9 +93,23 @@ export const WithLabel: Story = {
},
};

export const DifferentColorThanValue: Story = {
args: {
value: 'color1',
color: 'green',
},
parameters: {
docs: {
source: {
code: `<uui-color-swatch value="color1" color="green"></uui-color-slider>`,
},
},
},
};

export const Transparent: Story = {
args: {
value: 'rgba(53, 68, 177, 0.5)',
color: 'rgba(53, 68, 177, 0.5)',
},
parameters: {
docs: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ export class UUIColorSwatchesElement extends LabelMixin('label', LitElement) {
swatch.setAttribute('selectable', 'selectable');
}

if (this.value !== '' && swatch.color?.isEqual(this.value)) {
if (this.value !== '' && swatch.value === this.value) {
swatch.selected = true;
swatch.setAttribute('aria-checked', 'true');
this._selectedElement = swatch;
Expand Down
4 changes: 2 additions & 2 deletions packages/uui-color-swatches/lib/uui-color-swatches.story.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@ const Template: Story = {
return html`<uui-color-swatch
label="${label}"
.showLabel=${args.showLabel}>
${value}
.showLabel=${args.showLabel}
.value=${value}>
</uui-color-swatch>`;
})}
</uui-color-swatches>
Expand Down

0 comments on commit 48db9f5

Please sign in to comment.