Skip to content

Commit bf4684b

Browse files
committed
wip(framework): scope theming variables
1 parent 7d5f748 commit bf4684b

17 files changed

Lines changed: 318 additions & 89 deletions

File tree

packages/base/lib/generate-styles/index.js

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,24 @@
11
import fs from 'fs/promises';
22
import path from "path";
33
import CleanCSS from "clean-css";
4+
import { processComponentPackageFile } from '@ui5/webcomponents-tools/lib/css-processors/css-processor-themes.mjs';
45
import { pathToFileURL } from "url";
56

67
const generate = async () => {
8+
const packageJSON = JSON.parse(await fs.readFile("./package.json"))
79
await fs.mkdir("src/generated/css/", { recursive: true });
810

911
const files = (await fs.readdir("src/css/")).filter(file => file.endsWith(".css"));
1012
const filesPromises = files.map(async file => {
11-
let content = await fs.readFile(path.join("src/css/", file));
13+
const filePath = path.join("src/css/", file);
14+
let content = await fs.readFile(filePath);
1215
const res = new CleanCSS().minify(`${content}`);
13-
content = `export default \`${res.styles}\`;`;
16+
17+
// Scope used variables
18+
content = await processComponentPackageFile({ text: res.styles, path: filePath }, packageJSON);
19+
20+
content = `export default \`${content}\`;`;
21+
1422
return fs.writeFile(path.join("src/generated/css/", `${file}.ts`), content);
1523
});
1624

packages/base/src/theming/applyTheme.ts

Lines changed: 18 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
import { getThemeProperties, getRegisteredPackages, isThemeRegistered } from "../asset-registries/Themes.js";
2-
import { removeStyle, createOrUpdateStyle } from "../ManagedStyles.js";
2+
import { createOrUpdateStyle } from "../ManagedStyles.js";
33
import getThemeDesignerTheme from "./getThemeDesignerTheme.js";
44
import { fireThemeLoaded } from "./ThemeLoaded.js";
5-
import { getFeature } from "../FeaturesRegistry.js";
65
import { attachCustomThemeStylesToHead, getThemeRoot } from "../config/ThemeRoot.js";
7-
import type OpenUI5Support from "../features/OpenUI5Support.js";
86
import { DEFAULT_THEME } from "../generated/AssetParameters.js";
97
import { getCurrentRuntimeIndex } from "../Runtimes.js";
108

@@ -31,10 +29,6 @@ const loadThemeBase = async (theme: string) => {
3129
}
3230
};
3331

34-
const deleteThemeBase = () => {
35-
removeStyle("data-ui5-theme-properties", BASE_THEME_PACKAGE);
36-
};
37-
3832
const loadComponentPackages = async (theme: string, externalThemeName?: string) => {
3933
const registeredPackages = getRegisteredPackages();
4034

@@ -53,42 +47,34 @@ const loadComponentPackages = async (theme: string, externalThemeName?: string)
5347
};
5448

5549
const detectExternalTheme = async (theme: string) => {
50+
if (getThemeRoot()) {
51+
await attachCustomThemeStylesToHead(theme);
52+
}
53+
5654
// If theme designer theme is detected, use this
5755
const extTheme = getThemeDesignerTheme();
5856
if (extTheme) {
5957
return extTheme;
6058
}
61-
62-
// If OpenUI5Support is enabled, try to find out if it loaded variables
63-
const openUI5Support = getFeature<typeof OpenUI5Support>("OpenUI5Support");
64-
if (openUI5Support && openUI5Support.isOpenUI5Detected()) {
65-
const varsLoaded = openUI5Support.cssVariablesLoaded();
66-
if (varsLoaded) {
67-
return {
68-
themeName: openUI5Support.getConfigurationSettingsObject()?.theme, // just themeName
69-
baseThemeName: "", // baseThemeName is only relevant for custom themes
70-
};
71-
}
72-
} else if (getThemeRoot()) {
73-
await attachCustomThemeStylesToHead(theme);
74-
75-
return getThemeDesignerTheme();
76-
}
7759
};
7860

