Skip to content

Commit

Permalink
Fix CSS custom property precedence issue and work around Chromium bug (
Browse files Browse the repository at this point in the history
…#6906)

* Workaround Chrome bug by prepending custom property stylesheet

* Switch to Symbol instead of string property name

* Change files

---------

Co-authored-by: Chris Holt <chhol@microsoft.com>
  • Loading branch information
m-akinc and chrisdholt committed Mar 29, 2024
1 parent 2bebec0 commit 0c27d02
Show file tree
Hide file tree
Showing 7 changed files with 58 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "minor",
"comment": "Export Symbol to allow prepending specific stylesheets to adoptedStyleSheets",
"packageName": "@microsoft/fast-element",
"email": "7282195+m-akinc@users.noreply.github.com",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "patch",
"comment": "Fix CSS custom property precedence issue and work around Chromium bug",
"packageName": "@microsoft/fast-foundation",
"email": "7282195+m-akinc@users.noreply.github.com",
"dependentChangeType": "patch"
}
3 changes: 3 additions & 0 deletions packages/web-components/fast-element/docs/api-report.md
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,9 @@ export interface PartialFASTElementDefinition {
readonly template?: ElementViewTemplate;
}

// @public
export const prependToAdoptedStyleSheetsSymbol: unique symbol;

// @public
export class PropertyChangeNotifier implements Notifier {
constructor(source: any);
Expand Down
1 change: 1 addition & 0 deletions packages/web-components/fast-element/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export {
ElementStyleFactory,
ComposableStyles,
StyleTarget,
prependToAdoptedStyleSheetsSymbol,
} from "./styles/element-styles.js";
export { css, cssPartial } from "./styles/css.js";
export { CSSDirective } from "./styles/css-directive.js";
Expand Down
28 changes: 26 additions & 2 deletions packages/web-components/fast-element/src/styles/element-styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,11 +133,33 @@ function reduceBehaviors(
return prev.concat(curr);
}, null as Behavior[] | null);
}

/**
* A Symbol that can be added to a CSSStyleSheet to cause it to be prepended (rather than appended) to adoptedStyleSheets.
* @public
*/
export const prependToAdoptedStyleSheetsSymbol = Symbol("prependToAdoptedStyleSheets");

function separateSheetsToPrepend(
sheets: CSSStyleSheet[]
): {
prepend: CSSStyleSheet[];
append: CSSStyleSheet[];
} {
const prepend: CSSStyleSheet[] = [];
const append: CSSStyleSheet[] = [];
sheets.forEach(x =>
(x[prependToAdoptedStyleSheetsSymbol] ? prepend : append).push(x)
);
return { prepend, append };
}

let addAdoptedStyleSheets = (
target: Required<StyleTarget>,
sheets: CSSStyleSheet[]
): void => {
target.adoptedStyleSheets = [...target.adoptedStyleSheets!, ...sheets];
const { prepend, append } = separateSheetsToPrepend(sheets);
target.adoptedStyleSheets = [...prepend, ...target.adoptedStyleSheets!, ...append];
};
let removeAdoptedStyleSheets = (
target: Required<StyleTarget>,
Expand All @@ -157,7 +179,9 @@ if (DOM.supportsAdoptedStyleSheets) {
(document as any).adoptedStyleSheets.push();
(document as any).adoptedStyleSheets.splice();
addAdoptedStyleSheets = (target, sheets) => {
target.adoptedStyleSheets.push(...sheets);
const { prepend, append } = separateSheetsToPrepend(sheets);
target.adoptedStyleSheets.splice(0, 0, ...prepend);
target.adoptedStyleSheets.push(...append);
};
removeAdoptedStyleSheets = (target, sheets) => {
for (const sheet of sheets) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
FASTElement,
observable,
Observable,
prependToAdoptedStyleSheetsSymbol,
} from "@microsoft/fast-element";

export const defaultElement = document.createElement("div");
Expand Down Expand Up @@ -38,6 +39,7 @@ class ConstructableStyleSheetTarget extends QueuedStyleSheetTarget {
super();

const sheet = new CSSStyleSheet();
sheet[prependToAdoptedStyleSheetsSymbol] = true;
this.target = (sheet.cssRules[sheet.insertRule(":host{}")] as CSSStyleRule).style;
source.$fastController.addStyles(ElementStyles.create([sheet]));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -787,7 +787,18 @@ describe("A DesignToken", () => {
await DOM.nextUpdate();
expect(window.getComputedStyle(target).getPropertyValue("width")).to.equal("12px");
removeElement(parent)
})
});
it("should allow stylesheet to override token's CSS custom property", async () => {
const target = addElement();
const token = DesignToken.create<number>("test");
const styles = css`:host{${token.cssCustomProperty}: 34; width: calc(${token} * 1px);}`
target.$fastController.addStyles(styles);
token.setValueFor(target, 12);

await DOM.nextUpdate();
expect(window.getComputedStyle(target).getPropertyValue("width")).to.equal("34px");
removeElement(target)
});
});

describe("with a default value set", () => {
Expand Down

0 comments on commit 0c27d02

Please sign in to comment.