Skip to content

Commit a7df495

Browse files
committed
Initial support for style module media query variations
1 parent 6ce52f7 commit a7df495

File tree

8 files changed

+121
-2
lines changed

8 files changed

+121
-2
lines changed

package-lock.json

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/adaptive-ui/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
"dependencies": {
3737
"@microsoft/fast-element": "2.0.0-beta.26",
3838
"@microsoft/fast-foundation": "3.0.0-alpha.31",
39+
"@microsoft/fast-web-utilities": "^6.0.0",
3940
"culori": "^3.2.0"
4041
},
4142
"devDependencies": {

packages/adaptive-ui/src/design-tokens/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@ export * from "./density.js";
44
export * from "./elevation.js";
55
export * from "./layer.js";
66
export * from "./modules.js";
7+
export * from "./modules.forced-colors.js";
78
export * from "./palette.js";
89
export * from "./type.js";
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import { SystemColors } from "@microsoft/fast-web-utilities";
2+
import { InteractiveSet } from "../types.js";
3+
import { Styles } from "../modules/styles.js";
4+
5+
/**
6+
* Convenience function for styles that share rest/focus and hover/active states.
7+
*
8+
* @param restAndFocus - The value to use for rest and focus states.
9+
* @param hoverAndActive - The value to use for hover and active states.
10+
* @returns A full interactive color set.
11+
*/
12+
function set(
13+
restAndFocus: string,
14+
hoverAndActive: string,
15+
): InteractiveSet<string> {
16+
return {
17+
rest: restAndFocus,
18+
hover: hoverAndActive,
19+
active: hoverAndActive,
20+
focus: restAndFocus,
21+
disabled: SystemColors.GrayText,
22+
};
23+
}
24+
25+
/**
26+
* @public
27+
*/
28+
export const forcedColorsButtonStyles: Styles = Styles.fromProperties({
29+
backgroundFill: {
30+
...set(SystemColors.ButtonFace, SystemColors.HighlightText),
31+
},
32+
foregroundFill: {
33+
...set(SystemColors.ButtonText, SystemColors.Highlight),
34+
},
35+
borderFill: {
36+
...set(SystemColors.ButtonText, SystemColors.Highlight),
37+
},
38+
});
39+
40+
/**
41+
* @public
42+
*/
43+
export const forcedColorsHighlightStyles: Styles = Styles.fromProperties({
44+
backgroundFill: {
45+
...set(SystemColors.Highlight, SystemColors.ButtonFace),
46+
},
47+
foregroundFill: {
48+
...set(SystemColors.HighlightText, SystemColors.ButtonText),
49+
},
50+
borderFill: {
51+
...set(SystemColors.Highlight, SystemColors.ButtonText),
52+
},
53+
});
54+
55+
/**
56+
* @public
57+
*/
58+
export const forcedColorsTextStyles: Styles = Styles.fromProperties({
59+
foregroundFill: SystemColors.CanvasText,
60+
});

packages/adaptive-ui/src/design-tokens/modules.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { MediaQuery } from "../modules/css.js";
12
import { BorderFill, BorderStyle, BorderThickness, CornerRadius, Fill, Padding, Styles, StyleValue } from "../modules/styles.js";
23
import { cornerRadiusControl, cornerRadiusLayer, focusStrokeThickness, strokeThickness } from "./appearance.js";
34
import {
@@ -101,6 +102,7 @@ import {
101102
typeRampPlus6FontVariations,
102103
typeRampPlus6LineHeight,
103104
} from "./type.js";
105+
import { forcedColorsButtonStyles, forcedColorsHighlightStyles, forcedColorsTextStyles } from "./modules.forced-colors.js";
104106

105107
/**
106108
* Style module for the shape of a control.
@@ -1330,6 +1332,9 @@ export const selectableSelectedStyles: Styles = Styles.compose(
13301332
],
13311333
undefined,
13321334
"styles.selectable-control-selected",
1335+
).withMediaQuery(
1336+
MediaQuery.ForcedColors,
1337+
forcedColorsHighlightStyles,
13331338
);
13341339

13351340
/**
@@ -1343,6 +1348,9 @@ export const selectableUnselectedStyles: Styles = Styles.compose(
13431348
],
13441349
undefined,
13451350
"styles.selectable-control-unselected",
1351+
).withMediaQuery(
1352+
MediaQuery.ForcedColors,
1353+
forcedColorsButtonStyles,
13461354
);
13471355

13481356
/**
@@ -1369,6 +1377,9 @@ export const plainTextStyles: Styles = Styles.compose(
13691377
],
13701378
undefined,
13711379
"styles.text-plain",
1380+
).withMediaQuery(
1381+
MediaQuery.ForcedColors,
1382+
forcedColorsTextStyles,
13721383
);
13731384

13741385
/**

packages/adaptive-ui/src/modules/css.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
import { StyleProperty } from "./types.js";
22

3+
/**
4+
* Convenience media queries for {@link Styles} variations.
5+
*/
6+
export const MediaQuery = {
7+
ForcedColors: "(forced-colors)",
8+
ColorsDark: "(prefers-color-scheme: dark)",
9+
ColorsLight: "(prefers-color-scheme: light)",
10+
} as const;
11+
312
/**
413
* Converts a {@link StyleProperty} to a css property name.
514
*

packages/adaptive-ui/src/modules/element-styles-renderer.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { ComposableStyles, css, HostBehavior } from "@microsoft/fast-element";
22
import { type CSSDirective, ElementStyles } from "@microsoft/fast-element";
3-
import { CSSDesignToken } from "@microsoft/fast-foundation";
3+
import { CSSDesignToken, MatchMediaStyleSheetBehavior } from "@microsoft/fast-foundation";
44
import { Interactivity, type InteractivityDefinition, type StyleModuleTarget, StyleProperty } from "../modules/types.js";
55
import type { InteractiveSet } from "../types.js";
66
import { makeSelector } from "./selector.js";
@@ -184,8 +184,17 @@ export class ElementStylesRenderer {
184184
*/
185185
public static renderStyleRules(baseStyles: ComposableStyles[] = [], styleRules: StyleRules, anatomy?: ComponentAnatomy<any, any>) {
186186
for (const rule of styleRules) {
187+
const target = rule.target || {};
187188
const styles = Styles.fromDeclaration(rule);
188-
const renderedStyles = new ElementStylesRenderer(styles).render(rule.target || {}, anatomy?.interactivity);
189+
const renderedStyles = new ElementStylesRenderer(styles).render(target, anatomy?.interactivity);
190+
191+
styles.getMediaQueryStyles()?.forEach((queryStyles, query) => {
192+
const queryRenderedStyles = new ElementStylesRenderer(queryStyles).render(target, anatomy?.interactivity);
193+
renderedStyles.withBehaviors(
194+
MatchMediaStyleSheetBehavior.with(
195+
window.matchMedia(query))(queryRenderedStyles))
196+
});
197+
189198
baseStyles.push(renderedStyles);
190199
}
191200

packages/adaptive-ui/src/modules/styles.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,8 @@ export class Styles {
203203
private _properties?: StylePropertiesMap;
204204
// Effective properties from composed styles and additional properties
205205
private _composedProperties?: StylePropertiesMap;
206+
// Style overrides for a media query
207+
private _mediaQueryVariations: Map<string, Styles>;
206208

207209
private constructor(
208210
/**
@@ -266,6 +268,30 @@ export class Styles {
266268
this.createEffectiveProperties();
267269
}
268270

271+
/**
272+
* Adds a style variation for a media query like `forced-colors`.
273+
*
274+
* @param query - The media query, see {@link MediaQuery}.
275+
* @param styles - The styles to apply for the provided media query
276+
* @returns The `Styles` definition with media query variation.
277+
*/
278+
public withMediaQuery(query: string, styles: Styles): this {
279+
if (!this._mediaQueryVariations) {
280+
this._mediaQueryVariations = new Map();
281+
}
282+
this._mediaQueryVariations.set(query, styles);
283+
return this;
284+
}
285+
286+
/**
287+
* Gets the media query variations for this style.
288+
*
289+
* @returns The defined media query variations.
290+
*/
291+
public getMediaQueryStyles(): ReadonlyMap<string, Styles> | undefined {
292+
return this._mediaQueryVariations;
293+
}
294+
269295
/**
270296
* Gets the full effective set of properties, from composed styles and local properties as applicable.
271297
*/

0 commit comments

Comments
 (0)