7961
const applyTheme = async (theme: string) => {
62+
// Detect external theme if available (e.g., from theme designer or custom theme root)
8063
const extTheme = await detectExternalTheme(theme);
8164

82-
// Only load theme_base properties if there is no externally loaded theme, or there is, but it is not being loaded
83-
if (!extTheme || theme !== extTheme.themeName) {
84-
await loadThemeBase(theme);
85-
} else {
86-
deleteThemeBase();
87-
}
88-
89-
// Always load component packages properties. For non-registered themes, try with the base theme, if any
65+
// Determine which theme to use for component packages:
66+
// 1. If the requested theme is registered, use it directly
67+
// 2. If external theme exists, use its base theme (e.g., "my_custom_theme" extends "sap_fiori_3")
68+
// 3. Otherwise, fallback to the default theme
9069
const packagesTheme = isThemeRegistered(theme) ? theme : extTheme && extTheme.baseThemeName;
91-
await loadComponentPackages(packagesTheme || DEFAULT_THEME, extTheme && extTheme.themeName === theme ? theme : undefined);
70+
const effectiveTheme = packagesTheme || DEFAULT_THEME;
71+
72+
// Load base theme properties
73+
await loadThemeBase(effectiveTheme);
74+
75+
// Load component-specific theme properties
76+
// Pass external theme name only if it matches the requested theme to avoid conflicts
77+
await loadComponentPackages(effectiveTheme, extTheme && extTheme.themeName === theme ? theme : undefined);
9278

9379
fireThemeLoaded(theme);
9480
};

