From ce899d982a46443d2414e775c9a10e197e364e99 Mon Sep 17 00:00:00 2001 From: Brian Heston <47367562+bheston@users.noreply.github.com> Date: Thu, 4 Dec 2025 15:41:26 -0500 Subject: [PATCH 1/2] Fixed an issue with overlay handling of transparent colors --- packages/adaptive-ui-explorer/src/app.ts | 4 ++++ .../control-pane/control-pane.template.ts | 5 +++++ packages/adaptive-ui-explorer/src/state.ts | 4 ++++ packages/adaptive-ui/docs/api-report.md | 2 ++ packages/adaptive-ui/src/core/color/color.ts | 21 +++++++++++++++++++ .../src/core/color/utilities/conditional.ts | 13 +++++------- .../src/core/color/utilities/opacity.ts | 5 +++++ 7 files changed, 46 insertions(+), 8 deletions(-) diff --git a/packages/adaptive-ui-explorer/src/app.ts b/packages/adaptive-ui-explorer/src/app.ts index ff4e9995..dcab04f1 100644 --- a/packages/adaptive-ui-explorer/src/app.ts +++ b/packages/adaptive-ui-explorer/src/app.ts @@ -14,6 +14,7 @@ import { layerFillFixedMinus2, layerFillFixedMinus3, layerFillFixedPlus1, + neutralAsOverlay, neutralBaseColor, neutralPalette, wcagContrastLevel @@ -243,6 +244,9 @@ export class App extends FASTElement { app.highlightPalette = highlightPalette.getValueFor(app.canvas); break; + case "neutralAsOverlay": + neutralAsOverlay.setValueFor(app.canvas, source.neutralAsOverlay); + break; case "showOnlyLayerBackgrounds": app.updateBackgrounds(); break; diff --git a/packages/adaptive-ui-explorer/src/components/control-pane/control-pane.template.ts b/packages/adaptive-ui-explorer/src/components/control-pane/control-pane.template.ts index 98df9e07..80fa4ed6 100644 --- a/packages/adaptive-ui-explorer/src/components/control-pane/control-pane.template.ts +++ b/packages/adaptive-ui-explorer/src/components/control-pane/control-pane.template.ts @@ -40,6 +40,11 @@ export function controlPaneTemplate(): ElementViewTemplat /> + x.state.neutralAsOverlay)} + >Neutral as overlay + x.state.showOnlyLayerBackgrounds)} diff --git a/packages/adaptive-ui-explorer/src/state.ts b/packages/adaptive-ui-explorer/src/state.ts index 06ccb128..77c01a47 100644 --- a/packages/adaptive-ui-explorer/src/state.ts +++ b/packages/adaptive-ui-explorer/src/state.ts @@ -8,6 +8,7 @@ export const State = Context.create("State"); export interface State { componentType: ComponentType; neutralColor: Color; + neutralAsOverlay: boolean; accentColor: Color; highlightColor: Color; showOnlyLayerBackgrounds: boolean; @@ -31,6 +32,9 @@ export class DefaultState implements State { @observable public neutralColor: Color = PLACEHOLDER_COLOR; + @observable + public neutralAsOverlay: boolean = false; + @observable public accentColor: Color = PLACEHOLDER_COLOR; diff --git a/packages/adaptive-ui/docs/api-report.md b/packages/adaptive-ui/docs/api-report.md index f822a179..9b532dbc 100644 --- a/packages/adaptive-ui/docs/api-report.md +++ b/packages/adaptive-ui/docs/api-report.md @@ -75,10 +75,12 @@ export class Color extends PaintBase { }): Color; static fromRgb(r: number, g: number, b: number, alpha?: number): Color; protected readonly _intendedColor?: Color; + static isTransparent(color: Color_2): boolean; static parse(color: string): Color | undefined; // @deprecated toColorString: () => string; toString(): string; + static transparent: Color; static unsafeOpacity(color: Color, alpha: number): Color; } diff --git a/packages/adaptive-ui/src/core/color/color.ts b/packages/adaptive-ui/src/core/color/color.ts index 4bd92a4d..294d910a 100644 --- a/packages/adaptive-ui/src/core/color/color.ts +++ b/packages/adaptive-ui/src/core/color/color.ts @@ -1,5 +1,6 @@ import { cssDirective } from "@microsoft/fast-element"; import { type Color as CuloriColor, formatHex, formatRgb, modeLrgb, modeRgb, parse, type Rgb, useMode, wcagLuminance } from "culori/fn"; +import { parseTransparent } from "culori"; import { PaintBase } from "./paint.js"; import { calculateOverlayColor } from "./utilities/opacity.js"; @@ -7,6 +8,8 @@ useMode(modeRgb); // For luminance useMode(modeLrgb); +const _transparent: Rgb = parseTransparent("transparent"); + /** * Represents a color. * @@ -44,6 +47,9 @@ export class Color extends PaintBase { * @returns The color value in string format */ public toString(): string { + if (Color.isTransparent(this.color)) { + return "transparent"; + } return this.color.alpha !== undefined && this.color.alpha < 1 ? formatRgb(this.color) : formatHex(this.color); } @@ -99,6 +105,21 @@ export class Color extends PaintBase { } } + /** + * A Color representing the full transparent. + */ + public static transparent: Color = new Color(_transparent); + + /** + * Checks if a color is transparent. + * + * @param color - The color to check. + * @returns True if the color is transparent, false otherwise. + */ + public static isTransparent(color: CuloriColor): boolean { + return color.alpha === 0; + } + /** * Creates a new Color as an overlay representation of the `intendedColor` over `reference`. * diff --git a/packages/adaptive-ui/src/core/color/utilities/conditional.ts b/packages/adaptive-ui/src/core/color/utilities/conditional.ts index 9902292c..14eeb4ca 100644 --- a/packages/adaptive-ui/src/core/color/utilities/conditional.ts +++ b/packages/adaptive-ui/src/core/color/utilities/conditional.ts @@ -1,8 +1,5 @@ import { Color } from "../color.js"; import { InteractiveColorSet } from "../recipe.js"; -import { _white } from "./color-constants.js"; - -const _transparentWhite = Color.unsafeOpacity(_white, 0); /** * Return an interactive set of the provided tokens or a no-op "transparent" set of tokens. @@ -20,10 +17,10 @@ export function conditionalSwatchSet( } return { - rest: _transparentWhite, - hover: _transparentWhite, - active: _transparentWhite, - focus: _transparentWhite, - disabled: _transparentWhite, + rest: Color.transparent, + hover: Color.transparent, + active: Color.transparent, + focus: Color.transparent, + disabled: Color.transparent, }; } diff --git a/packages/adaptive-ui/src/core/color/utilities/opacity.ts b/packages/adaptive-ui/src/core/color/utilities/opacity.ts index 1124ff40..2add279e 100644 --- a/packages/adaptive-ui/src/core/color/utilities/opacity.ts +++ b/packages/adaptive-ui/src/core/color/utilities/opacity.ts @@ -34,6 +34,11 @@ function calcRgbOverlay(rgbMatch: Rgb, rgbBackground: Rgb, rgbOverlay: Rgb): num */ export function calculateOverlayColor(match: CuloriColor, background: CuloriColor): Rgb { const rgbMatch = rgb(match); + + if (Color.isTransparent(rgbMatch) || Color.isTransparent(background)) { + return rgbMatch; + } + const rgbBackground = rgb(background); let overlay = rgbBlack; let alpha = calcRgbOverlay(rgbMatch, rgbBackground, overlay); From d86dd55f95a0f3a9360c2dba8bd5edf657df2497 Mon Sep 17 00:00:00 2001 From: Brian Heston <47367562+bheston@users.noreply.github.com> Date: Thu, 4 Dec 2025 15:44:43 -0500 Subject: [PATCH 2/2] Changeset --- .changeset/neat-plants-spend.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/neat-plants-spend.md diff --git a/.changeset/neat-plants-spend.md b/.changeset/neat-plants-spend.md new file mode 100644 index 00000000..f9eae48f --- /dev/null +++ b/.changeset/neat-plants-spend.md @@ -0,0 +1,5 @@ +--- +"@adaptive-web/adaptive-ui": patch +--- + +Fixed an issue with overlay handling of transparent colors