diff --git a/.vscode/settings.json b/.vscode/settings.json index 7d5502898..c02b365ee 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,4 +1,11 @@ { - "cSpell.words": ["combobox", "cssprop", "noopener", "noreferrer", "Umbraco"], + "cSpell.words": [ + "combobox", + "cssprop", + "deselectable", + "noopener", + "noreferrer", + "Umbraco" + ], "npm.enableRunFromFolder": true } diff --git a/packages/uui-color-swatch/lib/uui-color-swatch.element.ts b/packages/uui-color-swatch/lib/uui-color-swatch.element.ts index d5b728a23..aaa513631 100644 --- a/packages/uui-color-swatch/lib/uui-color-swatch.element.ts +++ b/packages/uui-color-swatch/lib/uui-color-swatch.element.ts @@ -1,12 +1,7 @@ -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, @@ -14,11 +9,12 @@ import { } 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') @@ -26,23 +22,33 @@ 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 @@ -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) { - if (changedProperties.has('value')) { - this._initializeColor(); - } if (changedProperties.has('disabled')) { if (this.selectable) { this.selectable = !this.disabled; @@ -135,17 +103,16 @@ export class UUIColorSwatchElement extends LabelMixin( aria-label=${this.label} aria-disabled="${this.disabled}" title="${this.label}"> -
+
-
${iconCheck}
+ style="background-color: var(--uui-swatch-color, ${this.color ?? + this.value})">
+
+ ${iconCheck} +
${this._renderWithLabel()} @@ -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) @@ -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%, @@ -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; } @@ -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; } @@ -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; diff --git a/packages/uui-color-swatch/lib/uui-color-swatch.story.ts b/packages/uui-color-swatch/lib/uui-color-swatch.story.ts index 8aace23fd..02be2848d 100644 --- a/packages/uui-color-swatch/lib/uui-color-swatch.story.ts +++ b/packages/uui-color-swatch/lib/uui-color-swatch.story.ts @@ -13,8 +13,7 @@ const meta: Meta = { }, argTypes: { value: { control: 'color' }, - color: { control: false }, - isLight: { control: false }, + color: { control: 'color' }, }, parameters: { readme: { @@ -94,9 +93,23 @@ export const WithLabel: Story = { }, }; +export const DifferentColorThanValue: Story = { + args: { + value: 'color1', + color: 'green', + }, + parameters: { + docs: { + source: { + code: ``, + }, + }, + }, +}; + export const Transparent: Story = { args: { - value: 'rgba(53, 68, 177, 0.5)', + color: 'rgba(53, 68, 177, 0.5)', }, parameters: { docs: { diff --git a/packages/uui-color-swatches/lib/uui-color-swatches.element.ts b/packages/uui-color-swatches/lib/uui-color-swatches.element.ts index 50b9ba20e..fbb7b16c0 100644 --- a/packages/uui-color-swatches/lib/uui-color-swatches.element.ts +++ b/packages/uui-color-swatches/lib/uui-color-swatches.element.ts @@ -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; diff --git a/packages/uui-color-swatches/lib/uui-color-swatches.story.ts b/packages/uui-color-swatches/lib/uui-color-swatches.story.ts index 504d78405..713b7ef0d 100644 --- a/packages/uui-color-swatches/lib/uui-color-swatches.story.ts +++ b/packages/uui-color-swatches/lib/uui-color-swatches.story.ts @@ -84,8 +84,8 @@ const Template: Story = { return html` - ${value} + .showLabel=${args.showLabel} + .value=${value}> `; })}