From f0c317b26c0bd5dce10db2bbec770e6aac9b2dda Mon Sep 17 00:00:00 2001 From: ilhan007 Date: Wed, 4 Feb 2026 11:44:29 +0200 Subject: [PATCH 1/4] feat(framework): ship Font.css --- .../lib/css-processors/css-processor-font-face.mjs | 13 ++++++++++--- packages/base/package-scripts.cjs | 5 +++-- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/packages/base/lib/css-processors/css-processor-font-face.mjs b/packages/base/lib/css-processors/css-processor-font-face.mjs index 585d9544925a..1f0a9ceebbd1 100644 --- a/packages/base/lib/css-processors/css-processor-font-face.mjs +++ b/packages/base/lib/css-processors/css-processor-font-face.mjs @@ -5,12 +5,14 @@ import { fileURLToPath, pathToFileURL } from "url"; const generate = async () => { const themeBasePackage = JSON.parse(await readFile(fileURLToPath(import.meta.resolve("@sap-theming/theming-base-content/package.json", "utf-8")))); + const CDN_URL = `https://cdn.jsdelivr.net/npm/@sap-theming/theming-base-content@${themeBasePackage.version}/content/Base/baseLib/baseTheme/fonts`; + const NPM_URL = `@sap-theming/theming-base-content/content/Base/baseLib/baseTheme/fonts`; const processFontFace = (text) => { const declarationExpr = /@font-face\s*{[^}]*}/g; // change font-face src - text = text.replaceAll("../baseTheme/fonts", `https://cdn.jsdelivr.net/npm/@sap-theming/theming-base-content@${themeBasePackage.version}/content/Base/baseLib/baseTheme/fonts`); + text = text.replaceAll("../baseTheme/fonts", CDN_URL); // extract declarations for separate usage let fontFaceDeclarations = [...text.matchAll(declarationExpr)].map(x => x[0]); @@ -35,10 +37,15 @@ const generate = async () => { build.onEnd(result => { result.outputFiles.forEach(async f => { - let newText = processFontFace(f.text); const tsPath = path.join(process.cwd(), "src/generated/css/FontFace.css.ts"); - const tsContent = `export default \`${newText}\``; + const tsText = processFontFace(f.text); + const tsContent = `export default \`${tsText}\``; + + const cssPath = path.join(process.cwd(), "src/generated/css/FontFace.css"); + const cssContent = tsText.replaceAll(CDN_URL, NPM_URL); + await writeFile(tsPath, tsContent); + await writeFile(cssPath, cssContent); }); }) }, diff --git a/packages/base/package-scripts.cjs b/packages/base/package-scripts.cjs index ab745ad85e00..5f53aaeef35b 100644 --- a/packages/base/package-scripts.cjs +++ b/packages/base/package-scripts.cjs @@ -25,8 +25,8 @@ const scripts = { "dist": `ui5nps-script "${LIB}/rimraf/rimraf.js dist`, }, lint: `ui5nps-script "${LIB}/eslint/eslint.js"`, - generate: "ui5nps clean build.i18n integrate copy generateAssetParameters generateVersionInfo generateStyles generateFontFace build.jsonImports", - prepare: "ui5nps clean build.i18n integrate copy generateAssetParameters generateVersionInfo generateStyles generateFontFace typescript integrate.no-remaining-require build.jsonImports", + generate: "ui5nps clean build.i18n integrate copy generateAssetParameters generateVersionInfo generateStyles generateFontFace copy.fontFaceCss build.jsonImports", + prepare: "ui5nps clean build.i18n integrate copy generateAssetParameters generateVersionInfo generateStyles generateFontFace copy.fontFaceCss typescript integrate.no-remaining-require build.jsonImports", typescript: "tsc -b", integrate: { default: "ui5nps integrate.copy-used-modules integrate.amd-to-es6 integrate.third-party", @@ -56,6 +56,7 @@ const scripts = { default: "ui5nps copy.src", src: `ui5nps-script "${LIB}copy-and-watch/index.js" "src/**/*.{js,css,d.ts}" dist/`, srcWithWatch: `ui5nps-script "${LIB}copy-and-watch/index.js" "src/**/*.{js,css,d.ts}" dist/ --watch --skip-initial-copy`, + fontFaceCss: `ui5nps-script "${LIB}copy-and-watch/index.js" "src/generated/css/FontFace.css" dist/`, }, generateAssetParameters: `ui5nps-script "${assetParametersScript}"`, generateVersionInfo: `ui5nps-script "${versionScript}"`, From 0d2136516e9bfb2ddab87082b95215298d0456dd Mon Sep 17 00:00:00 2001 From: ilhan007 Date: Wed, 4 Feb 2026 13:01:15 +0200 Subject: [PATCH 2/4] chore: check for dist just in case --- .../base/lib/css-processors/css-processor-font-face.mjs | 6 ++++-- packages/base/package-scripts.cjs | 5 ++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/base/lib/css-processors/css-processor-font-face.mjs b/packages/base/lib/css-processors/css-processor-font-face.mjs index 1f0a9ceebbd1..c2893365e118 100644 --- a/packages/base/lib/css-processors/css-processor-font-face.mjs +++ b/packages/base/lib/css-processors/css-processor-font-face.mjs @@ -1,6 +1,6 @@ import * as esbuild from 'esbuild' import * as path from "path"; -import { readFile, writeFile } from "fs/promises"; +import { readFile, writeFile, mkdir } from "fs/promises"; import { fileURLToPath, pathToFileURL } from "url"; const generate = async () => { @@ -41,9 +41,11 @@ const generate = async () => { const tsText = processFontFace(f.text); const tsContent = `export default \`${tsText}\``; - const cssPath = path.join(process.cwd(), "src/generated/css/FontFace.css"); + const distPath = path.join(process.cwd(), "dist"); + const cssPath = path.join(distPath, "FontFace.css"); const cssContent = tsText.replaceAll(CDN_URL, NPM_URL); + await mkdir(distPath, { recursive: true }); await writeFile(tsPath, tsContent); await writeFile(cssPath, cssContent); }); diff --git a/packages/base/package-scripts.cjs b/packages/base/package-scripts.cjs index 5f53aaeef35b..ab745ad85e00 100644 --- a/packages/base/package-scripts.cjs +++ b/packages/base/package-scripts.cjs @@ -25,8 +25,8 @@ const scripts = { "dist": `ui5nps-script "${LIB}/rimraf/rimraf.js dist`, }, lint: `ui5nps-script "${LIB}/eslint/eslint.js"`, - generate: "ui5nps clean build.i18n integrate copy generateAssetParameters generateVersionInfo generateStyles generateFontFace copy.fontFaceCss build.jsonImports", - prepare: "ui5nps clean build.i18n integrate copy generateAssetParameters generateVersionInfo generateStyles generateFontFace copy.fontFaceCss typescript integrate.no-remaining-require build.jsonImports", + generate: "ui5nps clean build.i18n integrate copy generateAssetParameters generateVersionInfo generateStyles generateFontFace build.jsonImports", + prepare: "ui5nps clean build.i18n integrate copy generateAssetParameters generateVersionInfo generateStyles generateFontFace typescript integrate.no-remaining-require build.jsonImports", typescript: "tsc -b", integrate: { default: "ui5nps integrate.copy-used-modules integrate.amd-to-es6 integrate.third-party", @@ -56,7 +56,6 @@ const scripts = { default: "ui5nps copy.src", src: `ui5nps-script "${LIB}copy-and-watch/index.js" "src/**/*.{js,css,d.ts}" dist/`, srcWithWatch: `ui5nps-script "${LIB}copy-and-watch/index.js" "src/**/*.{js,css,d.ts}" dist/ --watch --skip-initial-copy`, - fontFaceCss: `ui5nps-script "${LIB}copy-and-watch/index.js" "src/generated/css/FontFace.css" dist/`, }, generateAssetParameters: `ui5nps-script "${assetParametersScript}"`, generateVersionInfo: `ui5nps-script "${versionScript}"`, From c9b2a9aa0efde5f7c93ec81ab06d4bf16fc9a4ba Mon Sep 17 00:00:00 2001 From: ilhan007 Date: Wed, 4 Feb 2026 13:18:45 +0200 Subject: [PATCH 3/4] chore: update docs --- docs/2-advanced/14-fonts.md | 68 ++++++++++++++++++++++++++++++------- 1 file changed, 56 insertions(+), 12 deletions(-) diff --git a/docs/2-advanced/14-fonts.md b/docs/2-advanced/14-fonts.md index a2d698700e5d..edfb1ab75ab0 100644 --- a/docs/2-advanced/14-fonts.md +++ b/docs/2-advanced/14-fonts.md @@ -1,28 +1,72 @@ -# Custom Fonts +# Fonts -During boot, the UI5 Web Components framework loads the necessary fonts to achieve the desired design of its components. +This article explains how fonts are handled in UI5 Web Components and the options available for customization. -**Important:** These fonts are fetched via network requests. +## Default Font Loading -## Customizing Fonts +During boot, the UI5 Web Components framework automatically loads the necessary fonts to achieve the SAP Fiori design. The fonts are fetched from a CDN (`cdn.jsdelivr.net`) via network requests. + +This default behavior requires no configuration - fonts are loaded automatically when you use UI5 Web Components. + +## Manual Font Loading (via `FontFace.css`) + +*Since version 2.20* + +The `@ui5/webcomponents-base` package ships a standalone `FontFace.css` file that you can use to load fonts via CSS instead of JavaScript. This is useful for: +- Avoiding cross-origin issues with CDN-based font loading +- Environments where you prefer CSS-based font loading + +### Usage + +The file is located at `@ui5/webcomponents-base/dist/FontFace.css` and contains `@font-face` declarations for all standard UI5 fonts. + +Import it in your application entry point: + +```ts +// In your main.ts or App.tsx +import "@ui5/webcomponents-base/dist/FontFace.css"; +``` + +```css +/* In your main.css */ +@import "@ui5/webcomponents-base/dist/FontFace.css"; +``` + +**Note:** The CSS file references font files from the `@sap-theming/theming-base-content` npm package. Most modern bundlers (Vite, Webpack with css-loader, etc.) handle this out of the box. Older build tools may require additional CSS plugins or configuration to resolve npm package paths in `url()` declarations. + +### Disabling Default Font Loading + +When using `FontFace.css`, you should disable the default JavaScript-based font loading to avoid duplicate requests: + +```ts +import { setDefaultFontLoading } from "@ui5/webcomponents-base/dist/config/Fonts.js"; + +setDefaultFontLoading(false); +``` + +## Custom Fonts There are several reasons why you might need to customize fonts: -- To specify different paths for fonts (e.g., due to restrictions on public internet access). -- To include additional declarations within `@font-face`. -- To download additional fonts, such as `72-Light`. -- To prevent the default fonts from being fetched. +- To specify different paths for fonts (e.g., due to restrictions on public internet access) +- To include additional declarations within `@font-face` (e.g., `font-display`) +- To download additional fonts, such as `72-Light` +- To prevent the default fonts from being fetched -To achieve this, you can prevent the fetching of default fonts by configuring `setDefaultFontLoading (@ui5/webcomponents-base/dist/config/Fonts.js)` to `false`: +### Disabling Default Fonts + +To prevent the framework from fetching default fonts, configure `setDefaultFontLoading` to `false`: ```ts -import { getDefaultFontLoading, setDefaultFontLoading } from "@ui5/webcomponents-base/dist/config/Fonts.js"; +import { setDefaultFontLoading } from "@ui5/webcomponents-base/dist/config/Fonts.js"; setDefaultFontLoading(false); ``` -Then, specify the custom font you intend to use. When the UI5 Web Components framework initializes, it will refrain from fetching default fonts and instead use the ones you have provided. +When the UI5 Web Components framework initializes, it will refrain from fetching default fonts and instead use the ones you have provided. + +### Providing Custom Font Definitions -To use the `72-Light` font in your application and specify the `font-display` setting, you should define the font in your application's styles. +After disabling default fonts, specify the custom fonts you intend to use. For example, to use the `72-Light` font with a custom `font-display` setting: ```html +``` -When using `FontFace.css`, you should disable the default JavaScript-based font loading to avoid duplicate requests: +- via `defaultFontLoading` in your HTML -```ts -import { setDefaultFontLoading } from "@ui5/webcomponents-base/dist/config/Fonts.js"; -setDefaultFontLoading(false); +```html + ``` -## Custom Fonts - -There are several reasons why you might need to customize fonts: -- To specify different paths for fonts (e.g., due to restrictions on public internet access) -- To include additional declarations within `@font-face` (e.g., `font-display`) -- To download additional fonts, such as `72-Light` -- To prevent the default fonts from being fetched - -### Disabling Default Fonts +- via `setDefaultFontLoading` JS API -To prevent the framework from fetching default fonts, configure `setDefaultFontLoading` to `false`: ```ts import { setDefaultFontLoading } from "@ui5/webcomponents-base/dist/config/Fonts.js"; @@ -64,12 +61,15 @@ setDefaultFontLoading(false); When the UI5 Web Components framework initializes, it will refrain from fetching default fonts and instead use the ones you have provided. -### Providing Custom Font Definitions -After disabling default fonts, specify the custom fonts you intend to use. For example, to use the `72-Light` font with a custom `font-display` setting: +### 2. Provide Custom Font Definitions + +After disabling the default fonts, specify the custom fonts you intend to use. + +For example, to use the `72-Light` font with a custom `font-display` setting: ```html -