From a7df495d76b3a81c402fd445467b8da49f045d7e Mon Sep 17 00:00:00 2001 From: Brian Heston <47367562+bheston@users.noreply.github.com> Date: Mon, 1 May 2023 21:03:34 -0700 Subject: [PATCH 1/2] Initial support for style module media query variations --- package-lock.json | 2 + packages/adaptive-ui/package.json | 1 + .../adaptive-ui/src/design-tokens/index.ts | 1 + .../design-tokens/modules.forced-colors.ts | 60 +++++++++++++++++++ .../adaptive-ui/src/design-tokens/modules.ts | 11 ++++ packages/adaptive-ui/src/modules/css.ts | 9 +++ .../src/modules/element-styles-renderer.ts | 13 +++- packages/adaptive-ui/src/modules/styles.ts | 26 ++++++++ 8 files changed, 121 insertions(+), 2 deletions(-) create mode 100644 packages/adaptive-ui/src/design-tokens/modules.forced-colors.ts diff --git a/package-lock.json b/package-lock.json index 588031e1..050327fa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -31812,6 +31812,7 @@ "dependencies": { "@microsoft/fast-element": "2.0.0-beta.26", "@microsoft/fast-foundation": "3.0.0-alpha.31", + "@microsoft/fast-web-utilities": "^6.0.0", "culori": "^3.2.0" }, "devDependencies": { @@ -32507,6 +32508,7 @@ "@microsoft/api-extractor": "^7.34.4", "@microsoft/fast-element": "2.0.0-beta.26", "@microsoft/fast-foundation": "3.0.0-alpha.31", + "@microsoft/fast-web-utilities": "^6.0.0", "@types/chai": "^4.3.4", "@types/culori": "^2.0.0", "@types/mocha": "^10.0.1", diff --git a/packages/adaptive-ui/package.json b/packages/adaptive-ui/package.json index 470d932b..8770ec90 100644 --- a/packages/adaptive-ui/package.json +++ b/packages/adaptive-ui/package.json @@ -36,6 +36,7 @@ "dependencies": { "@microsoft/fast-element": "2.0.0-beta.26", "@microsoft/fast-foundation": "3.0.0-alpha.31", + "@microsoft/fast-web-utilities": "^6.0.0", "culori": "^3.2.0" }, "devDependencies": { diff --git a/packages/adaptive-ui/src/design-tokens/index.ts b/packages/adaptive-ui/src/design-tokens/index.ts index c718847d..fbd64244 100644 --- a/packages/adaptive-ui/src/design-tokens/index.ts +++ b/packages/adaptive-ui/src/design-tokens/index.ts @@ -4,5 +4,6 @@ export * from "./density.js"; export * from "./elevation.js"; export * from "./layer.js"; export * from "./modules.js"; +export * from "./modules.forced-colors.js"; export * from "./palette.js"; export * from "./type.js"; \ No newline at end of file diff --git a/packages/adaptive-ui/src/design-tokens/modules.forced-colors.ts b/packages/adaptive-ui/src/design-tokens/modules.forced-colors.ts new file mode 100644 index 00000000..78f2e824 --- /dev/null +++ b/packages/adaptive-ui/src/design-tokens/modules.forced-colors.ts @@ -0,0 +1,60 @@ +import { SystemColors } from "@microsoft/fast-web-utilities"; +import { InteractiveSet } from "../types.js"; +import { Styles } from "../modules/styles.js"; + +/** + * Convenience function for styles that share rest/focus and hover/active states. + * + * @param restAndFocus - The value to use for rest and focus states. + * @param hoverAndActive - The value to use for hover and active states. + * @returns A full interactive color set. + */ +function set( + restAndFocus: string, + hoverAndActive: string, +): InteractiveSet { + return { + rest: restAndFocus, + hover: hoverAndActive, + active: hoverAndActive, + focus: restAndFocus, + disabled: SystemColors.GrayText, + }; +} + +/** + * @public + */ +export const forcedColorsButtonStyles: Styles = Styles.fromProperties({ + backgroundFill: { + ...set(SystemColors.ButtonFace, SystemColors.HighlightText), + }, + foregroundFill: { + ...set(SystemColors.ButtonText, SystemColors.Highlight), + }, + borderFill: { + ...set(SystemColors.ButtonText, SystemColors.Highlight), + }, +}); + +/** + * @public + */ +export const forcedColorsHighlightStyles: Styles = Styles.fromProperties({ + backgroundFill: { + ...set(SystemColors.Highlight, SystemColors.ButtonFace), + }, + foregroundFill: { + ...set(SystemColors.HighlightText, SystemColors.ButtonText), + }, + borderFill: { + ...set(SystemColors.Highlight, SystemColors.ButtonText), + }, +}); + +/** + * @public + */ +export const forcedColorsTextStyles: Styles = Styles.fromProperties({ + foregroundFill: SystemColors.CanvasText, +}); diff --git a/packages/adaptive-ui/src/design-tokens/modules.ts b/packages/adaptive-ui/src/design-tokens/modules.ts index 39a76350..404c14f9 100644 --- a/packages/adaptive-ui/src/design-tokens/modules.ts +++ b/packages/adaptive-ui/src/design-tokens/modules.ts @@ -1,3 +1,4 @@ +import { MediaQuery } from "../modules/css.js"; import { BorderFill, BorderStyle, BorderThickness, CornerRadius, Fill, Padding, Styles, StyleValue } from "../modules/styles.js"; import { cornerRadiusControl, cornerRadiusLayer, focusStrokeThickness, strokeThickness } from "./appearance.js"; import { @@ -101,6 +102,7 @@ import { typeRampPlus6FontVariations, typeRampPlus6LineHeight, } from "./type.js"; +import { forcedColorsButtonStyles, forcedColorsHighlightStyles, forcedColorsTextStyles } from "./modules.forced-colors.js"; /** * Style module for the shape of a control. @@ -1330,6 +1332,9 @@ export const selectableSelectedStyles: Styles = Styles.compose( ], undefined, "styles.selectable-control-selected", +).withMediaQuery( + MediaQuery.ForcedColors, + forcedColorsHighlightStyles, ); /** @@ -1343,6 +1348,9 @@ export const selectableUnselectedStyles: Styles = Styles.compose( ], undefined, "styles.selectable-control-unselected", +).withMediaQuery( + MediaQuery.ForcedColors, + forcedColorsButtonStyles, ); /** @@ -1369,6 +1377,9 @@ export const plainTextStyles: Styles = Styles.compose( ], undefined, "styles.text-plain", +).withMediaQuery( + MediaQuery.ForcedColors, + forcedColorsTextStyles, ); /** diff --git a/packages/adaptive-ui/src/modules/css.ts b/packages/adaptive-ui/src/modules/css.ts index a23296e3..0a0460a8 100644 --- a/packages/adaptive-ui/src/modules/css.ts +++ b/packages/adaptive-ui/src/modules/css.ts @@ -1,5 +1,14 @@ import { StyleProperty } from "./types.js"; +/** + * Convenience media queries for {@link Styles} variations. + */ +export const MediaQuery = { + ForcedColors: "(forced-colors)", + ColorsDark: "(prefers-color-scheme: dark)", + ColorsLight: "(prefers-color-scheme: light)", +} as const; + /** * Converts a {@link StyleProperty} to a css property name. * diff --git a/packages/adaptive-ui/src/modules/element-styles-renderer.ts b/packages/adaptive-ui/src/modules/element-styles-renderer.ts index 306bd22f..a1eaf078 100644 --- a/packages/adaptive-ui/src/modules/element-styles-renderer.ts +++ b/packages/adaptive-ui/src/modules/element-styles-renderer.ts @@ -1,6 +1,6 @@ import { ComposableStyles, css, HostBehavior } from "@microsoft/fast-element"; import { type CSSDirective, ElementStyles } from "@microsoft/fast-element"; -import { CSSDesignToken } from "@microsoft/fast-foundation"; +import { CSSDesignToken, MatchMediaStyleSheetBehavior } from "@microsoft/fast-foundation"; import { Interactivity, type InteractivityDefinition, type StyleModuleTarget, StyleProperty } from "../modules/types.js"; import type { InteractiveSet } from "../types.js"; import { makeSelector } from "./selector.js"; @@ -184,8 +184,17 @@ export class ElementStylesRenderer { */ public static renderStyleRules(baseStyles: ComposableStyles[] = [], styleRules: StyleRules, anatomy?: ComponentAnatomy) { for (const rule of styleRules) { + const target = rule.target || {}; const styles = Styles.fromDeclaration(rule); - const renderedStyles = new ElementStylesRenderer(styles).render(rule.target || {}, anatomy?.interactivity); + const renderedStyles = new ElementStylesRenderer(styles).render(target, anatomy?.interactivity); + + styles.getMediaQueryStyles()?.forEach((queryStyles, query) => { + const queryRenderedStyles = new ElementStylesRenderer(queryStyles).render(target, anatomy?.interactivity); + renderedStyles.withBehaviors( + MatchMediaStyleSheetBehavior.with( + window.matchMedia(query))(queryRenderedStyles)) + }); + baseStyles.push(renderedStyles); } diff --git a/packages/adaptive-ui/src/modules/styles.ts b/packages/adaptive-ui/src/modules/styles.ts index 8f35de09..0f767715 100644 --- a/packages/adaptive-ui/src/modules/styles.ts +++ b/packages/adaptive-ui/src/modules/styles.ts @@ -203,6 +203,8 @@ export class Styles { private _properties?: StylePropertiesMap; // Effective properties from composed styles and additional properties private _composedProperties?: StylePropertiesMap; + // Style overrides for a media query + private _mediaQueryVariations: Map; private constructor( /** @@ -266,6 +268,30 @@ export class Styles { this.createEffectiveProperties(); } + /** + * Adds a style variation for a media query like `forced-colors`. + * + * @param query - The media query, see {@link MediaQuery}. + * @param styles - The styles to apply for the provided media query + * @returns The `Styles` definition with media query variation. + */ + public withMediaQuery(query: string, styles: Styles): this { + if (!this._mediaQueryVariations) { + this._mediaQueryVariations = new Map(); + } + this._mediaQueryVariations.set(query, styles); + return this; + } + + /** + * Gets the media query variations for this style. + * + * @returns The defined media query variations. + */ + public getMediaQueryStyles(): ReadonlyMap | undefined { + return this._mediaQueryVariations; + } + /** * Gets the full effective set of properties, from composed styles and local properties as applicable. */ From 2c52fe50f3af7c6b6e7bd59e1dc03298d0e70fa3 Mon Sep 17 00:00:00 2001 From: Brian Heston <47367562+bheston@users.noreply.github.com> Date: Wed, 10 May 2023 15:59:49 -0700 Subject: [PATCH 2/2] Change files --- ...b-adaptive-ui-972c117e-79a9-42ce-a3c3-d439465f4178.json | 7 +++++++ ...eb-components-9b964b7c-2bef-4128-8709-3519071312b2.json | 7 +++++++ 2 files changed, 14 insertions(+) create mode 100644 change/@adaptive-web-adaptive-ui-972c117e-79a9-42ce-a3c3-d439465f4178.json create mode 100644 change/@adaptive-web-adaptive-web-components-9b964b7c-2bef-4128-8709-3519071312b2.json diff --git a/change/@adaptive-web-adaptive-ui-972c117e-79a9-42ce-a3c3-d439465f4178.json b/change/@adaptive-web-adaptive-ui-972c117e-79a9-42ce-a3c3-d439465f4178.json new file mode 100644 index 00000000..908759d4 --- /dev/null +++ b/change/@adaptive-web-adaptive-ui-972c117e-79a9-42ce-a3c3-d439465f4178.json @@ -0,0 +1,7 @@ +{ + "type": "minor", + "comment": "Initial support for style module media query variations", + "packageName": "@adaptive-web/adaptive-ui", + "email": "47367562+bheston@users.noreply.github.com", + "dependentChangeType": "patch" +} diff --git a/change/@adaptive-web-adaptive-web-components-9b964b7c-2bef-4128-8709-3519071312b2.json b/change/@adaptive-web-adaptive-web-components-9b964b7c-2bef-4128-8709-3519071312b2.json new file mode 100644 index 00000000..b4e0adbf --- /dev/null +++ b/change/@adaptive-web-adaptive-web-components-9b964b7c-2bef-4128-8709-3519071312b2.json @@ -0,0 +1,7 @@ +{ + "type": "minor", + "comment": "Initial support for style module media query variations", + "packageName": "@adaptive-web/adaptive-web-components", + "email": "47367562+bheston@users.noreply.github.com", + "dependentChangeType": "patch" +}