Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 50 additions & 4 deletions packages/uui-color-swatch/lib/uui-color-swatch.element.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { defineElement } from '@umbraco-ui/uui-base/lib/registration';
import { property } from 'lit/decorators.js';
import { property, state } from 'lit/decorators.js';
import { css, html, LitElement, nothing } from 'lit';
import { ref } from 'lit/directives/ref.js';
import { ifDefined } from 'lit/directives/if-defined.js';
import { iconCheck } from '@umbraco-ui/uui-icon-registry-essential/lib/svgs';
import {
ActiveMixin,
Expand All @@ -23,6 +24,9 @@
'label',
SelectableMixin(ActiveMixin(LitElement)),
) {
@state()
private _contrast: 'dark' | 'light' | undefined = undefined;

/**
* Value of the swatch. This will become the color value if color is left undefined, see the property `color` for more details.
*/
Expand Down Expand Up @@ -90,6 +94,11 @@

firstUpdated() {
this._setAriaAttributes();

const color = this.color ?? this.value;
if (color.startsWith('#')) {
this._contrast = this.#contrast(color) === 'light' ? 'light' : 'dark';
}
}

willUpdate(changedProperties: Map<string, any>) {
Expand Down Expand Up @@ -118,6 +127,27 @@
this.selectableTarget = button || this;
}

#contrast(hex: string): string {
const rgb = this.#hexToRgb(hex);
const o = Math.round((rgb[0] * 299 + rgb[1] * 587 + rgb[2] * 114) / 1000);
Copy link

Copilot AI Oct 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The magic numbers 299, 587, 114, and 1000 should be extracted as named constants to explain they represent the RGB to grayscale conversion coefficients and divisor.

Copilot uses AI. Check for mistakes.

return o <= 180 ? 'dark' : 'light';
Copy link

Copilot AI Oct 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The magic number 180 should be extracted as a named constant like 'LUMINANCE_THRESHOLD' to clarify its purpose as the brightness cutoff for determining contrast.

Copilot uses AI. Check for mistakes.
}

#hexToRgb(hex: string): number[] {
hex = hex.startsWith('#') ? hex.slice(1) : hex;
if (hex.length === 3) {
hex = Array.from(hex).reduce((str, x) => str + x + x, ''); // 123 -> 112233
}

const bigint = parseInt(hex, 16);
const r = (bigint >> 16) & 255;
const g = (bigint >> 8) & 255;
const b = bigint & 255;

return [r, g, b];
}

render() {
return html`
<button
Expand All @@ -126,7 +156,12 @@
aria-label=${this.label}
?disabled="${this.disabled}"
title="${this.label}">
<div class="color-swatch color-swatch--transparent-bg">
<div
class="color-swatch color-swatch--transparent-bg ${ifDefined(
this._contrast,
)
? `color-swatch--${this._contrast}`
: ''}">
<div
class="color-swatch__color"
style="background: var(--uui-swatch-color, ${this.color ??
Expand Down Expand Up @@ -251,8 +286,11 @@
}
.color-swatch.color-swatch--transparent-bg {
background-image:
linear-gradient(45deg, var(--uui-palette-grey) 25%, transparent 25%),
background-image: linear-gradient(

Check failure on line 289 in packages/uui-color-swatch/lib/uui-color-swatch.element.ts

View workflow job for this annotation

GitHub Actions / test

Replace `·linear-gradient(⏎············45deg,⏎············var(--uui-palette-grey)·25%,⏎············transparent·25%⏎··········` with `⏎··········linear-gradient(45deg,·var(--uui-palette-grey)·25%,·transparent·25%`
45deg,
var(--uui-palette-grey) 25%,
transparent 25%
),
linear-gradient(45deg, transparent 75%, var(--uui-palette-grey) 75%),
linear-gradient(45deg, transparent 75%, var(--uui-palette-grey) 75%),
linear-gradient(45deg, var(--uui-palette-grey) 25%, transparent 25%);
Expand Down Expand Up @@ -286,6 +324,14 @@
opacity: 0;
}
.color-swatch.color-swatch--light .color-swatch__check {
filter: invert(0) brightness(0);
}
.color-swatch.color-swatch--dark .color-swatch__check {
filter: invert(1) brightness(10);
}
:host([selected]) .color-swatch__check {
opacity: 1;
}
Expand Down
12 changes: 9 additions & 3 deletions packages/uui-color-swatches/lib/uui-color-swatches.story.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,15 @@ import { spread } from '../../../storyhelpers';
import { repeat } from 'lit/directives/repeat.js';

const swatches = [
{ label: 'Blood Orange', value: '#d0021b' },
{ label: 'Avocado', value: '#417505' },
{ label: 'Tufts Blue', value: '#4a90e2' },
{ label: 'Black', value: '#060606' },
{ label: 'Sunglow', value: '#fad634' },
{ label: 'Spanish Pink', value: '#f5c1bc' },
{ label: 'Violet Blue', value: '#3544b1' },
{ label: 'Malibu', value: '#3879ff' },
{ label: 'Maroon Flush', value: '#d42054' },
{ label: 'Jungle Green', value: '#2bc37c' },
{ label: 'Chamoisee', value: '#9d8057' },
{ label: 'Dusty Grey', value: '#9b9b9b' },
];

const gradients = [
Expand Down
Loading