packages/compat/cypress/specs/Table.cy.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -509,7 +509,6 @@ describe("Table general interaction", () => {
509509
cy.get("@popinChange")
510510
.should(stub => {
511511
expect(stub).to.have.been.calledTwice;
512-
debugger
513512
// @ts-ignore
514513
expect(stub.args.slice(-1)[0][0].detail.poppedColumns.length).to.equal(2);
515514
})
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<!DOCTYPE html>
2+
<html>
3+
4+
<head>
5+
<meta charset="utf-8">
6+
<title>Theming</title>
7+
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
8+
<meta charset="utf-8">
9+
<script src="../%VITE_BUNDLE_PATH%" type="module"></script>
10+
</head>
11+
12+
<body>
13+
<p><strong>Test Page 1:</strong> Default theming - Tests the component with default theme settings without any
14+
external styles or theme changes.</p>
15+
<p>Expected theme <strong>sap_horizon</strong></p>
16+
17+
<ui5-button>Some button</ui5-button>
18+
</body>
19+
20+
</html>
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<!DOCTYPE html>
2+
<html>
3+
4+
<head>
5+
<meta charset="utf-8">
6+
<title>Theming</title>
7+
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
8+
<meta charset="utf-8">
9+
<script src="../%VITE_BUNDLE_PATH%" type="module"></script>
10+
</head>
11+
12+
<body>
13+
<p><strong>Test Page 6:</strong> Theme change without external styles - Tests programmatic theme switching
14+
behavior without any external CSS interference to verify pure theme transition functionality.</p>
15+
<p>Expected theme <strong>sap_horizon_hcb</strong></p>
16+
<ui5-button>Some button</ui5-button>
17+
18+
<script type="module">
19+
setTimeout(() => {
20+
window["sap-ui-webcomponents-bundle"].configuration.setTheme("sap_horizon_hcb");
21+
}, 1000);
22+
</script>
23+
</body>
24+
25+
</html>
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<!DOCTYPE html>
2+
<html>
3+
4+
<head>
5+
<meta charset="utf-8">
6+
<title>Theming</title>
7+
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
8+
<meta charset="utf-8">
9+
<link rel="stylesheet"
10+
href="https://cdn.jsdelivr.net/npm/@sap-theming/theming-base-content/content/Base/baseLib/sap_belize/css_variables.css">
11+
<script src="../%VITE_BUNDLE_PATH%" type="module"></script>
12+
</head>
13+
14+
<body>
15+
<p><strong>Test Page 2:</strong> Default theming with preloaded external styles - Tests how components behave when
16+
external CSS is loaded before component initialization.</p>
17+
<p>Expected theme <strong>sap_belize</strong></p>
18+
19+
<ui5-button>Some button</ui5-button>
20+
</body>
21+
22+
</html>
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<!DOCTYPE html>
2+
<html>
3+
4+
<head>
5+
<meta charset="utf-8">
6+
<title>Theming</title>
7+
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
8+
<meta charset="utf-8">
9+
<script src="../%VITE_BUNDLE_PATH%" type="module"></script>
10+
</head>
11+
12+
<body>
13+
<p><strong>Test Page 3:</strong> Default theming with external styles loaded later - Tests the impact of external
14+
CSS loaded after component initialization on styling.</p>
15+
<p>Expected theme <strong>sap_belize</strong></p>
16+
17+
<ui5-button>Some button</ui5-button>
18+
<script>
19+
setTimeout(() => {
20+
const link = document.createElement("link");
21+
link.rel = "stylesheet";
22+
link.href = "https://cdn.jsdelivr.net/npm/@sap-theming/theming-base-content/content/Base/baseLib/sap_belize/css_variables.css";
23+
document.head.appendChild(link);
24+
}, 3000);
25+
</script>
26+
</body>
27+
28+
</html>
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<!DOCTYPE html>
2+
<html>
3+
4+
<head>
5+
<meta charset="utf-8">
6+
<title>Theming</title>
7+
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
8+
<meta charset="utf-8">
9+
<link rel="stylesheet"
10+
href="https://cdn.jsdelivr.net/npm/@sap-theming/theming-base-content/content/Base/baseLib/sap_belize/css_variables.css">
11+
<script src="../%VITE_BUNDLE_PATH%" type="module"></script>
12+
</head>
13+
14+
<body>
15+
<p><strong>Test Page 4:</strong> Default theming with theme change and preloaded external styles - Tests theme
16+
switching behavior when external CSS is already present in the DOM.</p>
17+
<p>Expected theme <strong>sap_belize</strong></p>
18+
19+
<ui5-button>Some button</ui5-button>
20+
<script type="module">
21+
setTimeout(() => {
22+
window["sap-ui-webcomponents-bundle"].configuration.setTheme("sap_horizon_hcb");
23+
}, 1000);
24+
</script>
25+
</body>
26+
27+
</html>
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<!DOCTYPE html>
2+
<html>
3+
4+
<head>
5+
<meta charset="utf-8">
6+
<title>Theming</title>
7+
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
8+
<meta charset="utf-8">
9+
<script src="../%VITE_BUNDLE_PATH%" type="module"></script>
10+
</head>
11+
12+
<body>
13+
<p><strong>Test Page 5:</strong> Default theming with theme change and external styles loaded later - Tests theme
14+
switching followed by external CSS injection to verify style resolution order.</p>
15+
<p>Expected theme <strong>sap_belize</strong></p>
16+
<ui5-button>Some button</ui5-button>
17+
18+
<script type="module">
19+
setTimeout(() => {
20+
window["sap-ui-webcomponents-bundle"].configuration.setTheme("sap_horizon_hcb");
21+
setTimeout(() => {
22+
const link = document.createElement("link");
23+
link.rel = "stylesheet";
24+
link.href = "https://cdn.jsdelivr.net/npm/@sap-theming/theming-base-content/content/Base/baseLib/sap_belize/css_variables.css";
25+
document.head.appendChild(link);
26+
}, 1000);
27+
}, 1000);
28+
</script>
29+
</body>
30+
31+
</html>
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<!DOCTYPE html>
2+
<html>
3+
4+
<head>
5+
<meta charset="utf-8">
6+
<title>Theming</title>
7+
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
8+
<meta charset="utf-8">
9+
<script data-ui5-config type="application/json">
10+
{
11+
"loadBaseThemingCSSVariables": true
12+
}
13+
</script>
14+
<script src="../%VITE_BUNDLE_PATH%" type="module"></script>
15+
</head>
16+
17+
<body style="background-color: var(--sapButton_Emphasized_Background);">
18+
<ui5-button>Some content</ui5-button>
19+
</body>
20+
21+
</html>

0 commit comments

Comments
 (0)