Skip to content

Commit 07f70bd

Browse files
marchboxHotell
andauthored
feat(web-components): enabling setting theme on an individual element and unsetting themes (#31973)
Co-authored-by: Martin Hochel <[email protected]>
1 parent b30f776 commit 07f70bd

11 files changed

+726
-97
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"type": "prerelease",
3+
"comment": "feat: enabling setting theme on an individual element and unsetting themes",
4+
"packageName": "@fluentui/web-components",
5+
"email": "[email protected]",
6+
"dependentChangeType": "patch"
7+
}

packages/web-components/.storybook/preview.mjs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,26 @@
1-
import { switchTheme } from '../public/theme-switch.js';
1+
import { teamsDarkTheme, teamsLightTheme, webDarkTheme, webLightTheme } from '@fluentui/tokens';
22
import webcomponentsTheme from './theme.mjs';
3+
import { setTheme } from '../src/theme/set-theme.js';
34

45
import '../src/index-rollup.js';
56
import './docs-root.css';
67

8+
const themes = {
9+
'web-light': webLightTheme,
10+
'web-dark': webDarkTheme,
11+
'teams-light': teamsLightTheme,
12+
'teams-dark': teamsDarkTheme,
13+
};
14+
715
function changeTheme(/** @type {Event} */ e) {
8-
switchTheme(/** @type {Parameters<typeof switchTheme>[number]} */ (/** @type {HTMLInputElement}*/ (e.target).value));
16+
setTheme(themes[/** @type {keyof themes} */ (/** @type {HTMLInputElement}*/ (e.target).value)]);
917
}
1018

19+
// This is needed in Playwright.
20+
Object.defineProperty(window, 'setTheme', { value: setTheme });
21+
1122
document.getElementById('theme-switch')?.addEventListener('change', changeTheme, false);
12-
switchTheme('web-light');
23+
setTheme(themes['web-light']);
1324

1425
export const parameters = {
1526
layout: 'fullscreen',

packages/web-components/docs/api-report.md

Lines changed: 71 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,62 @@ export class BaseButton extends FASTElement {
519519
value?: string;
520520
}
521521

522+
// @public
523+
export class BaseCheckbox extends FASTElement {
524+
autofocus: boolean;
525+
get checked(): boolean;
526+
set checked(next: boolean);
527+
checkValidity(): boolean;
528+
// @internal
529+
clickHandler(e: MouseEvent): boolean | void;
530+
// (undocumented)
531+
connectedCallback(): void;
532+
disabled?: boolean;
533+
disabledAttribute?: boolean;
534+
// @internal
535+
protected disabledAttributeChanged(prev: boolean | undefined, next: boolean | undefined): void;
536+
// @internal
537+
protected disabledChanged(prev: boolean | undefined, next: boolean | undefined): void;
538+
// @internal
539+
elementInternals: ElementInternals;
540+
get form(): HTMLFormElement | null;
541+
static formAssociated: boolean;
542+
formAttribute?: string;
543+
// @internal
544+
formResetCallback(): void;
545+
initialChecked?: boolean;
546+
// @internal
547+
protected initialCheckedChanged(prev: boolean | undefined, next: boolean | undefined): void;
548+
initialValue: string;
549+
// @internal
550+
protected initialValueChanged(prev: string, next: string): void;
551+
// @internal
552+
inputHandler(e: InputEvent): boolean | void;
553+
// @internal
554+
keydownHandler(e: KeyboardEvent): boolean | void;
555+
// @internal
556+
keyupHandler(e: KeyboardEvent): boolean | void;
557+
get labels(): ReadonlyArray<HTMLLabelElement>;
558+
name: string;
559+
reportValidity(): boolean;
560+
required: boolean;
561+
// @internal
562+
protected requiredChanged(prev: boolean, next: boolean): void;
563+
// @internal
564+
protected setAriaChecked(value?: boolean): void;
565+
setCustomValidity(message: string): void;
566+
// @internal
567+
setFormValue(value: File | string | FormData | null, state?: File | string | FormData | null): void;
568+
// @internal
569+
setValidity(flags?: Partial<ValidityState>, message?: string, anchor?: HTMLElement): void;
570+
toggleChecked(force?: boolean): void;
571+
get validationMessage(): string;
572+
get validity(): ValidityState;
573+
get value(): string;
574+
set value(value: string);
575+
get willValidate(): boolean;
576+
}
577+
522578
// @public
523579
export class BaseDivider extends FASTElement {
524580
// (undocumented)
@@ -883,8 +939,6 @@ export const ButtonType: {
883939
// @public
884940
export type ButtonType = ValuesOf<typeof ButtonType>;
885941

886-
// Warning: (ae-forgotten-export) The symbol "BaseCheckbox" needs to be exported by the entry point index.d.ts
887-
//
888942
// @public
889943
export class Checkbox extends BaseCheckbox {
890944
constructor();
@@ -2234,7 +2288,10 @@ export const DividerDefinition: FASTElementDefinition<typeof Divider>;
22342288

22352289
// @public
22362290
export const DividerOrientation: {
2237-
readonly horizontal: "horizontal";
2291+
readonly horizontal: "horizontal"; /**
2292+
* Divider roles
2293+
* @public
2294+
*/
22382295
readonly vertical: "vertical";
22392296
};
22402297

@@ -2971,7 +3028,10 @@ export const RadioGroupDefinition: FASTElementDefinition<typeof RadioGroup>;
29713028

29723029
// @public
29733030
export const RadioGroupOrientation: {
2974-
readonly horizontal: "horizontal";
3031+
readonly horizontal: "horizontal"; /**
3032+
* Radio Group orientation
3033+
* @public
3034+
*/
29753035
readonly vertical: "vertical";
29763036
};
29773037

@@ -3049,12 +3109,12 @@ export const roleForMenuItem: {
30493109
// Warning: (ae-internal-missing-underscore) The name "setTheme" should be prefixed with an underscore because the declaration is marked as @internal
30503110
//
30513111
// @internal
3052-
export const setTheme: (theme: Theme) => void;
3112+
export function setTheme(theme: Theme | null, node?: Document | HTMLElement): void;
30533113

30543114
// Warning: (ae-internal-missing-underscore) The name "setThemeFor" should be prefixed with an underscore because the declaration is marked as @internal
30553115
//
3056-
// @internal (undocumented)
3057-
export const setThemeFor: (element: HTMLElement, theme: Theme) => void;
3116+
// @internal @deprecated (undocumented)
3117+
export function setThemeFor(element: HTMLElement, theme: Theme | null): void;
30583118

30593119
// @public
30603120
export const shadow16 = "var(--shadow16)";
@@ -3475,7 +3535,10 @@ export const TablistDefinition: FASTElementDefinition<typeof Tablist>;
34753535

34763536
// @public
34773537
export const TablistOrientation: {
3478-
readonly horizontal: "horizontal";
3538+
readonly horizontal: "horizontal"; /**
3539+
* The appearance of the component
3540+
* @public
3541+
*/
34793542
readonly vertical: "vertical";
34803543
};
34813544

packages/web-components/playwright.config.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import type { PlaywrightTestConfig } from '@playwright/test';
2+
import { devices } from '@playwright/test';
23

34
const config: PlaywrightTestConfig = {
45
reporter: 'list',
5-
testMatch: /.*\.spec\.ts$/,
66
retries: 3,
77
fullyParallel: process.env.CI ? false : true,
88
timeout: process.env.CI ? 10000 : 30000,
@@ -13,6 +13,23 @@ const config: PlaywrightTestConfig = {
1313
width: 1280,
1414
},
1515
},
16+
projects: [
17+
{
18+
name: 'chromium',
19+
use: { ...devices['Desktop Chrome'] },
20+
testMatch: /.*\.spec\.ts$/,
21+
},
22+
{
23+
name: 'firefox',
24+
use: { ...devices['Desktop Firefox'] },
25+
testMatch: [/set-theme\.spec\.ts$/],
26+
},
27+
{
28+
name: 'webkit',
29+
use: { ...devices['Desktop Safari'] },
30+
testMatch: [/set-theme\.spec\.ts$/],
31+
},
32+
],
1633
webServer: {
1734
// double-quotes are required for Windows
1835
command: `node -e "import('express').then(({ default: e }) => e().use(e.static('./dist/storybook')).listen(6006))"`,

packages/web-components/public/theme-switch.ts

Lines changed: 0 additions & 13 deletions
This file was deleted.

packages/web-components/src/theme/set-theme.bench.ts renamed to packages/web-components/src/theme/set-theme.global.bench.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ const tests: Record<string, TestRenderFunction> = {
2121
setTheme(teamsDarkTheme);
2222
setTheme(teamsLightTheme);
2323

24+
// Unset themes
25+
setTheme(null);
26+
2427
endMeasure();
2528

2629
onComplete();
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { measurePerformance, type TestRenderFunction } from '@tensile-perf/web-components';
2+
import { teamsDarkTheme, teamsLightTheme, webDarkTheme, webLightTheme } from '@fluentui/tokens';
3+
4+
import { setTheme } from './set-theme.js';
5+
6+
const tests: Record<string, TestRenderFunction> = {
7+
mount: ({ onComplete }) => {
8+
const { startMeasure, endMeasure } = measurePerformance();
9+
10+
const el = document.createElement('div');
11+
document.body.append(el);
12+
13+
startMeasure();
14+
15+
// Newly set themes
16+
setTheme(webLightTheme, el);
17+
setTheme(webDarkTheme, el);
18+
setTheme(teamsDarkTheme, el);
19+
setTheme(teamsLightTheme, el);
20+
21+
// Cached themes
22+
setTheme(webLightTheme, el);
23+
setTheme(webDarkTheme, el);
24+
setTheme(teamsDarkTheme, el);
25+
setTheme(teamsLightTheme, el);
26+
27+
// Unset themes
28+
setTheme(null, el);
29+
30+
endMeasure();
31+
32+
onComplete();
33+
},
34+
};
35+
36+
export { tests };
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { measurePerformance, type TestRenderFunction } from '@tensile-perf/web-components';
2+
import { teamsDarkTheme, teamsLightTheme, webDarkTheme, webLightTheme } from '@fluentui/tokens';
3+
4+
import { setTheme } from './set-theme.js';
5+
6+
const tests: Record<string, TestRenderFunction> = {
7+
mount: ({ onComplete }) => {
8+
const { startMeasure, endMeasure } = measurePerformance();
9+
10+
const el = document.createElement('div');
11+
el.attachShadow({ mode: 'open' });
12+
el.shadowRoot!.append(document.createElement('span'));
13+
document.body.append(el);
14+
15+
startMeasure();
16+
17+
// Newly set themes
18+
setTheme(webLightTheme, el);
19+
setTheme(webDarkTheme, el);
20+
setTheme(teamsDarkTheme, el);
21+
setTheme(teamsLightTheme, el);
22+
23+
// Cached themes
24+
setTheme(webLightTheme, el);
25+
setTheme(webDarkTheme, el);
26+
setTheme(teamsDarkTheme, el);
27+
setTheme(teamsLightTheme, el);
28+
29+
// Unset themes
30+
setTheme(null, el);
31+
32+
endMeasure();
33+
34+
onComplete();
35+
},
36+
};
37+
38+
export { tests };

0 commit comments

Comments
 (0)