From f086b23889862b0ff9f9375364a6826e80eeb7ed Mon Sep 17 00:00:00 2001 From: ui5-webcomponents-bot Date: Thu, 9 Jan 2025 09:00:25 +0000 Subject: [PATCH 01/42] chore(release): publish v2.6.2 [ci skip] --- CHANGELOG.md | 11 +++++++++++ lerna.json | 2 +- packages/ai/CHANGELOG.md | 8 ++++++++ packages/ai/package.json | 12 ++++++------ packages/base/CHANGELOG.md | 8 ++++++++ packages/base/package.json | 4 ++-- packages/compat/CHANGELOG.md | 8 ++++++++ packages/compat/package.json | 12 ++++++------ packages/create-package/CHANGELOG.md | 8 ++++++++ packages/create-package/package.json | 2 +- packages/fiori/CHANGELOG.md | 8 ++++++++ packages/fiori/package.json | 12 ++++++------ packages/icons-business-suite/CHANGELOG.md | 8 ++++++++ packages/icons-business-suite/package.json | 6 +++--- packages/icons-tnt/CHANGELOG.md | 8 ++++++++ packages/icons-tnt/package.json | 6 +++--- packages/icons/CHANGELOG.md | 8 ++++++++ packages/icons/package.json | 6 +++--- packages/localization/CHANGELOG.md | 8 ++++++++ packages/localization/package.json | 6 +++--- packages/main/CHANGELOG.md | 11 +++++++++++ packages/main/package.json | 16 ++++++++-------- packages/theming/CHANGELOG.md | 8 ++++++++ packages/theming/package.json | 6 +++--- packages/tools/CHANGELOG.md | 8 ++++++++ packages/tools/package.json | 2 +- packages/website/CHANGELOG.md | 8 ++++++++ packages/website/package.json | 2 +- 28 files changed, 165 insertions(+), 47 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e8a7ce35ccac..6b7070a1f6c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [2.6.2](https://github.com/SAP/ui5-webcomponents/compare/v2.6.2-rc.0...v2.6.2) (2025-01-09) + + +### Bug Fixes + +* **build:** fix incorrect module ref in custom-elements-manifest ([#10497](https://github.com/SAP/ui5-webcomponents/issues/10497)) ([ea8cdea](https://github.com/SAP/ui5-webcomponents/commit/ea8cdea0b43f31c11479aa2997387be0ef71c6cb)) + + + + + ## [2.6.2-rc.0](https://github.com/SAP/ui5-webcomponents/compare/v2.6.1...v2.6.2-rc.0) (2025-01-09) diff --git a/lerna.json b/lerna.json index cb1a84d13fb8..871e8124e938 100644 --- a/lerna.json +++ b/lerna.json @@ -14,7 +14,7 @@ "packages/create-package", "packages/compat" ], - "version": "2.6.2-rc.0", + "version": "2.6.2", "command": { "publish": { "allowBranch": "*", diff --git a/packages/ai/CHANGELOG.md b/packages/ai/CHANGELOG.md index b5ace112987d..30f6d2782049 100644 --- a/packages/ai/CHANGELOG.md +++ b/packages/ai/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [2.6.2](https://github.com/SAP/ui5-webcomponents/compare/v2.6.2-rc.0...v2.6.2) (2025-01-09) + +**Note:** Version bump only for package @ui5/webcomponents-ai + + + + + ## [2.6.2-rc.0](https://github.com/SAP/ui5-webcomponents/compare/v2.6.1...v2.6.2-rc.0) (2025-01-09) **Note:** Version bump only for package @ui5/webcomponents-ai diff --git a/packages/ai/package.json b/packages/ai/package.json index 50451454d355..61fbbfc7a990 100644 --- a/packages/ai/package.json +++ b/packages/ai/package.json @@ -1,6 +1,6 @@ { "name": "@ui5/webcomponents-ai", - "version": "2.6.2-rc.0", + "version": "2.6.2", "description": "UI5 Web Components: webcomponents.ai", "ui5": { "webComponentsPackage": true @@ -45,13 +45,13 @@ "directory": "packages/ai" }, "dependencies": { - "@ui5/webcomponents": "2.6.2-rc.0", - "@ui5/webcomponents-base": "2.6.2-rc.0", - "@ui5/webcomponents-icons": "2.6.2-rc.0", - "@ui5/webcomponents-theming": "2.6.2-rc.0" + "@ui5/webcomponents": "2.6.2", + "@ui5/webcomponents-base": "2.6.2", + "@ui5/webcomponents-icons": "2.6.2", + "@ui5/webcomponents-theming": "2.6.2" }, "devDependencies": { - "@ui5/webcomponents-tools": "2.6.2-rc.0", + "@ui5/webcomponents-tools": "2.6.2", "chromedriver": "^131.0.0" } } diff --git a/packages/base/CHANGELOG.md b/packages/base/CHANGELOG.md index 82cf87510846..2bf96b21b88b 100644 --- a/packages/base/CHANGELOG.md +++ b/packages/base/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [2.6.2](https://github.com/SAP/ui5-webcomponents/compare/v2.6.2-rc.0...v2.6.2) (2025-01-09) + +**Note:** Version bump only for package @ui5/webcomponents-base + + + + + ## [2.6.2-rc.0](https://github.com/SAP/ui5-webcomponents/compare/v2.6.1...v2.6.2-rc.0) (2025-01-09) **Note:** Version bump only for package @ui5/webcomponents-base diff --git a/packages/base/package.json b/packages/base/package.json index 789171083f1f..47aeb1590dba 100644 --- a/packages/base/package.json +++ b/packages/base/package.json @@ -1,6 +1,6 @@ { "name": "@ui5/webcomponents-base", - "version": "2.6.2-rc.0", + "version": "2.6.2", "description": "UI5 Web Components: webcomponents.base", "author": "SAP SE (https://www.sap.com)", "license": "Apache-2.0", @@ -57,7 +57,7 @@ }, "devDependencies": { "@openui5/sap.ui.core": "1.120.17", - "@ui5/webcomponents-tools": "2.6.2-rc.0", + "@ui5/webcomponents-tools": "2.6.2", "chromedriver": "^131.0.0", "clean-css": "^5.2.2", "copy-and-watch": "^0.1.5", diff --git a/packages/compat/CHANGELOG.md b/packages/compat/CHANGELOG.md index 95b61b6144a7..aee20c50719a 100644 --- a/packages/compat/CHANGELOG.md +++ b/packages/compat/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [2.6.2](https://github.com/SAP/ui5-webcomponents/compare/v2.6.2-rc.0...v2.6.2) (2025-01-09) + +**Note:** Version bump only for package @ui5/webcomponents-compat + + + + + ## [2.6.2-rc.0](https://github.com/SAP/ui5-webcomponents/compare/v2.6.1...v2.6.2-rc.0) (2025-01-09) **Note:** Version bump only for package @ui5/webcomponents-compat diff --git a/packages/compat/package.json b/packages/compat/package.json index 9fb320bbba15..a68ec97a472a 100644 --- a/packages/compat/package.json +++ b/packages/compat/package.json @@ -1,6 +1,6 @@ { "name": "@ui5/webcomponents-compat", - "version": "2.6.2-rc.0", + "version": "2.6.2", "description": "UI5 Web Components: webcomponents.compat", "ui5": { "webComponentsPackage": true @@ -45,13 +45,13 @@ "directory": "packages/compat" }, "dependencies": { - "@ui5/webcomponents": "2.6.2-rc.0", - "@ui5/webcomponents-base": "2.6.2-rc.0", - "@ui5/webcomponents-icons": "2.6.2-rc.0", - "@ui5/webcomponents-theming": "2.6.2-rc.0" + "@ui5/webcomponents": "2.6.2", + "@ui5/webcomponents-base": "2.6.2", + "@ui5/webcomponents-icons": "2.6.2", + "@ui5/webcomponents-theming": "2.6.2" }, "devDependencies": { - "@ui5/webcomponents-tools": "2.6.2-rc.0", + "@ui5/webcomponents-tools": "2.6.2", "chromedriver": "^131.0.0" } } diff --git a/packages/create-package/CHANGELOG.md b/packages/create-package/CHANGELOG.md index e4a2a2854094..0f4d724ce9e5 100644 --- a/packages/create-package/CHANGELOG.md +++ b/packages/create-package/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [2.6.2](https://github.com/SAP/ui5-webcomponents/compare/v2.6.2-rc.0...v2.6.2) (2025-01-09) + +**Note:** Version bump only for package @ui5/create-webcomponents-package + + + + + ## [2.6.2-rc.0](https://github.com/SAP/ui5-webcomponents/compare/v2.6.1...v2.6.2-rc.0) (2025-01-09) **Note:** Version bump only for package @ui5/create-webcomponents-package diff --git a/packages/create-package/package.json b/packages/create-package/package.json index f534dc2eaf42..32fc9ef13839 100644 --- a/packages/create-package/package.json +++ b/packages/create-package/package.json @@ -1,6 +1,6 @@ { "name": "@ui5/create-webcomponents-package", - "version": "2.6.2-rc.0", + "version": "2.6.2", "description": "UI5 Web Components: create package", "author": "SAP SE (https://www.sap.com)", "license": "Apache-2.0", diff --git a/packages/fiori/CHANGELOG.md b/packages/fiori/CHANGELOG.md index 45065c9e2a87..a538893d5b3e 100644 --- a/packages/fiori/CHANGELOG.md +++ b/packages/fiori/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [2.6.2](https://github.com/SAP/ui5-webcomponents/compare/v2.6.2-rc.0...v2.6.2) (2025-01-09) + +**Note:** Version bump only for package @ui5/webcomponents-fiori + + + + + ## [2.6.2-rc.0](https://github.com/SAP/ui5-webcomponents/compare/v2.6.1...v2.6.2-rc.0) (2025-01-09) **Note:** Version bump only for package @ui5/webcomponents-fiori diff --git a/packages/fiori/package.json b/packages/fiori/package.json index 709a5dbe2d31..940fbbded25a 100644 --- a/packages/fiori/package.json +++ b/packages/fiori/package.json @@ -1,6 +1,6 @@ { "name": "@ui5/webcomponents-fiori", - "version": "2.6.2-rc.0", + "version": "2.6.2", "description": "UI5 Web Components: webcomponents.fiori", "ui5": { "webComponentsPackage": true @@ -53,14 +53,14 @@ "directory": "packages/fiori" }, "dependencies": { - "@ui5/webcomponents": "2.6.2-rc.0", - "@ui5/webcomponents-base": "2.6.2-rc.0", - "@ui5/webcomponents-icons": "2.6.2-rc.0", - "@ui5/webcomponents-theming": "2.6.2-rc.0", + "@ui5/webcomponents": "2.6.2", + "@ui5/webcomponents-base": "2.6.2", + "@ui5/webcomponents-icons": "2.6.2", + "@ui5/webcomponents-theming": "2.6.2", "@zxing/library": "^0.21.3" }, "devDependencies": { - "@ui5/webcomponents-tools": "2.6.2-rc.0", + "@ui5/webcomponents-tools": "2.6.2", "chromedriver": "^131.0.0", "lit": "^2.0.0" } diff --git a/packages/icons-business-suite/CHANGELOG.md b/packages/icons-business-suite/CHANGELOG.md index 44dce0b5c3d4..5716bfea6cd2 100644 --- a/packages/icons-business-suite/CHANGELOG.md +++ b/packages/icons-business-suite/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [2.6.2](https://github.com/SAP/ui5-webcomponents/compare/v2.6.2-rc.0...v2.6.2) (2025-01-09) + +**Note:** Version bump only for package @ui5/webcomponents-icons-business-suite + + + + + ## [2.6.2-rc.0](https://github.com/SAP/ui5-webcomponents/compare/v2.6.1...v2.6.2-rc.0) (2025-01-09) **Note:** Version bump only for package @ui5/webcomponents-icons-business-suite diff --git a/packages/icons-business-suite/package.json b/packages/icons-business-suite/package.json index 1520b52a77e7..2ec66c2e00a3 100644 --- a/packages/icons-business-suite/package.json +++ b/packages/icons-business-suite/package.json @@ -1,6 +1,6 @@ { "name": "@ui5/webcomponents-icons-business-suite", - "version": "2.6.2-rc.0", + "version": "2.6.2", "description": "UI5 Web Components: SAP Fiori Tools icon set", "author": "SAP SE (https://www.sap.com)", "license": "Apache-2.0", @@ -28,9 +28,9 @@ "directory": "packages/icons-business-suite" }, "dependencies": { - "@ui5/webcomponents-base": "2.6.2-rc.0" + "@ui5/webcomponents-base": "2.6.2" }, "devDependencies": { - "@ui5/webcomponents-tools": "2.6.2-rc.0" + "@ui5/webcomponents-tools": "2.6.2" } } diff --git a/packages/icons-tnt/CHANGELOG.md b/packages/icons-tnt/CHANGELOG.md index f1b36d8edf4a..0f592dd01d6d 100644 --- a/packages/icons-tnt/CHANGELOG.md +++ b/packages/icons-tnt/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [2.6.2](https://github.com/SAP/ui5-webcomponents/compare/v2.6.2-rc.0...v2.6.2) (2025-01-09) + +**Note:** Version bump only for package @ui5/webcomponents-icons-tnt + + + + + ## [2.6.2-rc.0](https://github.com/SAP/ui5-webcomponents/compare/v2.6.1...v2.6.2-rc.0) (2025-01-09) **Note:** Version bump only for package @ui5/webcomponents-icons-tnt diff --git a/packages/icons-tnt/package.json b/packages/icons-tnt/package.json index 54a29ba2bae6..1f6fcd01cec1 100644 --- a/packages/icons-tnt/package.json +++ b/packages/icons-tnt/package.json @@ -1,6 +1,6 @@ { "name": "@ui5/webcomponents-icons-tnt", - "version": "2.6.2-rc.0", + "version": "2.6.2", "description": "UI5 Web Components: SAP Fiori Tools icon set", "author": "SAP SE (https://www.sap.com)", "license": "Apache-2.0", @@ -28,9 +28,9 @@ "directory": "packages/icons-tnt" }, "dependencies": { - "@ui5/webcomponents-base": "2.6.2-rc.0" + "@ui5/webcomponents-base": "2.6.2" }, "devDependencies": { - "@ui5/webcomponents-tools": "2.6.2-rc.0" + "@ui5/webcomponents-tools": "2.6.2" } } diff --git a/packages/icons/CHANGELOG.md b/packages/icons/CHANGELOG.md index a070375e2e9e..c140f11db8e1 100644 --- a/packages/icons/CHANGELOG.md +++ b/packages/icons/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [2.6.2](https://github.com/SAP/ui5-webcomponents/compare/v2.6.2-rc.0...v2.6.2) (2025-01-09) + +**Note:** Version bump only for package @ui5/webcomponents-icons + + + + + ## [2.6.2-rc.0](https://github.com/SAP/ui5-webcomponents/compare/v2.6.1...v2.6.2-rc.0) (2025-01-09) **Note:** Version bump only for package @ui5/webcomponents-icons diff --git a/packages/icons/package.json b/packages/icons/package.json index ffde7dd06320..eee2268373a1 100644 --- a/packages/icons/package.json +++ b/packages/icons/package.json @@ -1,6 +1,6 @@ { "name": "@ui5/webcomponents-icons", - "version": "2.6.2-rc.0", + "version": "2.6.2", "description": "UI5 Web Components: webcomponents.SAP-icons", "author": "SAP SE (https://www.sap.com)", "license": "Apache-2.0", @@ -28,9 +28,9 @@ "directory": "packages/icons" }, "dependencies": { - "@ui5/webcomponents-base": "2.6.2-rc.0" + "@ui5/webcomponents-base": "2.6.2" }, "devDependencies": { - "@ui5/webcomponents-tools": "2.6.2-rc.0" + "@ui5/webcomponents-tools": "2.6.2" } } diff --git a/packages/localization/CHANGELOG.md b/packages/localization/CHANGELOG.md index 0e150c62d7df..137716038e7e 100644 --- a/packages/localization/CHANGELOG.md +++ b/packages/localization/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [2.6.2](https://github.com/SAP/ui5-webcomponents/compare/v2.6.2-rc.0...v2.6.2) (2025-01-09) + +**Note:** Version bump only for package @ui5/webcomponents-localization + + + + + ## [2.6.2-rc.0](https://github.com/SAP/ui5-webcomponents/compare/v2.6.1...v2.6.2-rc.0) (2025-01-09) **Note:** Version bump only for package @ui5/webcomponents-localization diff --git a/packages/localization/package.json b/packages/localization/package.json index cb7ca15eadd2..1592f0cb6f71 100644 --- a/packages/localization/package.json +++ b/packages/localization/package.json @@ -1,6 +1,6 @@ { "name": "@ui5/webcomponents-localization", - "version": "2.6.2-rc.0", + "version": "2.6.2", "description": "Localization for UI5 Web Components", "author": "SAP SE (https://www.sap.com)", "license": "Apache-2.0", @@ -33,7 +33,7 @@ "@babel/generator": "^7.23.6", "@babel/parser": "^7.23.6", "@openui5/sap.ui.core": "1.120.17", - "@ui5/webcomponents-tools": "2.6.2-rc.0", + "@ui5/webcomponents-tools": "2.6.2", "babel-plugin-amd-to-esm": "^2.0.3", "chromedriver": "^131.0.0", "estree-walk": "^2.2.0", @@ -42,6 +42,6 @@ }, "dependencies": { "@types/openui5": "^1.113.0", - "@ui5/webcomponents-base": "2.6.2-rc.0" + "@ui5/webcomponents-base": "2.6.2" } } diff --git a/packages/main/CHANGELOG.md b/packages/main/CHANGELOG.md index 4d5c2b210091..342ad8e064f3 100644 --- a/packages/main/CHANGELOG.md +++ b/packages/main/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [2.6.2](https://github.com/SAP/ui5-webcomponents/compare/v2.6.2-rc.0...v2.6.2) (2025-01-09) + + +### Bug Fixes + +* **build:** fix incorrect module ref in custom-elements-manifest ([#10497](https://github.com/SAP/ui5-webcomponents/issues/10497)) ([ea8cdea](https://github.com/SAP/ui5-webcomponents/commit/ea8cdea0b43f31c11479aa2997387be0ef71c6cb)) + + + + + ## [2.6.2-rc.0](https://github.com/SAP/ui5-webcomponents/compare/v2.6.1...v2.6.2-rc.0) (2025-01-09) diff --git a/packages/main/package.json b/packages/main/package.json index a7ee53df56f6..c0a493e06e20 100644 --- a/packages/main/package.json +++ b/packages/main/package.json @@ -1,6 +1,6 @@ { "name": "@ui5/webcomponents", - "version": "2.6.2-rc.0", + "version": "2.6.2", "description": "UI5 Web Components: webcomponents.main", "ui5": { "webComponentsPackage": true @@ -50,15 +50,15 @@ "directory": "packages/main" }, "dependencies": { - "@ui5/webcomponents-base": "2.6.2-rc.0", - "@ui5/webcomponents-icons": "2.6.2-rc.0", - "@ui5/webcomponents-icons-business-suite": "2.6.2-rc.0", - "@ui5/webcomponents-icons-tnt": "2.6.2-rc.0", - "@ui5/webcomponents-localization": "2.6.2-rc.0", - "@ui5/webcomponents-theming": "2.6.2-rc.0" + "@ui5/webcomponents-base": "2.6.2", + "@ui5/webcomponents-icons": "2.6.2", + "@ui5/webcomponents-icons-business-suite": "2.6.2", + "@ui5/webcomponents-icons-tnt": "2.6.2", + "@ui5/webcomponents-localization": "2.6.2", + "@ui5/webcomponents-theming": "2.6.2" }, "devDependencies": { - "@ui5/webcomponents-tools": "2.6.2-rc.0", + "@ui5/webcomponents-tools": "2.6.2", "chromedriver": "^131.0.0", "lit": "^2.0.0" } diff --git a/packages/theming/CHANGELOG.md b/packages/theming/CHANGELOG.md index b815d5612f14..661903b1f0ea 100644 --- a/packages/theming/CHANGELOG.md +++ b/packages/theming/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [2.6.2](https://github.com/SAP/ui5-webcomponents/compare/v2.6.2-rc.0...v2.6.2) (2025-01-09) + +**Note:** Version bump only for package @ui5/webcomponents-theming + + + + + ## [2.6.2-rc.0](https://github.com/SAP/ui5-webcomponents/compare/v2.6.1...v2.6.2-rc.0) (2025-01-09) **Note:** Version bump only for package @ui5/webcomponents-theming diff --git a/packages/theming/package.json b/packages/theming/package.json index c30983695372..09aacc69da2f 100644 --- a/packages/theming/package.json +++ b/packages/theming/package.json @@ -1,6 +1,6 @@ { "name": "@ui5/webcomponents-theming", - "version": "2.6.2-rc.0", + "version": "2.6.2", "description": "UI5 Web Components: webcomponents.theming", "author": "SAP SE (https://www.sap.com)", "license": "Apache-2.0", @@ -31,10 +31,10 @@ }, "dependencies": { "@sap-theming/theming-base-content": "11.24.0", - "@ui5/webcomponents-base": "2.6.2-rc.0" + "@ui5/webcomponents-base": "2.6.2" }, "devDependencies": { - "@ui5/webcomponents-tools": "2.6.2-rc.0", + "@ui5/webcomponents-tools": "2.6.2", "globby": "^13.1.1", "json-beautify": "^1.1.1", "nps": "^5.10.0", diff --git a/packages/tools/CHANGELOG.md b/packages/tools/CHANGELOG.md index 04d6f8ef4647..5ad0f814ff02 100644 --- a/packages/tools/CHANGELOG.md +++ b/packages/tools/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [2.6.2](https://github.com/SAP/ui5-webcomponents/compare/v2.6.2-rc.0...v2.6.2) (2025-01-09) + +**Note:** Version bump only for package @ui5/webcomponents-tools + + + + + ## [2.6.2-rc.0](https://github.com/SAP/ui5-webcomponents/compare/v2.6.1...v2.6.2-rc.0) (2025-01-09) **Note:** Version bump only for package @ui5/webcomponents-tools diff --git a/packages/tools/package.json b/packages/tools/package.json index 6e59f249b521..1df3aedda65d 100644 --- a/packages/tools/package.json +++ b/packages/tools/package.json @@ -1,6 +1,6 @@ { "name": "@ui5/webcomponents-tools", - "version": "2.6.2-rc.0", + "version": "2.6.2", "description": "UI5 Web Components: webcomponents.tools", "author": "SAP SE (https://www.sap.com)", "license": "Apache-2.0", diff --git a/packages/website/CHANGELOG.md b/packages/website/CHANGELOG.md index aab843d53aa7..51e9f146b023 100644 --- a/packages/website/CHANGELOG.md +++ b/packages/website/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [2.6.2](https://github.com/SAP/ui5-webcomponents/compare/v2.6.2-rc.0...v2.6.2) (2025-01-09) + +**Note:** Version bump only for package @ui5/webcomponents-website + + + + + ## [2.6.2-rc.0](https://github.com/SAP/ui5-webcomponents/compare/v2.6.1...v2.6.2-rc.0) (2025-01-09) **Note:** Version bump only for package @ui5/webcomponents-website diff --git a/packages/website/package.json b/packages/website/package.json index 19dfd006e454..3b2d3e224a51 100644 --- a/packages/website/package.json +++ b/packages/website/package.json @@ -1,6 +1,6 @@ { "name": "@ui5/webcomponents-website", - "version": "2.6.2-rc.0", + "version": "2.6.2", "private": true, "scripts": { "generate-local-cdn": "rimraf ./local-cdn && node ./build-scripts/local-cdn.mjs", From b79b529c1eacd0cb695121f7c94b8c92fb1fcb3a Mon Sep 17 00:00:00 2001 From: Tsanislav Gatev Date: Thu, 9 Jan 2025 13:42:51 +0200 Subject: [PATCH 02/42] chore: use fireDecoratorEvent over fireEvent (#10247) The fireEvent method is deprecated, we migrated the code base to use fireDecoratorEvent see #9944 --- packages/main/src/Menu.ts | 57 ++++++++++++++++++----------- packages/main/src/MenuItem.ts | 67 ++++++++++++++++++++++++++++++----- 2 files changed, 95 insertions(+), 29 deletions(-) diff --git a/packages/main/src/Menu.ts b/packages/main/src/Menu.ts index 71c6b55179ec..4ef475863559 100644 --- a/packages/main/src/Menu.ts +++ b/packages/main/src/Menu.ts @@ -1,5 +1,4 @@ import UI5Element from "@ui5/webcomponents-base/dist/UI5Element.js"; -import type { UI5CustomEvent } from "@ui5/webcomponents-base"; import customElement from "@ui5/webcomponents-base/dist/decorators/customElement.js"; import property from "@ui5/webcomponents-base/dist/decorators/property.js"; import slot from "@ui5/webcomponents-base/dist/decorators/slot.js"; @@ -103,42 +102,57 @@ type MenuBeforeCloseEventDetail = { escPressed: boolean }; * Fired when an item is being clicked. * * **Note:** Since 1.17.0 the event is preventable, allowing the menu to remain open after an item is pressed. - * @allowPreventDefault * @param { HTMLElement } item The currently clicked menu item. * @param { string } text The text of the currently clicked menu item. * @public */ -@event("item-click") +@event("item-click", { + cancelable: true, +}) /** - * Fired before the menu is opened. This event can be cancelled, which will prevent the menu from opening. **This event does not bubble.** + * Fired before the menu is opened. This event can be cancelled, which will prevent the menu from opening. * * **Note:** Since 1.14.0 the event is also fired before a sub-menu opens. * @public - * @allowPreventDefault * @since 1.10.0 * @param { HTMLElement } item The `ui5-menu-item` that triggers opening of the sub-menu or undefined when fired upon root menu opening. */ -@event("before-open") +@event("before-open", { + bubbles: true, + cancelable: true, +}) /** - * Fired after the menu is opened. **This event does not bubble.** + * Fired after the menu is opened. * @public * @since 1.10.0 */ -@event("open") +@event("open", { + bubbles: true, +}) /** - * Fired before the menu is closed. This event can be cancelled, which will prevent the menu from closing. **This event does not bubble.** + * Fired when the menu is being closed. + * @private + */ +@event("close-menu", { + bubbles: true, +}) + +/** + * Fired before the menu is closed. This event can be cancelled, which will prevent the menu from closing. * @public - * @allowPreventDefault * @param {boolean} escPressed Indicates that `ESC` key has triggered the event. * @since 1.10.0 */ -@event("before-close") +@event("before-close", { + bubbles: true, + cancelable: true, +}) /** - * Fired after the menu is closed. **This event does not bubble.** + * Fired after the menu is closed. * @public * @since 1.10.0 */ @@ -151,6 +165,7 @@ class Menu extends UI5Element { "open": void, "before-close": MenuBeforeCloseEventDetail, "close": void, + "close-menu": void, } /** * Defines the header text of the menu (displayed on mobile). @@ -254,9 +269,9 @@ class Menu extends UI5Element { return; } - this.fireEvent("before-open", { + this.fireDecoratorEvent("before-open", { item, - }, false, false); + }); item._popover.opener = item; item._popover.open = true; item.selected = true; @@ -317,13 +332,13 @@ class Menu extends UI5Element { const item = e.detail.item as MenuItem; if (!item._popover) { - const prevented = !this.fireEvent("item-click", { + const prevented = !this.fireDecoratorEvent("item-click", { "item": item, "text": item.text || "", - }, true, false); + }); if (!prevented && this._popover) { - item.fireEvent("close-menu", {}); + item.fireDecoratorEvent("close-menu"); } } else { this._openItemSubMenu(item); @@ -353,7 +368,7 @@ class Menu extends UI5Element { } _beforePopoverOpen(e: CustomEvent) { - const prevented = !this.fireEvent("before-open", {}, true, true); + const prevented = !this.fireDecoratorEvent("before-open", {}); if (prevented) { this.open = false; @@ -363,11 +378,11 @@ class Menu extends UI5Element { _afterPopoverOpen() { this._menuItems[0]?.focus(); - this.fireEvent("open", {}, false, true); + this.fireDecoratorEvent("open"); } - _beforePopoverClose(e: UI5CustomEvent) { - const prevented = !this.fireEvent("before-close", { escPressed: e.detail.escPressed }, true, true); + _beforePopoverClose(e: CustomEvent) { + const prevented = !this.fireDecoratorEvent("before-close", { escPressed: e.detail.escPressed }); if (prevented) { this.open = true; diff --git a/packages/main/src/MenuItem.ts b/packages/main/src/MenuItem.ts index 0d51dbee9064..3dc75dca7980 100644 --- a/packages/main/src/MenuItem.ts +++ b/packages/main/src/MenuItem.ts @@ -1,7 +1,8 @@ import jsxRenderer from "@ui5/webcomponents-base/dist/renderer/JsxRenderer.js"; import customElement from "@ui5/webcomponents-base/dist/decorators/customElement.js"; import property from "@ui5/webcomponents-base/dist/decorators/property.js"; -import type { AccessibilityAttributes, UI5CustomEvent } from "@ui5/webcomponents-base"; +import type { AccessibilityAttributes } from "@ui5/webcomponents-base"; +import event from "@ui5/webcomponents-base/dist/decorators/event-strict.js"; import slot from "@ui5/webcomponents-base/dist/decorators/slot.js"; import i18n from "@ui5/webcomponents-base/dist/decorators/i18n.js"; import { isPhone } from "@ui5/webcomponents-base/dist/Device.js"; @@ -57,7 +58,57 @@ type MenuItemAccessibilityAttributes = Pick("before-open", {}, true, false); + const prevented = !this.fireDecoratorEvent("before-open", {}); if (prevented) { e.preventDefault(); @@ -317,11 +368,11 @@ class MenuItem extends ListItem implements IMenuItem { _afterPopoverOpen() { this.items[0]?.focus(); - this.fireEvent("open", {}, false, false); + this.fireDecoratorEvent("open"); } - _beforePopoverClose(e: UI5CustomEvent) { - const prevented = !this.fireEvent("before-close", { escPressed: e.detail.escPressed }, true, false); + _beforePopoverClose(e: CustomEvent) { + const prevented = !this.fireDecoratorEvent("before-close", { escPressed: e.detail.escPressed }); if (prevented) { e.preventDefault(); @@ -332,13 +383,13 @@ class MenuItem extends ListItem implements IMenuItem { if (e.detail.escPressed) { this.focus(); if (isPhone()) { - this.fireEvent("close-menu", {}); + this.fireDecoratorEvent("close-menu"); } } } _afterPopoverClose() { - this.fireEvent("close", {}, false, false); + this.fireDecoratorEvent("close"); } } From 95471e21d21972110afc03cdbebdd87e1049643e Mon Sep 17 00:00:00 2001 From: ilhan orhan Date: Fri, 10 Jan 2025 10:30:18 +0200 Subject: [PATCH 03/42] docs(ui5-form): remove exp flag (#10508) --- packages/main/src/Form.ts | 3 +-- packages/main/src/FormGroup.ts | 1 - packages/main/src/FormItem.ts | 1 - .../website/docs/_components_pages/main/Form/FormGroup.mdx | 1 - packages/website/docs/_components_pages/main/Form/FormItem.mdx | 1 - 5 files changed, 1 insertion(+), 6 deletions(-) diff --git a/packages/main/src/Form.ts b/packages/main/src/Form.ts index b27497268429..350eee40fe57 100644 --- a/packages/main/src/Form.ts +++ b/packages/main/src/Form.ts @@ -26,10 +26,10 @@ const breakpoints = ["S", "M", "L", "Xl"]; const MAX_FORM_ITEM_CELLS = 12; const DEFAULT_FORM_ITEM_LAYOUT = "4fr 8fr 0fr"; const DEFAULT_FORM_ITEM_LAYOUT_S = "1fr"; + /** * Interface for components that can be slotted inside `ui5-form` as items. * @public - * @experimental * @since 2.0.0 */ interface IFormItem extends UI5Element { @@ -197,7 +197,6 @@ type ItemsInfo = { * * @public * @since 2.0.0 - * @experimental This component is availabe since 2.0 under an experimental flag and its API and behaviour are subject to change. * @extends UI5Element */ @customElement({ diff --git a/packages/main/src/FormGroup.ts b/packages/main/src/FormGroup.ts index 230525b417ac..e857ca9ea74c 100644 --- a/packages/main/src/FormGroup.ts +++ b/packages/main/src/FormGroup.ts @@ -31,7 +31,6 @@ import type FormItemSpacing from "./types/FormItemSpacing.js"; * @public * @implements {IFormItem} * @since 2.0.0 - * @experimental This component is availabe since 2.0 under an experimental flag and its API and behaviour are subject to change. * @extends UI5Element */ @customElement({ diff --git a/packages/main/src/FormItem.ts b/packages/main/src/FormItem.ts index a0fd1b32e341..054f7483babf 100644 --- a/packages/main/src/FormItem.ts +++ b/packages/main/src/FormItem.ts @@ -37,7 +37,6 @@ import type FormItemSpacing from "./types/FormItemSpacing.js"; * @implements {IFormItem} * @public * @since 2.0.0 - * @experimental This component is availabe since 2.0 under an experimental flag and its API and behaviour are subject to change. * @extends UI5Element */ @customElement({ diff --git a/packages/website/docs/_components_pages/main/Form/FormGroup.mdx b/packages/website/docs/_components_pages/main/Form/FormGroup.mdx index 084bdc31ff19..46dfed75a2f6 100644 --- a/packages/website/docs/_components_pages/main/Form/FormGroup.mdx +++ b/packages/website/docs/_components_pages/main/Form/FormGroup.mdx @@ -1,6 +1,5 @@ --- slug: ../../FormGroup -sidebar_class_name: expComponentBadge --- <%COMPONENT_OVERVIEW%> diff --git a/packages/website/docs/_components_pages/main/Form/FormItem.mdx b/packages/website/docs/_components_pages/main/Form/FormItem.mdx index 1102ddde4005..517593307ca7 100644 --- a/packages/website/docs/_components_pages/main/Form/FormItem.mdx +++ b/packages/website/docs/_components_pages/main/Form/FormItem.mdx @@ -1,6 +1,5 @@ --- slug: ../../FormItem -sidebar_class_name: expComponentBadge --- <%COMPONENT_OVERVIEW%> From dfe09ae51987ef6237fccfbf0bcb76abb8251dee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cahit=20G=C3=BCrg=C3=BCc?= Date: Fri, 10 Jan 2025 11:03:57 +0100 Subject: [PATCH 04/42] feat(ui5-table): table row actions feature added (#10460) * feat(ui5-table): table row actions - rebase First push after the last rebase * feat(ui5-table): Table row actions * feat(ui5-table): table row actions feature added * feat(ui5-table): table row actions feature added --------- Co-authored-by: Felix Schubert Co-authored-by: ilhan007 --- packages/main/cypress/specs/Table.cy.ts | 2 +- .../main/cypress/specs/TableRowActions.cy.ts | 212 ++++++++++++++++++ packages/main/src/Table.hbs | 2 +- packages/main/src/Table.ts | 77 ++++++- packages/main/src/TableCell.ts | 4 +- packages/main/src/TableCellBase.ts | 8 +- packages/main/src/TableExtension.ts | 2 +- packages/main/src/TableHeaderCell.ts | 6 +- packages/main/src/TableHeaderRow.hbs | 4 + packages/main/src/TableHeaderRow.ts | 8 + packages/main/src/TableRow.hbs | 25 ++- packages/main/src/TableRow.ts | 88 +++++++- packages/main/src/TableRowAction.ts | 61 +++++ packages/main/src/TableRowActionBase.hbs | 17 ++ packages/main/src/TableRowActionBase.ts | 117 ++++++++++ packages/main/src/TableRowActionNavigation.ts | 46 ++++ packages/main/src/TableRowBase.ts | 3 + packages/main/src/TableVirtualizer.ts | 4 +- packages/main/src/bundle.esm.ts | 2 + .../main/src/i18n/messagebundle.properties | 6 +- packages/main/src/themes/TableCellBase.css | 2 +- packages/main/src/themes/TableRow.css | 169 ++++++++------ .../main/src/themes/TableRowActionBase.css | 13 ++ packages/main/src/themes/TableRowBase.css | 20 +- .../main/src/themes/base/Table-parameters.css | 12 +- packages/main/test/pages/TableRowActions.html | 90 ++++++++ .../main/Table/TableRowAction.mdx | 14 ++ .../main/Table/TableRowActionNavigation.mdx | 14 ++ .../main/Table/RowAction/RowAction.md | 10 + .../_samples/main/Table/RowAction/main.js | 41 ++++ .../_samples/main/Table/RowAction/sample.html | 65 ++++++ .../RowActionNavigation.md | 10 + .../main/Table/RowActionNavigation/main.js | 13 ++ .../Table/RowActionNavigation/sample.html | 57 +++++ 34 files changed, 1101 insertions(+), 123 deletions(-) create mode 100644 packages/main/cypress/specs/TableRowActions.cy.ts create mode 100644 packages/main/src/TableRowAction.ts create mode 100644 packages/main/src/TableRowActionBase.hbs create mode 100644 packages/main/src/TableRowActionBase.ts create mode 100644 packages/main/src/TableRowActionNavigation.ts create mode 100644 packages/main/src/themes/TableRowActionBase.css create mode 100644 packages/main/test/pages/TableRowActions.html create mode 100644 packages/website/docs/_components_pages/main/Table/TableRowAction.mdx create mode 100644 packages/website/docs/_components_pages/main/Table/TableRowActionNavigation.mdx create mode 100644 packages/website/docs/_samples/main/Table/RowAction/RowAction.md create mode 100644 packages/website/docs/_samples/main/Table/RowAction/main.js create mode 100644 packages/website/docs/_samples/main/Table/RowAction/sample.html create mode 100644 packages/website/docs/_samples/main/Table/RowActionNavigation/RowActionNavigation.md create mode 100644 packages/website/docs/_samples/main/Table/RowActionNavigation/main.js create mode 100644 packages/website/docs/_samples/main/Table/RowActionNavigation/sample.html diff --git a/packages/main/cypress/specs/Table.cy.ts b/packages/main/cypress/specs/Table.cy.ts index 20a053e69a31..3f304719fbde 100644 --- a/packages/main/cypress/specs/Table.cy.ts +++ b/packages/main/cypress/specs/Table.cy.ts @@ -21,7 +21,7 @@ describe("Table - Rendering", () => { Cell A Cell B - + `); cy.get("ui5-table").should("exist"); diff --git a/packages/main/cypress/specs/TableRowActions.cy.ts b/packages/main/cypress/specs/TableRowActions.cy.ts new file mode 100644 index 000000000000..560150ba3ca2 --- /dev/null +++ b/packages/main/cypress/specs/TableRowActions.cy.ts @@ -0,0 +1,212 @@ +/* eslint-disable cypress/no-unnecessary-waiting */ +/* eslint-disable newline-per-chained-call */ +import "../../src/Table.js"; +import "../../src/TableHeaderRow.js"; +import "../../src/TableHeaderCell.js"; +import "../../src/TableRow.js"; +import "../../src/TableCell.js"; +import "../../src/TableRowAction.js"; +import "../../src/TableRowActionNavigation.js"; +import "../../src/Menu.js"; +import "../../src/MenuItem.js"; +import "@ui5/webcomponents-icons/dist/add.js"; +import "@ui5/webcomponents-icons/dist/edit.js"; +import "@ui5/webcomponents-icons/dist/delete.js"; +import "@ui5/webcomponents-icons/dist/share.js"; +import "@ui5/webcomponents-icons/dist/overflow.js"; +import "@ui5/webcomponents-icons/dist/navigation-right-arrow.js"; + +describe("TableRowActions", () => { + function mountTable(rowActionCount = 0, rows = "") { + cy.mount(` + + + ${rows} + + `); + + cy.get("[ui5-table]").as("table").children("ui5-table-row").as("rows"); + cy.get("@table").children("ui5-table-header-row").first().as("headerRow"); + cy.get("@table").shadow().find("#table").as("innerTable"); + cy.get("@rows").then($rows => { + $rows.each(index => { + cy.get("@rows").eq(index).as(`row${index + 1}`); + }); + }); + cy.get("@table").then($table => { + $table[0].addEventListener("row-action-click", cy.stub().as("rowActionClick")); + }); + } + + describe("Rendering", () => { + it("tests single row action", () => { + mountTable(1, ` + + + + + + + + + + + + + `); + + cy.get("@headerRow").shadow().find("#actions-cell").should("exist"); + cy.get("@innerTable").should("have.css", "gridTemplateColumns", `${8 + 36 + 8}px`); + cy.get("@row1").find("[icon=add]").shadow().find("ui5-button").should("exist"); + cy.get("@row2").find("[icon=add]").should("have.css", "display", "block"); + cy.get("@row3").find("ui5-table-row-action-navigation").shadow().find("ui5-icon").should("have.attr", "name", "navigation-right-arrow"); + cy.get("@row4").find("ui5-table-row-action-navigation").shadow().find("ui5-button").should("have.attr", "icon", "navigation-right-arrow"); + + cy.get("#addAction").realClick(); + cy.get("@rowActionClick").invoke("getCall", 0).its("args.0.detail.row.id").should("equal", "addRow"); + cy.get("@rowActionClick").invoke("getCall", 0).its("args.0.detail.action.id").should("equal", "addAction"); + cy.get("#navigationAction").realClick(); + cy.get("@rowActionClick").invoke("getCall", 1).its("args.0.detail.row.id").should("equal", "navigationRow"); + cy.get("@rowActionClick").invoke("getCall", 1).its("args.0.detail.action.id").should("equal", "navigationAction"); + + cy.get("@table").invoke("attr", "row-action-count", "0"); + cy.get("@headerRow").shadow().find("#actions-cell").should("not.exist"); + cy.get("@row1").shadow().find("#actions-cell").should("not.exist"); + }); + + it("tests multiple row actions - all visible", () => { + mountTable(2, ` + + + + + + + `); + + cy.get("@headerRow").shadow().find("#actions-cell").should("exist"); + cy.get("@innerTable").should("have.css", "gridTemplateColumns", `${8 + 36 + 4 + 36 + 8}px`); + cy.get("@row1").shadow().find("#actions-cell").children().as("actions"); + cy.get("@actions").should("have.length", 2); + cy.get("@actions").eq(0).as("overflowButton"); + cy.get("@overflowButton").should("have.attr", "ui5-button"); + cy.get("@overflowButton").and("have.attr", "icon", "overflow"); + cy.get("@actions").eq(1).should("have.attr", "name", "actions-1"); + + cy.get("@overflowButton").realClick(); + cy.wait(200); + cy.get("ui5-menu").should("exist"); + cy.get("[ui5-menu-item]").as("menuItems").should("have.length", 3); + cy.get("@menuItems").eq(0).should("have.attr", "text", "Add").and("have.attr", "icon", "add"); + cy.get("@menuItems").eq(1).should("have.attr", "text", "Edit").and("have.attr", "icon", "edit"); + cy.get("@menuItems").eq(2).should("have.attr", "text", "Delete").and("have.attr", "icon", "delete"); + + cy.get("@menuItems").eq(0).ui5MenuItemClick(); + cy.get("@rowActionClick").invoke("getCall", 0).its("args.0.detail.action.id").should("equal", "addAction"); + cy.get("ui5-menu").invoke("get", 0).its("open").should("be.false"); + + cy.get("@overflowButton").realClick(); + cy.wait(200); + cy.get("ui5-menu").should("have.length", 1); + cy.get("[ui5-menu-item]").as("menuItems").should("have.length", 3); + cy.get("@menuItems").eq(1).ui5MenuItemClick(); + cy.get("@rowActionClick").invoke("getCall", 1).its("args.0.detail.action.id").should("equal", "editAction"); + + cy.get("@table").invoke("attr", "row-action-count", "3"); + cy.get("@innerTable").should("have.css", "gridTemplateColumns", `${8 + 36 + 4 + 36 + 4 + 36 + 8}px`); + cy.get("@actions").should("have.length", 3); + cy.get("@actions").eq(0).should("have.attr", "name", "actions-2"); + cy.get("@actions").eq(1).as("overflowButton").should("have.attr", "icon", "overflow"); + cy.get("@actions").eq(2).should("have.attr", "name", "actions-1"); + cy.get("@overflowButton").realClick(); + cy.wait(200); + cy.get("[ui5-menu-item]").as("menuItems").should("have.length", 2); + cy.get("@menuItems").eq(0).should("have.attr", "text", "Edit").and("have.attr", "icon", "edit"); + cy.get("@menuItems").eq(1).should("have.attr", "text", "Delete").and("have.attr", "icon", "delete"); + cy.get("@menuItems").eq(0).ui5MenuItemClick(); + cy.get("@rowActionClick").invoke("getCall", 2).its("args.0.detail.action.id").should("equal", "editAction"); + + cy.get("@table").invoke("attr", "row-action-count", "4"); + cy.get("@innerTable").should("have.css", "gridTemplateColumns", `${8 + 36 + 4 + 36 + 4 + 36 + 4 + 36 + 8}px`); + cy.get("@actions").should("have.length", 4); + cy.get("@actions").eq(0).should("have.attr", "name", "actions-2"); + cy.get("@actions").eq(1).should("have.attr", "name", "actions-3"); + cy.get("@actions").eq(2).should("have.attr", "name", "actions-4"); + cy.get("@actions").eq(3).should("have.attr", "name", "actions-1"); + + cy.get("@table").invoke("attr", "row-action-count", "5"); + cy.get("@innerTable").should("have.css", "gridTemplateColumns", `${8 + 36 + 4 + 36 + 4 + 36 + 4 + 36 + 4 + 36 + 8}px`); + cy.get("@actions").should("have.length", 4); + cy.get("@row1").find("[slot=actions-4],[slot=actions-1]").then($lastActions => { + const lastAction = $lastActions[0]; + const penultimateAction = $lastActions[1]; + const distanceBetweenLastActions = lastAction.getBoundingClientRect().left - penultimateAction.getBoundingClientRect().right; + return distanceBetweenLastActions > lastAction.clientWidth; + }).should("be.true"); + + cy.get("@table").invoke("attr", "row-action-count", "1"); + cy.get("@innerTable").should("have.css", "gridTemplateColumns", `${8 + 36 + 8}px`); + cy.get("@actions").should("have.length", 1); + cy.get("@actions").eq(0).should("have.attr", "icon", "overflow"); + }); + + it("tests that invisible actions occupy space for alignment", () => { + mountTable(3, ` + + + + + + `); + + cy.get("@row1").find("ui5-table-row-action").then($actions => { + const firstAction = $actions[0]; + const lastAction = $actions[2]; + const distanceBetweenActions = lastAction.getBoundingClientRect().left - firstAction.getBoundingClientRect().right; + return distanceBetweenActions > lastAction.clientWidth; + }).should("be.true"); + }); + + it("tests that avoiding overflow is more important than aligment", () => { + mountTable(3, ` + + + + + + + `); + + cy.get("@row1").shadow().find("#actions-cell").children().as("actions"); + cy.get("@actions").should("have.length", 2); + cy.get("@actions").eq(0).should("have.attr", "name", "actions-2"); + cy.get("@actions").eq(1).should("have.attr", "name", "actions-3"); + }); + + it("tests that the aligment of navigation is more important than avoiding overflow", () => { + mountTable(3, ` + + + + + + + `); + + cy.get("@row1").shadow().find("#actions-cell").children().as("actions"); + cy.get("@actions").should("have.length", 3); + cy.get("@actions").eq(0).should("have.attr", "name", "actions-2"); + cy.get("@actions").eq(1).as("overflowButton").should("have.attr", "icon", "overflow"); + cy.get("@actions").eq(2).should("have.attr", "name", "actions-1"); + + cy.get("@overflowButton").realClick(); + cy.wait(200); + cy.get("ui5-menu").should("have.length", 1); + cy.get("[ui5-menu-item]").as("menuItems").should("have.length", 2); + cy.get("@menuItems").eq(0).should("have.attr", "text", "Edit").and("have.attr", "icon", "edit"); + cy.get("@menuItems").eq(1).should("have.attr", "text", "Delete").and("have.attr", "icon", "delete"); + cy.get("@menuItems").eq(0).ui5MenuItemPress("Enter"); + cy.get("@rowActionClick").invoke("getCall", 0).its("args.0.detail.action.icon").should("equal", "edit"); + }); + }); +}); diff --git a/packages/main/src/Table.hbs b/packages/main/src/Table.hbs index c375dd082a3f..0d323fef700a 100644 --- a/packages/main/src/Table.hbs +++ b/packages/main/src/Table.hbs @@ -14,7 +14,7 @@ {{#unless rows.length}} - + {{#if nodata.length}} {{else}} diff --git a/packages/main/src/Table.ts b/packages/main/src/Table.ts index 4cb8981fb4e3..1fbbdd40695e 100644 --- a/packages/main/src/Table.ts +++ b/packages/main/src/Table.ts @@ -28,10 +28,11 @@ import BusyIndicator from "./BusyIndicator.js"; import TableCell from "./TableCell.js"; import { findVerticalScrollContainer, scrollElementIntoView, isFeature } from "./TableUtils.js"; import TableDragAndDrop from "./TableDragAndDrop.js"; +import type TableRowActionBase from "./TableRowActionBase.js"; import type TableVirtualizer from "./TableVirtualizer.js"; /** - * Interface for components that can be slotted inside the features slot of the ui5-table. + * Interface for components that can be slotted inside the `features` slot of the `ui5-table`. * * @public * @experimental @@ -50,7 +51,7 @@ interface ITableFeature extends UI5Element { } /** - * Interface for components that can be slotted inside the features slot of the ui5-table + * Interface for components that can be slotted inside the `features` slot of the `ui5-table` * and provide growing/data loading functionality. * @public * @experimental @@ -78,6 +79,17 @@ type TableRowClickEventDetail = { type TableMoveEventDetail = MoveEventDetail; +/** + * Fired when a row action is clicked. + * @param {TableRowActionBase} action The row action instance + * @param {TableRow} row The row instance + * @public + */ +type TableRowActionClickEventDetail = { + action: TableRowActionBase, + row: TableRow, +}; + /** * @class * @@ -181,7 +193,7 @@ type TableMoveEventDetail = MoveEventDetail; * @public */ @event("row-click", { - bubbles: true, + bubbles: false, }) /** @@ -221,16 +233,28 @@ type TableMoveEventDetail = MoveEventDetail; bubbles: true, }) +/** + * Fired when a row action is clicked. + * + * @param {TableRowActionBase} action The row action instance + * @since 2.6.0 + * @public + */ +@event("row-action-click", { + bubbles: false, +}) + class Table extends UI5Element { eventDetails!: { "row-click": TableRowClickEventDetail; "move-over": TableMoveEventDetail; "move": TableMoveEventDetail; + "row-action-click": TableRowActionClickEventDetail; } /** * Defines the rows of the component. * - * Note: Use ui5-table-row for the intended design. + * **Note:** Use `ui5-table-row` for the intended design. * * @public */ @@ -247,7 +271,7 @@ class Table extends UI5Element { /** * Defines the header row of the component. * - * Note: Use ui5-table-header-row for the intended design. + * **Note:** Use `ui5-table-header-row` for the intended design. * * @public */ @@ -314,7 +338,7 @@ class Table extends UI5Element { /** * Defines if the loading indicator should be shown. * - * Note: When the component is loading, it is non-interactive. + * **Note:** When the component is loading, it is not interactive. * @default false * @public */ @@ -335,6 +359,18 @@ class Table extends UI5Element { @property() stickyTop = "0"; + /** + * Defines the maximum number of row actions that is displayed, which determines the width of the row action column. + * + * **Note:** It is recommended to use a maximum of 3 row actions, as exceeding this limit may take up too much space on smaller screens. + * + * @default 0 + * @since 2.7.0 + * @public + */ + @property({ type: Number }) + rowActionCount = 0; + @property({ type: Number, noAttribute: true }) _invalidate = 0; @@ -380,13 +416,14 @@ class Table extends UI5Element { } onBeforeRendering(): void { - const renderNavigated = this._renderNavigated; this._renderNavigated = this.rows.some(row => row.navigated); - if (renderNavigated !== this._renderNavigated) { - this.rows.forEach(row => { - row._renderNavigated = this._renderNavigated; - }); + if (this.headerRow[0]) { + this.headerRow[0]._rowActionCount = this.rowActionCount; } + this.rows.forEach(row => { + row._renderNavigated = this._renderNavigated; + row._rowActionCount = this.rowActionCount; + }); this.style.setProperty(getScopedVarName("--ui5_grid_sticky_top"), this.stickyTop); this._refreshPopinState(); @@ -513,10 +550,15 @@ class Table extends UI5Element { return Boolean(feature.loadMore && feature.hasGrowingComponent && this._isFeature(feature)); } - _onRowPress(row: TableRow) { + _onRowClick(row: TableRow) { this.fireDecoratorEvent("row-click", { row }); } + _onRowActionClick(action: TableRowActionBase) { + const row = action.parentElement as TableRow; + this.fireDecoratorEvent("row-action-click", { action, row }); + } + get styles() { const virtualizer = this._getVirtualizer(); const headerStyleMap = this.headerRow?.[0]?.cells?.reduce((headerStyles, headerCell) => { @@ -555,9 +597,15 @@ class Table extends UI5Element { } return `minmax(${cell.width}, ${cell.width})`; })); + + if (this.rowActionCount > 0) { + widths.push(`calc(var(${getScopedVarName("--_ui5_button_base_min_width")}) * ${this.rowActionCount} + var(${getScopedVarName("--_ui5_table_row_actions_gap")}) * ${this.rowActionCount - 1} + var(${getScopedVarName("--_ui5_table_cell_horizontal_padding")}) * 2)`); + } + if (this._renderNavigated) { widths.push(`var(${getScopedVarName("--_ui5_table_navigated_cell_width")})`); } + return widths.join(" "); } @@ -632,6 +680,10 @@ class Table extends UI5Element { get dropIndicatorDOM(): DropIndicator | null { return this.shadowRoot!.querySelector("[ui5-drop-indicator]"); } + + get _hasRowActions() { + return this.rowActionCount > 0; + } } Table.define(); @@ -643,4 +695,5 @@ export type { ITableGrowing, TableRowClickEventDetail, TableMoveEventDetail, + TableRowActionClickEventDetail, }; diff --git a/packages/main/src/TableCell.ts b/packages/main/src/TableCell.ts index 68725811ad8b..04a34f863bb5 100644 --- a/packages/main/src/TableCell.ts +++ b/packages/main/src/TableCell.ts @@ -34,8 +34,8 @@ class TableCell extends TableCellBase { super.onBeforeRendering(); if (this.horizontalAlign) { this.style.justifyContent = this.horizontalAlign; - } else { - this.style.justifyContent = `var(--horizontal-align-${(this as any)._individualSlot})`; + } else if (this._individualSlot) { + this.style.justifyContent = `var(--horizontal-align-${this._individualSlot})`; } } diff --git a/packages/main/src/TableCellBase.ts b/packages/main/src/TableCellBase.ts index 3a830028cf47..baa160d59ca7 100644 --- a/packages/main/src/TableCellBase.ts +++ b/packages/main/src/TableCellBase.ts @@ -29,18 +29,18 @@ abstract class TableCellBase extends UI5Element { @slot({ type: Node, "default": true }) content!: Array; - @property({ type: Boolean }) - _popin = false; - /** * Determines the horizontal alignment of table cells. - * **Note:** All values valid for justify-content can be used, not just the ones inside the enumeration. + * * @default undefined * @public */ @property() horizontalAlign?: `${TableCellHorizontalAlign}`; + @property({ type: Boolean }) + _popin = false; + protected ariaRole: string = "gridcell"; @i18n("@ui5/webcomponents") diff --git a/packages/main/src/TableExtension.ts b/packages/main/src/TableExtension.ts index 5071f1a1d400..29bd5d7bd01f 100644 --- a/packages/main/src/TableExtension.ts +++ b/packages/main/src/TableExtension.ts @@ -1,5 +1,5 @@ /** - * Base class for the extensions of ui5-table components. + * Base class for the extensions of `ui5-table` components. * @private */ export default abstract class TableExtension {} diff --git a/packages/main/src/TableHeaderCell.ts b/packages/main/src/TableHeaderCell.ts index dbf1fa364405..4b3888ca79fe 100644 --- a/packages/main/src/TableHeaderCell.ts +++ b/packages/main/src/TableHeaderCell.ts @@ -90,8 +90,10 @@ class TableHeaderCell extends TableCellBase { onBeforeRendering() { super.onBeforeRendering(); - // overwrite setting of TableCellBase so that the TableHeaderCell always uses the slot variable - this.style.justifyContent = `var(--horizontal-align-${this._individualSlot})`; + if (this._individualSlot) { + // overwrite setting of TableCellBase so that the TableHeaderCell always uses the slot variable + this.style.justifyContent = `var(--horizontal-align-${this._individualSlot})`; + } } } diff --git a/packages/main/src/TableHeaderRow.hbs b/packages/main/src/TableHeaderRow.hbs index de3218f7bed7..028689013512 100644 --- a/packages/main/src/TableHeaderRow.hbs +++ b/packages/main/src/TableHeaderRow.hbs @@ -19,6 +19,10 @@ {{/each}} +{{#if _hasRowActions}} + +{{/if}} + {{#if _popinCells.length}} {{/if}} diff --git a/packages/main/src/TableHeaderRow.ts b/packages/main/src/TableHeaderRow.ts index c839e7977c1e..d88e30ba53ef 100644 --- a/packages/main/src/TableHeaderRow.ts +++ b/packages/main/src/TableHeaderRow.ts @@ -8,6 +8,7 @@ import TableHeaderCell from "./TableHeaderCell.js"; import { TABLE_SELECTION, TABLE_ROW_POPIN, + TABLE_ROW_ACTIONS, } from "./generated/i18n/i18n-defaults.js"; /** @@ -85,6 +86,10 @@ class TableHeaderRow extends TableRowBase { return true; } + get _hasRowActions() { + return this._table ? this._table._hasRowActions : false; + } + get _isSelectable() { return this._isMultiSelect; } @@ -100,6 +105,9 @@ class TableHeaderRow extends TableRowBase { get _i18nRowPopin() { return TableRowBase.i18nBundle.getText(TABLE_ROW_POPIN); } + get _i18nRowActions() { + return TableRowBase.i18nBundle.getText(TABLE_ROW_ACTIONS); + } } TableHeaderRow.define(); diff --git a/packages/main/src/TableRow.hbs b/packages/main/src/TableRow.hbs index d96044c38157..3187e576809b 100644 --- a/packages/main/src/TableRow.hbs +++ b/packages/main/src/TableRow.hbs @@ -21,12 +21,31 @@ {{/each}} -{{#if _renderNavigated}} - - +{{#if _hasRowActions}} + + {{#each _flexibleActions}} + + {{/each}} + {{#if _hasOverflowActions}} + + + {{/if}} + {{#each _fixedActions}} + + {{/each}} {{/if}} +{{#if _renderNavigated}} + + + +{{/if}} + {{#if _popinCells.length}} {{#each _popinCells}} diff --git a/packages/main/src/TableRow.ts b/packages/main/src/TableRow.ts index 9990a6ebd021..934de44daa30 100644 --- a/packages/main/src/TableRow.ts +++ b/packages/main/src/TableRow.ts @@ -3,11 +3,14 @@ import slot from "@ui5/webcomponents-base/dist/decorators/slot.js"; import property from "@ui5/webcomponents-base/dist/decorators/property.js"; import { isEnter } from "@ui5/webcomponents-base/dist/Keys.js"; import getActiveElement from "@ui5/webcomponents-base/dist/util/getActiveElement.js"; +import Button from "./Button.js"; +import RadioButton from "./RadioButton.js"; import TableRowTemplate from "./generated/templates/TableRowTemplate.lit.js"; import TableRowBase from "./TableRowBase.js"; import TableRowCss from "./generated/themes/TableRow.css.js"; import TableCell from "./TableCell.js"; -import RadioButton from "./RadioButton.js"; +import type TableRowActionBase from "./TableRowActionBase.js"; +import "@ui5/webcomponents-icons/dist/overflow.js"; /** * @class @@ -30,7 +33,7 @@ import RadioButton from "./RadioButton.js"; tag: "ui5-table-row", styles: [TableRowBase.styles, TableRowCss], template: TableRowTemplate, - dependencies: [...TableRowBase.dependencies, RadioButton, TableCell], + dependencies: [...TableRowBase.dependencies, RadioButton, TableCell, Button], }) class TableRow extends TableRowBase { /** @@ -51,6 +54,20 @@ class TableRow extends TableRowBase { }) cells!: Array; + /** + * Defines the actions of the component. + * + * **Note:** Use `ui5-table-row-action` or `ui5-table-row-action-navigation` for the intended design. + * + * @since 2.7.0 + * @public + */ + @slot({ + type: HTMLElement, + individualSlots: true, + }) + actions!: Array; + /** * Unique identifier of the row. * @@ -61,7 +78,7 @@ class TableRow extends TableRowBase { rowKey = ""; /** - * Defines the position of the row respect to the total number of rows within the table when the ui5-table-virtualizer feature is used. + * Defines the position of the row respect to the total number of rows within the table when the `ui5-table-virtualizer` feature is used. * * @default -1 * @since 2.5.0 @@ -133,13 +150,13 @@ class TableRow extends TableRowBase { if (eventOrigin === this && this._isInteractive && isEnter(e)) { this.toggleAttribute("_active", true); - this._table?._onRowPress(this); + this._table?._onRowClick(this); } } _onclick() { if (this._isInteractive && this === getActiveElement()) { - this._table?._onRowPress(this); + this._table?._onRowClick(this); } } @@ -151,9 +168,70 @@ class TableRow extends TableRowBase { this.removeAttribute("_active"); } + _onOverflowButtonClick(e: PointerEvent) { + const ctor = this.actions[0].constructor as typeof TableRowActionBase; + ctor.showMenu(this._overflowActions, e.target as HTMLElement); + } + get _isInteractive() { return this.interactive; } + + get _hasRowActions() { + return this._rowActionCount > 0 && this.actions.some(action => action.isFixedAction() || !action.invisible); + } + + get _hasOverflowActions() { + let renderedActionsCount = 0; + return this.actions.some(action => { + if (action.isFixedAction() || !action.invisible) { + renderedActionsCount++; + } + return renderedActionsCount > this._rowActionCount; + }); + } + + get _flexibleActions() { + const flexibleActions = this.actions.filter(action => !action.isFixedAction()); + const fixedActionsCount = this.actions.length - flexibleActions.length; + let maxFlexibleActionsCount = this._rowActionCount - fixedActionsCount; + if (maxFlexibleActionsCount < 1) { + return []; // fixed actions occupy all the available space + } + if (flexibleActions.length <= maxFlexibleActionsCount) { + return flexibleActions; // all actions fit the available space + } + + const visibleFlexibleActions = flexibleActions.filter(action => !action.invisible); + if (visibleFlexibleActions.length > maxFlexibleActionsCount) { + maxFlexibleActionsCount--; // preserve space for the overflow button + } + + return visibleFlexibleActions.slice(0, maxFlexibleActionsCount); + } + + get _fixedActions() { + let maxFixedActionsCount = this._rowActionCount; + if (this._hasOverflowActions) { + maxFixedActionsCount--; + } + + const fixedActions = this.actions.filter(action => action.isFixedAction()); + return fixedActions.slice(0, maxFixedActionsCount); + } + + get _overflowActions() { + const fixedActions = this._fixedActions; + const flexibleActions = this._flexibleActions; + const overflowActions: Array = []; + this.actions.forEach(action => { + if (!action.invisible && !fixedActions.includes(action) && !flexibleActions.includes(action)) { + overflowActions.push(action); + } + }); + + return overflowActions; + } } TableRow.define(); diff --git a/packages/main/src/TableRowAction.ts b/packages/main/src/TableRowAction.ts new file mode 100644 index 000000000000..d94f1587f75a --- /dev/null +++ b/packages/main/src/TableRowAction.ts @@ -0,0 +1,61 @@ +import customElement from "@ui5/webcomponents-base/dist/decorators/customElement.js"; +import property from "@ui5/webcomponents-base/dist/decorators/property.js"; +import TableRowActionBase from "./TableRowActionBase.js"; + +/** + * @class + * The `TableRowAction` class defines a row action for table rows. + * @constructor + * @extends TableRowActionBase + * @since 2.7.0 + * @public + */ +@customElement({ tag: "ui5-table-row-action" }) + +class TableRowAction extends TableRowActionBase { + /** + * Defines the icon of the row action. + * + * **Note:** For row actions to work properly, this property is mandatory. + * + * **Note:** SAP-icons font provides numerous built-in icons. To find all the available icons, see the + * [Icon Explorer](https://sdk.openui5.org/test-resources/sap/m/demokit/iconExplorer/webapp/index.html). + * + * @default "" + * @public + */ + @property() + icon = ""; + + /** + * Defines the text of the row action. + * + * **Note:** For row actions to work properly, this property is mandatory. + * + * @default "" + * @public + */ + @property() + text = ""; + + /** + * Defines the disabled state of the row action. + * + * @default false + * @public + */ + @property({ type: Boolean }) + disabled = false; + + getRenderInfo() { + return { + text: this.text, + icon: this.icon, + interactive: true, + }; + } +} + +TableRowAction.define(); + +export default TableRowAction; diff --git a/packages/main/src/TableRowActionBase.hbs b/packages/main/src/TableRowActionBase.hbs new file mode 100644 index 000000000000..065267d6927e --- /dev/null +++ b/packages/main/src/TableRowActionBase.hbs @@ -0,0 +1,17 @@ +{{#if invisible}} +
+{{else if _isInteractive}} + + +{{else}} + + +{{/if}} \ No newline at end of file diff --git a/packages/main/src/TableRowActionBase.ts b/packages/main/src/TableRowActionBase.ts new file mode 100644 index 000000000000..f8e158133aa5 --- /dev/null +++ b/packages/main/src/TableRowActionBase.ts @@ -0,0 +1,117 @@ +import UI5Element from "@ui5/webcomponents-base/dist/UI5Element.js"; +import { customElement, property } from "@ui5/webcomponents-base/dist/decorators.js"; +import litRender from "@ui5/webcomponents-base/dist/renderer/LitRenderer.js"; +import TableRowActionBaseTemplate from "./generated/templates/TableRowActionBaseTemplate.lit.js"; +import TableRowActionBaseStyles from "./generated/themes/TableRowActionBase.css.js"; +import i18n from "@ui5/webcomponents-base/dist/decorators/i18n.js"; +import Icon from "./Icon.js"; +import Button from "./Button.js"; +import type Menu from "./Menu.js"; +import type MenuItem from "./MenuItem.js"; +import type Table from "./Table.js"; +import type TableRow from "./TableRow.js"; +import type TableRowAction from "./TableRowAction.js"; +import type I18nBundle from "@ui5/webcomponents-base/dist/i18nBundle.js"; + +let MenuConstructor: new () => Menu; +let MenuItemConstructor: new () => MenuItem; + +/** + * @class + * The `TableRowActionBase` class serves as a foundation for table row actions. + * @constructor + * @abstract + * @extends UI5Element + * @since 2.7.0 + * @public + */ +@customElement({ + renderer: litRender, + styles: TableRowActionBaseStyles, + template: TableRowActionBaseTemplate, + dependencies: [Button, Icon], +}) + +abstract class TableRowActionBase extends UI5Element { + /** + * Defines the visibility of the row action. + * + * **Note:** Invisible row actions still take up space, allowing to hide the action while maintaining its position. + * + * @default false + * @public + */ + @property({ type: Boolean }) + invisible = false; + + @i18n("@ui5/webcomponents") + static i18nBundle: I18nBundle; + + private static _menu: Menu; + private static _menuItems = new WeakMap(); + static async showMenu(actions: TableRowActionBase[], opener: HTMLElement) { + if (!MenuConstructor) { + [MenuConstructor, MenuItemConstructor] = await Promise.all([ + import("./Menu.js").then(module => module.default), + import("./MenuItem.js").then(module => module.default), + ]); + } + + if (!this._menu || !this._menu.isConnected) { + this._menu = new MenuConstructor(); + this._menu.addEventListener("item-click", ((e: CustomEvent) => { + const menuItem = e.detail.item as MenuItem; + const rowAction = this._menuItems.get(menuItem) as TableRowAction; + rowAction._onActionClick(); + }) as EventListener); + document.body.append(this._menu); + } + + const menuItems = actions.map(action => { + const menuItem = new MenuItemConstructor(); + menuItem.icon = action._icon; + menuItem.text = action._text; + menuItem.disabled = !action._isInteractive; + this._menuItems.set(menuItem, action); + return menuItem; + }); + + this._menu.replaceChildren(...menuItems); + this._menu.opener = opener; + this._menu.open = true; + } + + abstract getRenderInfo(): { + text: string; + icon: string; + interactive: boolean; + }; + + isFixedAction() { + return false; + } + + onEnterDOM(): void { + this.toggleAttribute("_fixed", this.isFixedAction()); + } + + _onActionClick() { + const row = this.parentElement as TableRow; + const table = row.parentElement as Table; + table._onRowActionClick(this); + } + + get _text() { + return this.getRenderInfo().text; + } + + get _icon() { + return this.getRenderInfo().icon; + } + + get _isInteractive() { + return this.getRenderInfo().interactive; + } +} + +export default TableRowActionBase; diff --git a/packages/main/src/TableRowActionNavigation.ts b/packages/main/src/TableRowActionNavigation.ts new file mode 100644 index 000000000000..9a27657e7aca --- /dev/null +++ b/packages/main/src/TableRowActionNavigation.ts @@ -0,0 +1,46 @@ +import customElement from "@ui5/webcomponents-base/dist/decorators/customElement.js"; +import property from "@ui5/webcomponents-base/dist/decorators/property.js"; +import TableRowActionBase from "./TableRowActionBase.js"; +import { TABLE_NAVIGATION } from "./generated/i18n/i18n-defaults.js"; +import "@ui5/webcomponents-icons/dist/navigation-right-arrow.js"; + +/** + * @class + * The `TableRowActionNavigation` class defines a navigation actio‚n for table rows. + * @constructor + * @extends TableRowActionBase + * @since 2.7.0 + * @public + */ +@customElement({ tag: "ui5-table-row-action-navigation" }) + +class TableRowActionNavigation extends TableRowActionBase { + /** + * Defines the interactive state of the navigation action. + * + * @default false + * @public + */ + @property({ type: Boolean }) + interactive = false; + + getRenderInfo() { + return { + text: this._i18nNavigation, + icon: "navigation-right-arrow", + interactive: this.interactive, + }; + } + + isFixedAction() { + return true; + } + + get _i18nNavigation() { + return TableRowActionBase.i18nBundle.getText(TABLE_NAVIGATION); + } +} + +TableRowActionNavigation.define(); + +export default TableRowActionNavigation; diff --git a/packages/main/src/TableRowBase.ts b/packages/main/src/TableRowBase.ts index 17aeee886e30..012d9fe88bf3 100644 --- a/packages/main/src/TableRowBase.ts +++ b/packages/main/src/TableRowBase.ts @@ -34,6 +34,9 @@ abstract class TableRowBase extends UI5Element { @property({ type: Number, noAttribute: true }) _invalidate = 0; + @property({ type: Number, noAttribute: true }) + _rowActionCount = 0; + @i18n("@ui5/webcomponents") static i18nBundle: I18nBundle; diff --git a/packages/main/src/TableVirtualizer.ts b/packages/main/src/TableVirtualizer.ts index e57acf9fccc7..096496b3fd14 100644 --- a/packages/main/src/TableVirtualizer.ts +++ b/packages/main/src/TableVirtualizer.ts @@ -80,7 +80,7 @@ class TableVirtualizer extends UI5Element implements ITableFeature { /** * Defines the height of the rows in the table. * - * **Note:** This property is mandatory for the virtualization to work properly. + * **Note:** For virtualization to work properly, this property is mandatory. * * @default 45 * @public @@ -91,7 +91,7 @@ class TableVirtualizer extends UI5Element implements ITableFeature { /** * Defines the total count of rows in the table. * - * **Note:** This property is mandatory for the virtualization to work properly. + * **Note:** For virtualization to work properly, this property is mandatory. * * @default 100 * @public diff --git a/packages/main/src/bundle.esm.ts b/packages/main/src/bundle.esm.ts index 5569c81e4993..79440bd881f2 100644 --- a/packages/main/src/bundle.esm.ts +++ b/packages/main/src/bundle.esm.ts @@ -59,6 +59,8 @@ import TableHeaderRow from "./TableHeaderRow.js"; import TableGrowing from "./TableGrowing.js"; import TableSelection from "./TableSelection.js"; import TableVirtualizer from "./TableVirtualizer.js"; +import TableRowAction from "./TableRowAction.js"; +import TableRowActionNavigation from "./TableRowActionNavigation.js"; import Icon from "./Icon.js"; import Input from "./Input.js"; import SuggestionItemCustom from "./SuggestionItemCustom.js"; diff --git a/packages/main/src/i18n/messagebundle.properties b/packages/main/src/i18n/messagebundle.properties index 831c9093d016..ca9dfc3623cd 100644 --- a/packages/main/src/i18n/messagebundle.properties +++ b/packages/main/src/i18n/messagebundle.properties @@ -606,4 +606,8 @@ TABLE_ROW_POPIN=Row Popin #XTXT: Text for the growing button TABLE_MORE=More #XACT: ARIA description for the growing button -TABLE_MORE_DESCRIPTION=Load more rows by pressing Enter or Space \ No newline at end of file +TABLE_MORE_DESCRIPTION=To load more rows, press Enter or Space +#XACT: ARIA description for the row action of the header cell +TABLE_ROW_ACTIONS=Row Actions +#XACT: ARIA description for the row action navigation +TABLE_NAVIGATION=Navigation diff --git a/packages/main/src/themes/TableCellBase.css b/packages/main/src/themes/TableCellBase.css index df6912f2afee..b88fc72520a8 100644 --- a/packages/main/src/themes/TableCellBase.css +++ b/packages/main/src/themes/TableCellBase.css @@ -6,7 +6,7 @@ max-width: 100%; overflow: clip; overflow-clip-margin: content-box; - padding: var(--_ui5_table_cell_padding); + padding: var(--_ui5_table_cell_vertical_padding) var(--_ui5_table_cell_horizontal_padding); box-sizing: border-box; } diff --git a/packages/main/src/themes/TableRow.css b/packages/main/src/themes/TableRow.css index 1c5a409c07bc..75064c5e9bd5 100644 --- a/packages/main/src/themes/TableRow.css +++ b/packages/main/src/themes/TableRow.css @@ -1,73 +1,96 @@ -:host { - background: var(--sapList_Background); -} - -:host([position]) { - height: var(--row-height); - overflow: clip; -} - -:host([aria-selected=true]) { - background-color: var(--sapList_SelectionBackgroundColor); - border-bottom: var(--sapList_BorderWidth) solid var(--sapList_SelectionBorderColor); -} - -:host([_interactive]) { - cursor: pointer; -} - -@media (hover: hover) { - :host([_interactive]:hover) { - background: var(--sapList_Hover_Background); - } - :host([_interactive][aria-selected=true]:hover) { - background: var(--sapList_Hover_SelectionBackground); - } -} - -:host([_interactive]:active), -:host([_interactive][_active]), -:host([_interactive][aria-selected=true]:active), -:host([_interactive][aria-selected=true][_active]) { - background: var(--sapList_Active_Background); -} - -#popin-cell { - align-content: initial; - flex-direction: column; - grid-column: 1 / -1; -} - -#navigated-cell { - position: relative; - overflow: visible; - grid-row: span 2; - min-width: 0; - padding: 0; - position: sticky; - right: 0; -} - -:dir(rtl)#navigated-cell { - left: 0; -} - -:host([navigated]) #navigated { - position: absolute; - inset: 0; - background-color: var(--sapList_SelectionBorderColor); -} - -:host([tabindex]:focus) #navigated { - transform: translateX(calc(var(--_ui5_table_navigated_cell_width) * -1)); - bottom: 2px; - top: 3px; -} - -:host([tabindex]:focus) #navigated:dir(rtl) { - transform: translateX(var(--_ui5_table_navigated_cell_width)); -} - -:host([navigated]) #popin-cell { - grid-column: 1 / -2; -} +:host { + background: var(--sapList_Background); +} + +:host([position]) { + height: var(--row-height); + overflow: clip; +} + +:host([aria-selected=true]) { + background-color: var(--sapList_SelectionBackgroundColor); + border-bottom: var(--sapList_BorderWidth) solid var(--sapList_SelectionBorderColor); +} + +:host([_interactive]) { + cursor: pointer; +} + +@media (hover: hover) { + :host([_interactive]:hover) { + background: var(--sapList_Hover_Background); + } + :host([_interactive][aria-selected=true]:hover) { + background: var(--sapList_Hover_SelectionBackground); + } +} + +:host([_interactive]:active), +:host([_interactive][_active]), +:host([_interactive][aria-selected=true]:active), +:host([_interactive][aria-selected=true][_active]) { + background: var(--sapList_Active_Background); +} + +#popin-cell { + align-content: initial; + flex-direction: column; + grid-column: 1 / -1; +} + +#navigated-cell { + position: sticky; + right: 0; + overflow: visible; + grid-row: span 2; + min-width: 0; + padding: 0; + background: inherit; +} + +:dir(rtl)#navigated-cell { + left: 0; +} + +:host([navigated]) #navigated { + position: absolute; + inset: 0; + background-color: var(--sapList_SelectionBorderColor); +} + +:host([tabindex]:focus) #navigated { + transform: translateX(calc(var(--_ui5_table_navigated_cell_width) * -1)); + bottom: 2px; + top: 3px; +} + +:host([tabindex]:focus) #navigated:dir(rtl) { + transform: translateX(var(--_ui5_table_navigated_cell_width)); +} + +:host([tabindex]:focus) #navigated-cell { + clip-path: inset(var(--sapContent_FocusWidth) var(--sapContent_FocusWidth) var(--sapContent_FocusWidth) calc(var(--_ui5_table_navigated_cell_width) * -1)); +} + +:host([tabindex]:focus) #navigated-cell:dir(rtl) { + clip-path: inset(var(--sapContent_FocusWidth) calc(var(--_ui5_table_navigated_cell_width) * -1) var(--sapContent_FocusWidth) var(--sapContent_FocusWidth)); +} + +:host([navigated]) #popin-cell { + grid-column: 1 / -2; +} + +#actions-cell { + display: flex; + align-items: center; + gap: var(--_ui5_table_row_actions_gap); +} + +#actions-cell:has(+ #navigated-cell) { + right: var(--_ui5_table_navigated_cell_width); + overflow: auto; +} + +:dir(rtl)#actions-cell:has(+ #navigated-cell) { + left: var(--_ui5_table_navigated_cell_width); +} \ No newline at end of file diff --git a/packages/main/src/themes/TableRowActionBase.css b/packages/main/src/themes/TableRowActionBase.css new file mode 100644 index 000000000000..d211f02dc627 --- /dev/null +++ b/packages/main/src/themes/TableRowActionBase.css @@ -0,0 +1,13 @@ +:host([invisible]) { + display: block; + width: var(--_ui5_button_base_min_width); +} + +:host([_fixed]) { + margin-inline-start: auto; +} + +[ui5-icon] { + display: flex; + width: var(--_ui5_button_base_min_width); +} \ No newline at end of file diff --git a/packages/main/src/themes/TableRowBase.css b/packages/main/src/themes/TableRowBase.css index ee566aaaf65d..8bbe898f261a 100644 --- a/packages/main/src/themes/TableRowBase.css +++ b/packages/main/src/themes/TableRowBase.css @@ -14,6 +14,11 @@ outline-offset: calc(-1 * var(--sapContent_FocusWidth)); } +:host([tabindex]:focus) #selection-cell, +:host([tabindex]:focus) #actions-cell { + clip-path: inset(var(--sapContent_FocusWidth)); /* focus outline should not overlap sticky cells */ +} + #selection-cell { padding: 0; left: 0; @@ -27,10 +32,13 @@ vertical-align: middle; } -/** Focus outline for the selection cell */ -:host([tabindex]:focus) #selection-cell { - outline: none; - box-shadow: var(--_ui5_table_shadow_border_top), - var(--_ui5_table_shadow_border_left), - var(--_ui5_table_shadow_border_bottom); /* There is a 1px difference between row and cell, therefore the outline is also 1px difference between their outline offsets */ +#actions-cell { + position: sticky; + right: 0; + background-color: inherit; + flex-wrap: nowrap; } + +:dir(rtl)#actions-cell { + left: 0; +} \ No newline at end of file diff --git a/packages/main/src/themes/base/Table-parameters.css b/packages/main/src/themes/base/Table-parameters.css index 7cf2b221d514..2efe5c4f3f85 100644 --- a/packages/main/src/themes/base/Table-parameters.css +++ b/packages/main/src/themes/base/Table-parameters.css @@ -2,13 +2,7 @@ --_ui5_table_cell_valign: center; --_ui5_table_cell_min_width: 2.75rem; --_ui5_table_navigated_cell_width: 0.25rem; - --_ui5_table_shadow_border_left: inset var(--sapContent_FocusWidth) 0 var(--sapContent_FocusColor); - --_ui5_table_shadow_border_right: inset calc(-1 * var(--sapContent_FocusWidth)) 0 var(--sapContent_FocusColor); - --_ui5_table_shadow_border_top: inset 0 var(--sapContent_FocusWidth) var(--sapContent_FocusColor); - --_ui5_table_shadow_border_bottom: inset 0 -1px var(--sapContent_FocusColor); -} - -[dir="rtl"] { - --_ui5_table_shadow_border_left: inset calc(-1 * var(--sapContent_FocusWidth)) 0 var(--sapContent_FocusColor); - --_ui5_table_shadow_border_right: inset var(--sapContent_FocusWidth) 0 var(--sapContent_FocusColor); + --_ui5_table_cell_horizontal_padding: 0.5rem; + --_ui5_table_cell_vertical_padding: 0.25rem; + --_ui5_table_row_actions_gap: 0.25rem; } \ No newline at end of file diff --git a/packages/main/test/pages/TableRowActions.html b/packages/main/test/pages/TableRowActions.html new file mode 100644 index 000000000000..85a264dd3554 --- /dev/null +++ b/packages/main/test/pages/TableRowActions.html @@ -0,0 +1,90 @@ + + + + + Table (in development) + + + + + + + + + + My Products + + + + + + + Product + Supplier + Dimensions + Weight + Price + + + Notebook Basic 15
HT-1000
+ Very Best Screens + 30 x 18 x 3 cm + 4.2 KG + 399.99 EUR + +
+ + Notebook Basic 15
HT-1000
+ Very Best Screens + 30 x 18 x 3 cm + 4.2 KG + 399.99 EUR + + + + + + +
+ + Notebook Basic 15
HT-1000
+ Very Best Screens + 30 x 18 x 3 cm + 4.2 KG + 399.99 EUR + + + +
+ + Notebook Basic 15
HT-1000
+ Very Best Screens + 30 x 18 x 3 cm + 4.2 KG + 399.99 EUR + + +
+
+ + + + + + \ No newline at end of file diff --git a/packages/website/docs/_components_pages/main/Table/TableRowAction.mdx b/packages/website/docs/_components_pages/main/Table/TableRowAction.mdx new file mode 100644 index 000000000000..4e31cba8cb97 --- /dev/null +++ b/packages/website/docs/_components_pages/main/Table/TableRowAction.mdx @@ -0,0 +1,14 @@ +--- +slug: ../../TableRowAction +sidebar_class_name: newComponentBadge expComponentBadge +--- + +import RowAction from "../../../_samples/main/Table/RowAction/RowAction.md"; + +<%COMPONENT_OVERVIEW%> + +<%COMPONENT_METADATA%> + +## Basic Sample + + diff --git a/packages/website/docs/_components_pages/main/Table/TableRowActionNavigation.mdx b/packages/website/docs/_components_pages/main/Table/TableRowActionNavigation.mdx new file mode 100644 index 000000000000..fb4ed9cb8d37 --- /dev/null +++ b/packages/website/docs/_components_pages/main/Table/TableRowActionNavigation.mdx @@ -0,0 +1,14 @@ +--- +slug: ../../TableRowActionNavigation +sidebar_class_name: newComponentBadge expComponentBadge +--- + +import RowActionNavigation from "../../../_samples/main/Table/RowActionNavigation/RowActionNavigation.md"; + +<%COMPONENT_OVERVIEW%> + +<%COMPONENT_METADATA%> + +## Basic Sample + + diff --git a/packages/website/docs/_samples/main/Table/RowAction/RowAction.md b/packages/website/docs/_samples/main/Table/RowAction/RowAction.md new file mode 100644 index 000000000000..7aa4602677fe --- /dev/null +++ b/packages/website/docs/_samples/main/Table/RowAction/RowAction.md @@ -0,0 +1,10 @@ +import html from '!!raw-loader!./sample.html'; +import js from '!!raw-loader!./main.js'; + +The `ui5-table-row-action` component lets you incorporate interactive elements into table rows, enabling users to take actions directly related to each row. + +The `row-action-count` property of the `ui5-table` component determines the width of the row action column. A maximum value of `3` is recommended, as exceeding this limit may take up too much space on smaller screens. If the number of row actions exceeds the `row-action-count`, an overflow button will appear, providing access to the additional actions. + +The `invisible` property of row actions allows you to hide specific row actions while preserving their space. This can be useful for consistent alignment of row actions across several rows. + + diff --git a/packages/website/docs/_samples/main/Table/RowAction/main.js b/packages/website/docs/_samples/main/Table/RowAction/main.js new file mode 100644 index 000000000000..01afe72402a5 --- /dev/null +++ b/packages/website/docs/_samples/main/Table/RowAction/main.js @@ -0,0 +1,41 @@ +import "@ui5/webcomponents/dist/Table.js"; +import "@ui5/webcomponents/dist/TableHeaderRow.js"; +import "@ui5/webcomponents/dist/TableHeaderCell.js"; +import "@ui5/webcomponents/dist/TableRow.js"; +import "@ui5/webcomponents/dist/TableCell.js"; +import "@ui5/webcomponents/dist/TableRowAction.js"; +import "@ui5/webcomponents/dist/TableRowActionNavigation.js"; +import "@ui5/webcomponents/dist/Label.js"; +import "@ui5/webcomponents-icons/dist/add.js"; +import "@ui5/webcomponents-icons/dist/edit.js"; +import "@ui5/webcomponents-icons/dist/share.js"; +import "@ui5/webcomponents-icons/dist/heart.js"; +import "@ui5/webcomponents-icons/dist/delete.js"; + +const handlers = { + onAdd: (row) => { + console.log(`Add action of row ${row.rowKey} is clicked`); + }, + onEdit: (row) => { + console.log(`Edit action of row ${row.rowKey} is clicked`); + }, + onLike: (row) => { + console.log(`Like action of row ${row.rowKey} is clicked`); + }, + onDelete: (row) => { + console.log(`Delete action of row ${row.rowKey} is clicked`); + }, + onShare: (row) => { + console.log(`Share action of row ${row.rowKey} is clicked`); + }, + onNavigate: (row) => { + console.log(`Navigate action of row ${row.rowKey} is clicked`); + }, +}; + +const table = document.getElementById("table"); +table.addEventListener("row-action-click", (e) => { + const { action, row } = e.detail; + const handler = action.getAttribute("handler"); + handlers[handler]?.(row); +}) \ No newline at end of file diff --git a/packages/website/docs/_samples/main/Table/RowAction/sample.html b/packages/website/docs/_samples/main/Table/RowAction/sample.html new file mode 100644 index 000000000000..9cdd1e19d887 --- /dev/null +++ b/packages/website/docs/_samples/main/Table/RowAction/sample.html @@ -0,0 +1,65 @@ + + + + + + + + Sample + + + +
+ + + + + + Product + Supplier + Price + + + Notebook Basic 15
HT-1000
+ Very Best Screens + 899.99 EUR + +
+ + + Astro Laptop 216
HT-1251
+ Technocom + 679.99 EUR + + + + + + +
+ + + Benda Laptop 1408
HT-6102
+ Ultrasonic United + 699.99 EUR + + + +
+ + Broad Screen 22HD
HT-1255
+ Speaker Experts + 399.99 EUR + + +
+ +
+ + +
+ + + + + diff --git a/packages/website/docs/_samples/main/Table/RowActionNavigation/RowActionNavigation.md b/packages/website/docs/_samples/main/Table/RowActionNavigation/RowActionNavigation.md new file mode 100644 index 000000000000..f0c5cbe85fec --- /dev/null +++ b/packages/website/docs/_samples/main/Table/RowActionNavigation/RowActionNavigation.md @@ -0,0 +1,10 @@ +import html from '!!raw-loader!./sample.html'; +import js from '!!raw-loader!./main.js'; + +By default, the `ui5-table-row-action-navigation` component displays a dedicated navigation icon to indicate that a row is navigable. The icon appears on the right side of the row and is the last item to move into the overflow menu. Therefore, if you want to show additional row actions along with the `ui5-table-row-action-navigation`, the `row-action-count` property of the `ui5-table` must be set to at least `2`. This ensures that the `ui5-table-row-action-navigation` component never appears in the overflow menu. + +If the `interactive` property is set to `true`, the navigation icon appears as a button, and clicking it triggers the table’s `row-action-click` event. + +The `invisible` property allows you to hide specific navigation actions. This property is useful for ensuring a consistent layout by displaying the navigation column. + + diff --git a/packages/website/docs/_samples/main/Table/RowActionNavigation/main.js b/packages/website/docs/_samples/main/Table/RowActionNavigation/main.js new file mode 100644 index 000000000000..dc31af54d952 --- /dev/null +++ b/packages/website/docs/_samples/main/Table/RowActionNavigation/main.js @@ -0,0 +1,13 @@ +import "@ui5/webcomponents/dist/Table.js"; +import "@ui5/webcomponents/dist/TableHeaderRow.js"; +import "@ui5/webcomponents/dist/TableHeaderCell.js"; +import "@ui5/webcomponents/dist/TableRow.js"; +import "@ui5/webcomponents/dist/TableCell.js"; +import "@ui5/webcomponents/dist/TableRowActionNavigation.js"; +import "@ui5/webcomponents/dist/Label.js"; + +const table = document.getElementById("table"); +table.addEventListener("row-action-click", (e) => { + const row = e.detail.row; + console.log(`Navigate action of row ${row.rowKey} is clicked`); +}); \ No newline at end of file diff --git a/packages/website/docs/_samples/main/Table/RowActionNavigation/sample.html b/packages/website/docs/_samples/main/Table/RowActionNavigation/sample.html new file mode 100644 index 000000000000..a167178d6666 --- /dev/null +++ b/packages/website/docs/_samples/main/Table/RowActionNavigation/sample.html @@ -0,0 +1,57 @@ + + + + + + + + Sample + + + +
+ + + + + + Product + Supplier + Price + + + Notebook Basic 15
HT-1000
+ Very Best Screens + 899.99 EUR + +
+ + + Astro Laptop 216
HT-1251
+ Technocom + 679.99 EUR + +
+ + + Benda Laptop 1408
HT-6102
+ Ultrasonic United + 699.99 EUR + +
+ + Broad Screen 22HD
HT-1255
+ Speaker Experts + 399.99 EUR + +
+ +
+ + +
+ + + + + From a01a3036526cd02eaac1a973ac5054a7c9c8a194 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cahit=20G=C3=BCrg=C3=BCc?= Date: Fri, 10 Jan 2025 13:36:01 +0100 Subject: [PATCH 05/42] feat(ui5-table): popin-text property added (#10514) --- packages/main/cypress/specs/Table.cy.ts | 32 +++++++++++++++++++++++- packages/main/src/TableCell.hbs | 11 ++++---- packages/main/src/TableCell.ts | 13 +++++++--- packages/main/src/TableHeaderCell.ts | 10 ++++++++ packages/main/test/pages/TablePopin.html | 2 +- 5 files changed, 58 insertions(+), 10 deletions(-) diff --git a/packages/main/cypress/specs/Table.cy.ts b/packages/main/cypress/specs/Table.cy.ts index 3f304719fbde..e20e36c0d9ea 100644 --- a/packages/main/cypress/specs/Table.cy.ts +++ b/packages/main/cypress/specs/Table.cy.ts @@ -5,6 +5,7 @@ import "../../src/TableHeaderRow.js"; import "../../src/TableCell.js"; import "../../src/TableRow.js"; import "../../src/TableSelection.js"; +import type Table from "../../src/Table.js"; // Porting Table.spec.js (wdio tests) to cypress tests const ROLE_COLUMN_HEADER = "columnheader"; @@ -60,7 +61,7 @@ describe("Table - Popin Mode", () => { ColumnA Column B Column C - Column D + Column D Cell A @@ -194,6 +195,35 @@ describe("Table - Popin Mode", () => { }); } }); + + it("should show the popin-text in the popin area", () => { + cy.get("ui5-table").then($table => { + $table.css("width", "150px"); + }); + + // eslint-disable-next-line cypress/no-unnecessary-waiting + cy.wait(50); + + cy.get("ui5-table").then($table => { + let popinCellCount = 0; + let validPopinTextCount = 0; + const table = $table[0] as Table; + // eslint-disable-next-line no-restricted-syntax + for (const row of table.rows) { + // eslint-disable-next-line no-restricted-syntax + for (const cell of row.cells) { + if (cell._popin) { + popinCellCount++; + const popinText = cell._headerCell.popinText || cell._headerCell.textContent; + if (cell.shadowRoot!.textContent === `${popinText}:`) { + validPopinTextCount++; + } + } + } + } + return popinCellCount && popinCellCount === validPopinTextCount; + }).should("be.true"); + }); }); describe("Table - Horizontal alignment of cells", () => { diff --git a/packages/main/src/TableCell.hbs b/packages/main/src/TableCell.hbs index 81808af7bf82..a19d38ec0c5c 100644 --- a/packages/main/src/TableCell.hbs +++ b/packages/main/src/TableCell.hbs @@ -1,9 +1,10 @@ {{#if _popin}} - {{#if _popinHeader}} -
- {{_popinHeader}} - {{_i18nPopinColon}} -
+ {{#if _popinText}} + {{_popinText}} + {{_i18nPopinColon}} + {{else if _popinHeader}} + {{_popinHeader}} + {{_i18nPopinColon}} {{/if}} {{else}} diff --git a/packages/main/src/TableCell.ts b/packages/main/src/TableCell.ts index 04a34f863bb5..d0dfaae9d517 100644 --- a/packages/main/src/TableCell.ts +++ b/packages/main/src/TableCell.ts @@ -39,12 +39,19 @@ class TableCell extends TableCellBase { } } - get _popinHeader() { + get _headerCell() { const row = this.parentElement as TableRow; const table = row.parentElement as Table; const index = row.cells.indexOf(this); - const headerCell = table.headerRow[0].cells[index]; - return headerCell.content[0]?.cloneNode(true); + return table.headerRow[0].cells[index]; + } + + get _popinText() { + return this._headerCell?.popinText; + } + + get _popinHeader() { + return this._headerCell?.content[0]?.cloneNode(true); } get _i18nPopinColon() { diff --git a/packages/main/src/TableHeaderCell.ts b/packages/main/src/TableHeaderCell.ts index 4b3888ca79fe..cb40fe18bc22 100644 --- a/packages/main/src/TableHeaderCell.ts +++ b/packages/main/src/TableHeaderCell.ts @@ -75,6 +75,16 @@ class TableHeaderCell extends TableCellBase { @property({ type: Number }) importance = 0; + /** + * The text for the column when it pops in. + * + * @default undefined + * @since 2.7.0 + * @public + */ + @property() + popinText?: string; + @property({ type: Boolean, noAttribute: true }) _popin = false; diff --git a/packages/main/test/pages/TablePopin.html b/packages/main/test/pages/TablePopin.html index 468b2a41456d..5f76d065c224 100644 --- a/packages/main/test/pages/TablePopin.html +++ b/packages/main/test/pages/TablePopin.html @@ -18,7 +18,7 @@ ColumnA Column B Column C - Column D + Column D Cell A From 11b9356a13d01ece1ebcf4185b61259b9ad6d364 Mon Sep 17 00:00:00 2001 From: Vladislav Tasev Date: Fri, 10 Jan 2025 14:49:21 +0200 Subject: [PATCH 06/42] fix: ai button and color palette bring their own items (#10517) --- packages/ai/README.md | 1 + packages/ai/src/Button.ts | 1 + packages/main/README.md | 2 +- packages/main/src/ColorPalette.ts | 1 + 4 files changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/ai/README.md b/packages/ai/README.md index 2459ecdbf61a..d40a1ee5a82b 100644 --- a/packages/ai/README.md +++ b/packages/ai/README.md @@ -13,6 +13,7 @@ Provides web components implementing AI-related visual and interaction. | Web Component | Tag name | Module import | |--------------------------|--------------------------------|---------------------------------------------------------| | Button | `ui5-ai-button` | `import "@ui5/webcomponents-ai/dist/Button.js";` | +| Button State | `ui5-ai-button-state` | comes with `ui5-ai-button` | | PromptInput | `ui5-ai-prompt-input` | `import "@ui5/webcomponents-ai/dist/PromptInput.js";` | ## Provided assets diff --git a/packages/ai/src/Button.ts b/packages/ai/src/Button.ts index b9e90523c2ff..dcd3b919f13a 100644 --- a/packages/ai/src/Button.ts +++ b/packages/ai/src/Button.ts @@ -9,6 +9,7 @@ import jsxRenderer from "@ui5/webcomponents-base/dist/renderer/JsxRenderer.js"; import type SplitButton from "@ui5/webcomponents/dist/SplitButton.js"; import type ButtonDesign from "@ui5/webcomponents/dist/types/ButtonDesign.js"; import type ButtonState from "./ButtonState.js"; +import "./ButtonState.js"; import ButtonTemplate from "./ButtonTemplate.js"; diff --git a/packages/main/README.md b/packages/main/README.md index f146c8b662f3..5f1eff1dce2e 100644 --- a/packages/main/README.md +++ b/packages/main/README.md @@ -28,7 +28,7 @@ Provides general purpose UI building blocks such as buttons, labels, inputs and | Checkbox | `ui5-checkbox` | `import "@ui5/webcomponents/dist/CheckBox.js";` | | Color Palette | `ui5-color-palette` | `import "@ui5/webcomponents/dist/ColorPalette.js";` | | Color Palette Item | `ui5-color-palette-item` | comes with `ui5-color-palette` | -| Color Palette Popover | `ui5-color-palette-popover` | comes with `ui5-color-palette-popover` | +| Color Palette Popover | `ui5-color-palette-popover` | `import "@ui5/webcomponents/dist/ColorPalettePopover.js";` | | Color Picker | `ui5-color-picker` | `import "@ui5/webcomponents/dist/ComboPicker.js";` | | ComboBox | `ui5-combobox` | `import "@ui5/webcomponents/dist/ComboBox.js";` | | ComboBox Item | `ui5-cb-item` | comes with `ui5-combobox` | diff --git a/packages/main/src/ColorPalette.ts b/packages/main/src/ColorPalette.ts index 87820892ef6d..90ab6fbc8095 100644 --- a/packages/main/src/ColorPalette.ts +++ b/packages/main/src/ColorPalette.ts @@ -24,6 +24,7 @@ import type Button from "./Button.js"; import type Dialog from "./Dialog.js"; import type ColorPaletteMoreColors from "./features/ColorPaletteMoreColors.js"; import type ColorPicker from "./ColorPicker.js"; +import "./ColorPaletteItem.js"; import { COLORPALETTE_CONTAINER_LABEL, From eb44feb431ab580093bb1d75e414a05656736314 Mon Sep 17 00:00:00 2001 From: Peter Skelin Date: Fri, 10 Jan 2025 16:07:34 +0200 Subject: [PATCH 07/42] chore: add lint rule for conditional jsx rendering strict boolean checks (#10516) chore: add lint rule for contional jsx rendring strict bolean checks --- packages/fiori/src/DynamicPageTitle.ts | 4 +- packages/fiori/src/UserMenuTemplate.tsx | 4 +- packages/main/src/DialogTemplate.tsx | 2 +- packages/main/src/SliderBaseTemplate.tsx | 4 +- packages/main/src/SuggestionListItem.ts | 2 +- packages/main/src/TreeItemTemplate.tsx | 2 +- packages/tools/components-package/eslint.js | 2 + packages/tools/package.json | 1 + yarn.lock | 92 ++++++++++++++++++++- 9 files changed, 102 insertions(+), 11 deletions(-) diff --git a/packages/fiori/src/DynamicPageTitle.ts b/packages/fiori/src/DynamicPageTitle.ts index 2952905d3860..400d738a13ef 100644 --- a/packages/fiori/src/DynamicPageTitle.ts +++ b/packages/fiori/src/DynamicPageTitle.ts @@ -274,8 +274,8 @@ class DynamicPageTitle extends UI5Element { } } - get _needsSeparator() { - return (this.navigationBar.length && this.actionsBar.length); + get _needsSeparator(): boolean { + return (this.navigationBar.length > 0 && this.actionsBar.length > 0); } prepareLayoutActions() { diff --git a/packages/fiori/src/UserMenuTemplate.tsx b/packages/fiori/src/UserMenuTemplate.tsx index 895a0aedec19..ff87347b8ad1 100644 --- a/packages/fiori/src/UserMenuTemplate.tsx +++ b/packages/fiori/src/UserMenuTemplate.tsx @@ -77,7 +77,7 @@ export default function UserMenuTemplate(this: UserMenu) { - - - + {{#if secondaryTitle}} + {{#unless isSBreakPoint}} +
{{secondaryTitle}}
+ {{/unless}} {{/if}} + {{/if}} {{/if}} {{#unless hasMenuItems}} - {{#if hasLogo}} - - {{/if}} - {{#if primaryTitle}} -

- {{primaryTitle}} -

+ {{#if isSBreakPoint}} + {{#if hasLogo}} + {{> singleLogo}} + {{/if}} + {{else}} + {{> combinedLogo}} + {{#if secondaryTitle}} + {{#if primaryTitle}} +

{{secondaryTitle}}

+ {{/if}} + {{/if}} {{/if}} {{/unless}} - - {{#if secondaryTitle}} -

{{secondaryTitle}}

- {{/if}} - {{#if hasMidContent}}
- {{else}} -
- {{#if _isXXLBreakpoint}} - {{#if hasSearchField}} - - {{/if}} - {{/if}} -
{{/if}} +
+ {{#if showAdditionalContext}} +
+
+
+ {{#each startContent}} +
+ +
+ {{/each}} +
+ {{#each endContent}} +
+ +
+ {{/each}} +
+
+
+ {{else}} +
+ {{/if}} +
+ {{#if hasSearchField}} + {{#if _showFullWidthSearch}} +
+
+ +
+ + {{_cancelBtnText}} + +
+ {{/if}} -
-
- - {{#unless hasMidContent }} - {{#unless _isXXLBreakpoint }} - {{#if hasSearchField}} - {{#if _fullWidthSearch}} -
-
+
+ {{#unless _showFullWidthSearch}} + {{/unless}}
- - {{_cancelBtnText}} - -
- {{/if}} -
- {{#unless _fullWidthSearch}} - - {{/unless}} -
+ + {{/if}} + {{#if hasAssistant}} +
+ +
+ {{/if}} - - {{/if}} - {{/unless}} - {{/unless}} + {{#if showNotifications}} + + {{/if}} - {{#if hasAssistant}} - - {{/if}} + {{#each customItemsInfo}} + + {{/each}} - {{#each customItemsInfo}} - {{/each}} - - {{#if showNotifications}} - - {{/if}} - - - {{#if hasProfile}} - {{> profileButton}} - {{/if}} + {{#if hasProfile}} + {{> profileButton}} + {{/if}} - {{#if showProductSwitch}} - - {{/if}} + {{#if showProductSwitch}} + + {{/if}} +
-
{{#*inline "profileButton"}} @@ -216,9 +211,10 @@ profile-btn id="{{this._id}}-item-3" @click={{_handleProfilePress}} - style="{{styles.items.profile}}" tooltip="{{_profileText}}" - class="ui5-shellbar-button ui5-shellbar-image-button" + class="ui5-shellbar-button ui5-shellbar-image-button ui5-shellbar-no-overflow-button ui5-shellbar-items-for-arrow-nav" + aria-label="{{imageBtnText}}" + aria-haspopup="dialog" .accessibilityAttributes={{accInfo.profile.accessibilityAttributes}} data-ui5-stable="profile" > @@ -226,4 +222,42 @@ {{/inline}} + +{{#*inline "singleLogo"}} + +{{/inline}} + +{{#*inline "combinedLogo"}} +
+ {{#if hasLogo}} + + {{/if}} +
+ {{#if primaryTitle}} +

+ {{primaryTitle}} +

+ {{/if}} +
+
+{{/inline}} + {{>include "./ShellBarPopover.hbs"}} \ No newline at end of file diff --git a/packages/fiori/src/ShellBar.ts b/packages/fiori/src/ShellBar.ts index 87810bfaea29..f3bb40a281ea 100644 --- a/packages/fiori/src/ShellBar.ts +++ b/packages/fiori/src/ShellBar.ts @@ -7,13 +7,20 @@ import event from "@ui5/webcomponents-base/dist/decorators/event-strict.js"; import i18n from "@ui5/webcomponents-base/dist/decorators/i18n.js"; import litRender from "@ui5/webcomponents-base/dist/renderer/LitRenderer.js"; import ResizeHandler from "@ui5/webcomponents-base/dist/delegate/ResizeHandler.js"; -import { isSpace, isEnter } from "@ui5/webcomponents-base/dist/Keys.js"; +import { + isSpace, + isEnter, + isLeft, + isRight, +} from "@ui5/webcomponents-base/dist/Keys.js"; +import { getEffectiveAriaLabelText } from "@ui5/webcomponents-base/dist/util/AccessibilityTextsHelper.js"; import ListItemStandard from "@ui5/webcomponents/dist/ListItemStandard.js"; import List from "@ui5/webcomponents/dist/List.js"; import type { ListSelectionChangeEventDetail } from "@ui5/webcomponents/dist/List.js"; import type { ResizeObserverCallback } from "@ui5/webcomponents-base/dist/delegate/ResizeHandler.js"; import Popover from "@ui5/webcomponents/dist/Popover.js"; import Button from "@ui5/webcomponents/dist/Button.js"; +import Menu from "@ui5/webcomponents/dist/Menu.js"; import Icon from "@ui5/webcomponents/dist/Icon.js"; import type Input from "@ui5/webcomponents/dist/Input.js"; import type { IButton } from "@ui5/webcomponents/dist/Button.js"; @@ -25,13 +32,16 @@ import "@ui5/webcomponents-icons/dist/overflow.js"; import "@ui5/webcomponents-icons/dist/grid.js"; import "@ui5/webcomponents-icons/dist/slim-arrow-down.js"; import type { - Timeout, ClassMap, AccessibilityAttributes, AriaRole, } from "@ui5/webcomponents-base"; import type ListItemBase from "@ui5/webcomponents/dist/ListItemBase.js"; import type PopoverHorizontalAlign from "@ui5/webcomponents/dist/types/PopoverHorizontalAlign.js"; +import throttle from "@ui5/webcomponents-base/dist/util/throttle.js"; +import { getScopedVarName } from "@ui5/webcomponents-base/dist/CustomElementsScope.js"; +import getActiveElement from "@ui5/webcomponents-base/dist/util/getActiveElement.js"; + import type ShellBarItem from "./ShellBarItem.js"; // Templates @@ -45,11 +55,18 @@ import { SHELLBAR_LABEL, SHELLBAR_LOGO, SHELLBAR_NOTIFICATIONS, + SHELLBAR_NOTIFICATIONS_NO_COUNT, SHELLBAR_CANCEL, SHELLBAR_PROFILE, SHELLBAR_PRODUCTS, SHELLBAR_SEARCH, + SHELLBAR_SEARCH_FIELD, SHELLBAR_OVERFLOW, + SHELLBAR_LOGO_AREA, + SHELLBAR_ADDITIONAL_CONTEXT, + SHELLBAR_SEARCHFIELD_DESCRIPTION, + SHELLBAR_SEARCH_BTN_OPEN, + SHELLBAR_PRODUCT_SWITCH_BTN, } from "./generated/i18n/i18n-defaults.js"; type ShellBarLogoAccessibilityAttributes = { @@ -57,7 +74,7 @@ type ShellBarLogoAccessibilityAttributes = { name?: string, } type ShellBarProfileAccessibilityAttributes = Pick; -type ShellBarAreaAccessibilityAttributes = Pick; +type ShellBarAreaAccessibilityAttributes = Pick; type ShellBarAccessibilityAttributes = { logo?: ShellBarLogoAccessibilityAttributes notifications?: ShellBarAreaAccessibilityAttributes @@ -87,6 +104,10 @@ type ShellBarMenuItemClickEventDetail = { item: HTMLElement; }; +type ShellBarContentItemVisibilityChangeEventDetail = { + items: Array +}; + type ShellBarSearchButtonEventDetail = { targetRef: HTMLElement; searchFieldVisible: boolean; @@ -96,7 +117,6 @@ interface IShelBarItemInfo { id: string, icon?: string, text?: string, - priority: number, show: boolean, count?: string, custom?: boolean, @@ -104,14 +124,17 @@ interface IShelBarItemInfo { stableDomRef?: string, refItemid?: string, press: (e: MouseEvent) => void, - styles: object, domOrder: number, classes: string, order?: number, profile?: boolean, + tooltip?: string, } -const HANDLE_RESIZE_DEBOUNCE_RATE = 200; // ms +const RESIZE_THROTTLE_RATE = 40; // ms + +// actions always visible in lean mode, order is important +const PREDEFINED_PLACE_ACTIONS = ["feedback", "sys-help"]; /** * @class @@ -159,6 +182,7 @@ const HANDLE_RESIZE_DEBOUNCE_RATE = 200; // ms List, Popover, ListItemStandard, + Menu, ], }) /** @@ -230,6 +254,18 @@ const HANDLE_RESIZE_DEBOUNCE_RATE = 200; // ms bubbles: true, }) +/** + * Fired, when an item from the startContent or endContent slots is hidden or shown. + * **Note:** The `content-item-visibility-change` event is in an experimental state and is a subject to change. + * + * @param {Array} array of all the items that are hidden + * @public + * @since 2.7.0 + */ +@event("content-item-visibility-change", { + bubbles: true, +}) + class ShellBar extends UI5Element { eventDetails!: { "notifications-click": ShellBarNotificationsClickEventDetail, @@ -238,6 +274,7 @@ class ShellBar extends UI5Element { "logo-click": ShellBarLogoClickEventDetail, "menu-item-click": ShellBarMenuItemClickEventDetail, "search-button-click": ShellBarSearchButtonEventDetail, + "content-item-visibility-change": ShellBarContentItemVisibilityChangeEventDetail } /** * Defines the `primaryTitle`. @@ -327,14 +364,14 @@ class ShellBar extends UI5Element { * @public * @since 1.10.0 */ - @property({ type: Object }) - accessibilityAttributes: ShellBarAccessibilityAttributes = {}; + @property({ type: Object }) + accessibilityAttributes: ShellBarAccessibilityAttributes = {}; /** * @private */ @property() - breakpointSize?: string; + breakpointSize = "S"; /** * @private @@ -355,10 +392,12 @@ class ShellBar extends UI5Element { _overflowPopoverExpanded = false; @property({ type: Boolean, noAttribute: true }) - _fullWidthSearch = false; + hasVisibleStartContent = false; @property({ type: Boolean, noAttribute: true }) - _isXXLBreakpoint = false; + hasVisibleEndContent = false; + + _cachedHiddenContent: Array = []; /** * Defines the assistant slot. @@ -401,7 +440,7 @@ class ShellBar extends UI5Element { logo!: Array; /** - * Defines the items displayed in menu after a click on the primary title. + * Defines the items displayed in menu after a click on a start button. * * **Note:** You can use the `` and its ancestors. * @since 0.10 @@ -419,7 +458,7 @@ class ShellBar extends UI5Element { /** * Defines a `ui5-button` in the bar that will be placed in the beginning. - * We encourage this slot to be used for a back or home button. + * We encourage this slot to be used for a menu button. * It gets overstyled to match ShellBar's styling. * @public */ @@ -435,6 +474,26 @@ class ShellBar extends UI5Element { @slot() midContent!: Array; + /** + * Define the items displayed in the start of the additional content area. + * **Note:** The `startContent` slot is in an experimental state and is a subject to change. + * + * @public + * @since 2.7.0 + */ + @slot({ type: HTMLElement, individualSlots: true }) + startContent!: Array; + + /** + * Define the items displayed in the end of the additional content area. + * **Note:** The `endContent` slot is in an experimental state and is a subject to change. + * + * @public + * @since 2.7.0 + */ + @slot({ type: HTMLElement, individualSlots: true }) + endContent!: Array; + @i18n("@ui5/webcomponents-fiori") static i18nBundle: I18nBundle; overflowPopover?: Popover | null; @@ -442,9 +501,16 @@ class ShellBar extends UI5Element { _isInitialRendering: boolean; _defaultItemPressPrevented: boolean; menuItemsObserver: MutationObserver; - _debounceInterval?: Timeout | null; + additionalContextObserver: MutationObserver; _hiddenIcons: Array; _handleResize: ResizeObserverCallback; + _overflowNotifications: string | null; + _lastOffsetWidth = 0; + _observableContent: Array = []; + _searchBarAutoOpen: boolean = false; + _searchBarAutoClosed: boolean = false; + _searchIconPressed: boolean = false; + _headerPress: () => void; static get FIORI_3_BREAKPOINTS() { @@ -474,6 +540,7 @@ class ShellBar extends UI5Element { this._hiddenIcons = []; this._itemsInfo = []; this._isInitialRendering = true; + this._overflowNotifications = null; // marks if preventDefault() is called in item's press handler this._defaultItemPressPrevented = false; @@ -482,6 +549,10 @@ class ShellBar extends UI5Element { this._updateClonedMenuItems(); }); + this.additionalContextObserver = new MutationObserver(() => { + this._updateAdditionalContextItems(); + }); + this._headerPress = () => { this._updateClonedMenuItems(); @@ -492,22 +563,113 @@ class ShellBar extends UI5Element { } }; - this._handleResize = () => { - this._debounce(() => { - this.menuPopover = this._getMenuPopover(); - this.overflowPopover = this._getOverflowPopover(); - this.overflowPopover.open = false; + this._handleResize = throttle(() => { + this.menuPopover = this._getMenuPopover(); + this.overflowPopover = this._getOverflowPopover(); + this.overflowPopover.open = false; + if (this._lastOffsetWidth !== this.offsetWidth) { this._overflowActions(); - }, HANDLE_RESIZE_DEBOUNCE_RATE); - }; + if (this._searchBarAutoOpen) { + this._searchBarInitialState(); + } + } + }, RESIZE_THROTTLE_RATE); + } + + _searchBarInitialState() { + const spacerWidth = this.shadowRoot!.querySelector(".ui5-shellbar-spacer") ? this.shadowRoot!.querySelector(".ui5-shellbar-spacer")!.getBoundingClientRect().width : 0; + const searchFieldWidth = this.domCalculatedValues("--_ui5_shellbar_search_field_width"); + if (this._searchIconPressed || document.activeElement === this.searchField[0]) { + return; + } + if (this._showFullWidthSearch) { + this.showSearchField = false; + this._searchBarAutoClosed = true; + return; + } + if ((spacerWidth <= 0 || this.additionalContextHidden.length !== 0) && this.showSearchField === true) { + this.showSearchField = false; + this._searchBarAutoClosed = true; + } + if (spacerWidth > searchFieldWidth && this.additionalContextHidden.length === 0 && this.showSearchField === false) { + this.showSearchField = true; + this._searchBarAutoClosed = false; + } + } + + _onKeyDown(e: KeyboardEvent) { + const items = this._getVisibleAndInteractiveItems(); + const activeElement = getActiveElement(); + const currentIndex = items.findIndex(el => el === activeElement); + + if (isLeft(e) || isRight(e)) { + e.preventDefault();// Prevent the default behavior to avoid any further automatic focus movemen + + // Focus navigation based on the key pressed + if (isLeft(e)) { + this._focusPreviousItem(items, currentIndex); + } else if (isRight(e)) { + this._focusNextItem(items, currentIndex); + } + } + } + + _focusNextItem(items: HTMLElement[], currentIndex: number) { + if (currentIndex < items.length - 1) { + (items[currentIndex + 1]).focus(); // Focus the next element + } + } + + _focusPreviousItem(items: HTMLElement[], currentIndex: number) { + if (currentIndex > 0) { + (items[currentIndex - 1]).focus(); // Focus the previous element + } + } + + _isVisible(element: HTMLElement): boolean { + const style = getComputedStyle(element); + + return style.display !== "none" && style.visibility !== "hidden" && element.offsetWidth > 0 && element.offsetHeight > 0; + } + + _isInteractive(element: HTMLElement | UI5Element): boolean { + const component = element as UI5Element; + if (component.isUI5Element) { + const dom = component.getFocusDomRef(); + return dom?.tabIndex === 0; + } + return element.tabIndex === 0; + } + + _getNavigableContent() { + return [ + ...this.startButton, + ...this.logo, + ...this.shadowRoot!.querySelectorAll(".ui5-shellbar-logo"), + ...this.shadowRoot!.querySelectorAll(".ui5-shellbar-logo-area"), + ...this.shadowRoot!.querySelectorAll(".ui5-shellbar-menu-button"), + ...this.startContent, + ...this.endContent, + ...this._getRightChildItems(), + ] as HTMLElement[]; + } + + _getRightChildItems() { + return [ + ...this.searchField, + ...this.shadowRoot!.querySelectorAll(".ui5-shellbar-search-item-for-arrow-nav"), + ...this.assistant, + ...this.shadowRoot!.querySelectorAll(".ui5-shellbar-items-for-arrow-nav"), + ] as HTMLElement[]; } - _debounce(fn: () => void, delay: number) { - clearTimeout(this._debounceInterval!); - this._debounceInterval = setTimeout(() => { - this._debounceInterval = null; - fn(); - }, delay); + _getVisibleAndInteractiveItems() { + const items = this._getNavigableContent(); + const visibleAndInteractiveItems = items.filter(item => { + return this._isVisible(item) && this._isInteractive(item); + }); + + return visibleAndInteractiveItems; } _menuItemPress(e: CustomEvent) { @@ -564,6 +726,19 @@ class ShellBar extends UI5Element { } } + _calculateCSSREMValue(styleSet: CSSStyleDeclaration, propertyName: string): number { + return Number(styleSet.getPropertyValue(propertyName).replace("rem", "")) * parseInt(getComputedStyle(document.body).getPropertyValue("font-size")); + } + + _parsePxValue(styleSet: CSSStyleDeclaration, propertyName: string): number { + return Number(styleSet.getPropertyValue(propertyName).replace("px", "")); + } + + domCalculatedValues(cssVar: string): number { + const shellbarComputerStyle = getComputedStyle(this.getDomRef()!); + return this._calculateCSSREMValue(shellbarComputerStyle, getScopedVarName(cssVar)); // px + } + onBeforeRendering() { this.withLogo = this.hasLogo; @@ -578,12 +753,26 @@ class ShellBar extends UI5Element { }); this._observeMenuItems(); + this._observeAdditionalContextItems(); + this._updateSeparatorsVisibility(); } - onAfterRendering() { - this._overflowActions(); + get additionalContextSorted() { + return this.additionalContext.sort((a, b) => { + return parseInt(a.getAttribute("data-hide-order") || "0") - parseInt(b.getAttribute("data-hide-order") || "0"); + }).map(item => this.shadowRoot!.querySelector(`#${item.slot}`)).filter(item => item !== null); + } - this._fullWidthSearch = this._showFullWidthSearch; + get additionalContextContainer() { + return this.shadowRoot!.querySelector(".ui5-shellbar-overflow-container-additional-content"); + } + + onAfterRendering() { + requestAnimationFrame(() => { + this._lastOffsetWidth = this.offsetWidth; + this._overflowActions(); + }); + this._searchBarAutoOpen = this._searchBarAutoClosed || (this.showSearchField && !this._searchIconPressed); } /** @@ -607,88 +796,132 @@ class ShellBar extends UI5Element { if (this.breakpointSize !== mappedSize) { this.breakpointSize = mappedSize; } - - this._isXXLBreakpoint = this.breakpointSize === "XXL"; - return mappedSize; } - _handleSizeS() { - const hasIcons = this.showNotifications || this.showProductSwitch || !!this.searchField.length || !!this.items.length; - - const newItems = this._getAllItems(hasIcons).map((info): IShelBarItemInfo => { - const isOverflowIcon = info.classes.indexOf("ui5-shellbar-overflow-button") !== -1; - const isImageIcon = info.classes.indexOf("ui5-shellbar-image-button") !== -1; - const shouldStayOnScreen = isOverflowIcon || (isImageIcon && this.hasProfile); + _hideOverflowItems(hiddenItems: number, items: IShelBarItemInfo[]) { + for (let i = 0; hiddenItems > 0 && i < items.length; i++) { + // start from last item + const item = items[items.length - 1 - i]; + if (item.classes.indexOf("ui5-shellbar-no-overflow-button") === -1) { + item.classes = `${item.classes} ui5-shellbar-hidden-button`; + hiddenItems--; + } + } - return { - ...info, - classes: `${info.classes} ${shouldStayOnScreen ? "" : "ui5-shellbar-hidden-button"} ui5-shellbar-button`, - styles: { - order: shouldStayOnScreen ? 1 : -1, - }, - }; - }); + // assistant is a slot, still described in the itemsInfo for the purpose of the overflow + // so if marked as hidden, it should be hidden separately + this._updateAssistantIconVisibility(items); - this._updateItemsInfo(newItems); + return hiddenItems; } - _handleActionsOverflow() { - const rightContainerRect = this.shadowRoot!.querySelector(".ui5-shellbar-overflow-container-right")!.getBoundingClientRect(); - let overflowSelector = ".ui5-shellbar-button:not(.ui5-shellbar-overflow-button):not(.ui5-shellbar-invisible-button)"; + _hideAdditionalContext() { + const container = this.additionalContextContainer; + const totalWidth = container?.offsetWidth || 0; - if (this.showSearchField) { - overflowSelector += ",.ui5-shellbar-search-field"; - } + const additionalContextSorted = this.additionalContextSorted.toReversed(); - const elementsToOverflow = this.shadowRoot!.querySelectorAll diff --git a/packages/main/src/ToolbarItem.ts b/packages/main/src/ToolbarItem.ts index a88ab8bd7e02..1f9f246707e9 100644 --- a/packages/main/src/ToolbarItem.ts +++ b/packages/main/src/ToolbarItem.ts @@ -1,6 +1,7 @@ import UI5Element from "@ui5/webcomponents-base/dist/UI5Element.js"; import type { TemplateFunction } from "@ui5/webcomponents-base/dist/renderer/executeTemplate.js"; import property from "@ui5/webcomponents-base/dist/decorators/property.js"; +import event from "@ui5/webcomponents-base/dist/decorators/event-strict.js"; import type ToolbarItemOverflowBehavior from "./types/ToolbarItemOverflowBehavior.js"; @@ -8,6 +9,14 @@ type IEventOptions = { preventClosing: boolean; } +type ToolbarItemEventDetail = { + targetRef: HTMLElement; +} + +@event("close-overflow", { + bubbles: true, +}) + /** * @class * @@ -21,7 +30,8 @@ type IEventOptions = { class ToolbarItem extends UI5Element { // strictEvents: needed for parent class eventDetails!: { - click: void + click: ToolbarItemEventDetail, + "close-overflow": void; } /** * Property used to define the access of the item to the overflow Popover. If "NeverOverflow" option is set, @@ -101,18 +111,13 @@ class ToolbarItem extends UI5Element { throw new Error("Popover template must be defined"); } - /** - * Returns the events that the item is subscribed to. - * @protected - */ - get subscribedEvents(): Map { - return new Map(); - } - get stableDomRef() { return this.getAttribute("stable-dom-ref") || `${this._id}-stable-dom-ref`; } } -export type { IEventOptions }; +export type { + IEventOptions, + ToolbarItemEventDetail, +}; export default ToolbarItem; diff --git a/packages/main/src/ToolbarPopoverButtonTemplate.tsx b/packages/main/src/ToolbarPopoverButtonTemplate.tsx index 9b4753955b43..c07114e3f022 100644 --- a/packages/main/src/ToolbarPopoverButtonTemplate.tsx +++ b/packages/main/src/ToolbarPopoverButtonTemplate.tsx @@ -16,6 +16,7 @@ export default function ToolbarPopoverButtonTemplate(this: ToolbarButton) { class="ui5-tb-popover-button ui5-tb-popover-item" data-ui5-external-action-item-id={this._id} data-ui5-stable={this.stableDomRef} + onClick={(...args) => this.onClick(...args)} > {this.text} diff --git a/packages/main/src/ToolbarPopoverSelectTemplate.tsx b/packages/main/src/ToolbarPopoverSelectTemplate.tsx index c1997b319b1b..2e897caf4c76 100644 --- a/packages/main/src/ToolbarPopoverSelectTemplate.tsx +++ b/packages/main/src/ToolbarPopoverSelectTemplate.tsx @@ -11,6 +11,10 @@ export default function ToolbarPopoverSelectTemplate(this: ToolbarSelect) { disabled={this.disabled} accessibleName={this.accessibleName} accessibleNameRef={this.accessibleNameRef} + onClick={(...args) => this.onClick(...args)} + onClose={(...args) => this.onClose(...args)} + onOpen={(...args) => this.onOpen(...args)} + onChange={(...args) => this.onChange(...args)} > {this.options.map((option, index) => (
); } + +function getEffectiveGroupIcon(layout: `${TimelineLayout}`, collapsed: boolean): string { + if (layout === TimelineLayout.Vertical) { + return collapsed ? slimArrowleft : slimArrowDown; + } + + return collapsed ? slimArrowup : slimArrowRight; +} diff --git a/packages/fiori/src/TimelineItem.ts b/packages/fiori/src/TimelineItem.ts index 352e6a683249..df4f8162ed24 100644 --- a/packages/fiori/src/TimelineItem.ts +++ b/packages/fiori/src/TimelineItem.ts @@ -3,11 +3,23 @@ import customElement from "@ui5/webcomponents-base/dist/decorators/customElement import event from "@ui5/webcomponents-base/dist/decorators/event-strict.js"; import property from "@ui5/webcomponents-base/dist/decorators/property.js"; import slot from "@ui5/webcomponents-base/dist/decorators/slot.js"; +import i18n from "@ui5/webcomponents-base/dist/decorators/i18n.js"; import jsxRenderer from "@ui5/webcomponents-base/dist/renderer/JsxRenderer.js"; import type Link from "@ui5/webcomponents/dist/Link.js"; +import type I18nBundle from "@ui5/webcomponents-base/dist/i18nBundle.js"; +import type { I18nText } from "@ui5/webcomponents-base/dist/i18nBundle.js"; import type { ITimelineItem } from "./Timeline.js"; +import type ValueState from "@ui5/webcomponents-base/dist/types/ValueState.js"; import TimelineItemTemplate from "./TimelineItemTemplate.js"; import type TimelineLayout from "./types/TimelineLayout.js"; + +import { + TIMELINE_ITEM_INFORMATION_STATE_TEXT, + TIMELINE_ITEM_POSITIVE_STATE_TEXT, + TIMELINE_ITEM_NEGATIVE_STATE_TEXT, + TIMELINE_ITEM_CRITICAL_STATE_TEXT, +} from "./generated/i18n/i18n-defaults.js"; + // Styles import TimelineItemCss from "./generated/themes/TimelineItem.css.js"; @@ -86,6 +98,15 @@ class TimelineItem extends UI5Element implements ITimelineItem { @property() subtitleText?: string; + /** + * Defines the state of the icon displayed in the `ui5-timeline-item`. + * @default "None" + * @public + * @since 2.7.0 + */ + @property() + state: `${ValueState}` = "None"; + /** * Defines the content of the `ui5-timeline-item`. * @public @@ -149,6 +170,9 @@ class TimelineItem extends UI5Element implements ITimelineItem { @property({ type: Number }) positionInGroup?: number; + @i18n("@ui5/webcomponents") + static i18nBundle: I18nBundle; + constructor() { super(); } @@ -164,6 +188,19 @@ class TimelineItem extends UI5Element implements ITimelineItem { this.shadowRoot!.querySelector("[ui5-link]")?.focus(); } + static typeTextMappings(): Record { + return { + "Information": TIMELINE_ITEM_INFORMATION_STATE_TEXT, + "Positive": TIMELINE_ITEM_POSITIVE_STATE_TEXT, + "Negative": TIMELINE_ITEM_NEGATIVE_STATE_TEXT, + "Critical": TIMELINE_ITEM_CRITICAL_STATE_TEXT, + }; + } + + get timelineItemStateText() { + return this.state !== "None" ? TimelineItem.i18nBundle.getText(TimelineItem.typeTextMappings()[this.state]) : undefined; + } + get isGroupItem() { return false; } diff --git a/packages/fiori/src/TimelineItemTemplate.tsx b/packages/fiori/src/TimelineItemTemplate.tsx index cb90a7933248..d92126f2e9dd 100644 --- a/packages/fiori/src/TimelineItemTemplate.tsx +++ b/packages/fiori/src/TimelineItemTemplate.tsx @@ -16,7 +16,7 @@ export default function TimelineItemTemplate(this: TimelineItem) {
{ this.icon ? - + :
} @@ -28,6 +28,7 @@ export default function TimelineItemTemplate(this: TimelineItem) { data-sap-focus-ref class="ui5-tli-bubble" tabindex={parseInt(this.forcedTabIndex)} + aria-description={this.timelineItemStateText} >
{ this.name && name.call(this) } diff --git a/packages/fiori/src/i18n/messagebundle.properties b/packages/fiori/src/i18n/messagebundle.properties index f535c99e686a..972fdc4d693a 100644 --- a/packages/fiori/src/i18n/messagebundle.properties +++ b/packages/fiori/src/i18n/messagebundle.properties @@ -98,6 +98,12 @@ NOTIFICATION_LIST_GROUP_EXPANDED=Expanded #XACT: ARIA announcement for timeline label TIMELINE_ARIA_LABEL=Timeline +#XACT: ARIA announcement for the TimelineItem state +TIMELINE_ITEM_INFORMATION_STATE_TEXT=Information State +TIMELINE_ITEM_POSITIVE_STATE_TEXT=Positive State +TIMELINE_ITEM_NEGATIVE_STATE_TEXT=Negative State +TIMELINE_ITEM_CRITICAL_STATE_TEXT=Critical State + #XBUT: Button text for cancel button in the UploadCollectionItem UPLOADCOLLECTIONITEM_CANCELBUTTON_TEXT=Cancel diff --git a/packages/fiori/src/themes/TimelineItem.css b/packages/fiori/src/themes/TimelineItem.css index 9b145271891a..3d5490a95629 100644 --- a/packages/fiori/src/themes/TimelineItem.css +++ b/packages/fiori/src/themes/TimelineItem.css @@ -33,6 +33,22 @@ inset-inline-start: 50%; } +:host([state="Positive"]) .ui5-tli-icon { + color: var(--sapPositiveElementColor); +} + +:host([state="Negative"]) .ui5-tli-icon { + color: var(--sapNegativeElementColor); +} + +:host([state="Critical"]) .ui5-tli-icon { + color: var(--sapCriticalElementColor); +} + +:host([state="Information"]) .ui5-tli-icon { + color: var(--sapInformativeElementColor); +} + :host(:not([icon])[layout="Vertical"]) .ui5-tli-indicator::before { inset-block-start: 1.75rem; } diff --git a/packages/fiori/test/pages/Timeline.html b/packages/fiori/test/pages/Timeline.html index 15e6abfca042..527b9a4bea50 100644 --- a/packages/fiori/test/pages/Timeline.html +++ b/packages/fiori/test/pages/Timeline.html @@ -286,6 +286,33 @@

Advanced Timeline - Horizontal With Groups and Diverse Components

+ +
+

Timeline with Various Timeline Item States

+
+ + + + Compilation succeeded. + + + Lint completed with minor issues. + + + + + Unit tests failed. + + + Integration tests have warnings. + + + End-to-end tests passed. + + + +
+
+ + + + From ae56a424cb7704ba98f655cc6aafff4812a1ba29 Mon Sep 17 00:00:00 2001 From: Georgieva Date: Mon, 20 Jan 2025 16:15:56 +0200 Subject: [PATCH 35/42] docs(ui5-notification-list): enhance sample (#10540) Jira: BGSOFUIRODOPI-3374 --- .../NotificationList/InShellBar/main.css | 2 +- .../fiori/NotificationList/InShellBar/main.js | 60 ++- .../NotificationList/InShellBar/sample.html | 418 +++++------------- 3 files changed, 151 insertions(+), 329 deletions(-) diff --git a/packages/website/docs/_samples/fiori/NotificationList/InShellBar/main.css b/packages/website/docs/_samples/fiori/NotificationList/InShellBar/main.css index 149a3b790f4d..f26cbeaac0a9 100644 --- a/packages/website/docs/_samples/fiori/NotificationList/InShellBar/main.css +++ b/packages/website/docs/_samples/fiori/NotificationList/InShellBar/main.css @@ -1,5 +1,5 @@ .notificationsPopover { - max-width: 27rem; + width: 27rem; max-height: 40rem; } diff --git a/packages/website/docs/_samples/fiori/NotificationList/InShellBar/main.js b/packages/website/docs/_samples/fiori/NotificationList/InShellBar/main.js index 282b33bf7061..8d07c3d4a4c3 100644 --- a/packages/website/docs/_samples/fiori/NotificationList/InShellBar/main.js +++ b/packages/website/docs/_samples/fiori/NotificationList/InShellBar/main.js @@ -1,32 +1,41 @@ import "@ui5/webcomponents/dist/Avatar.js"; import "@ui5/webcomponents/dist/List.js"; +import "@ui5/webcomponents/dist/Text.js"; import "@ui5/webcomponents/dist/Popover.js"; import "@ui5/webcomponents/dist/Title.js"; import "@ui5/webcomponents/dist/Button.js"; import "@ui5/webcomponents/dist/Menu.js"; +import "@ui5/webcomponents/dist/MenuItem.js"; import "@ui5/webcomponents/dist/Bar.js"; import "@ui5/webcomponents/dist/MessageStrip.js"; import "@ui5/webcomponents-icons/dist/action-settings.js" import "@ui5/webcomponents-icons/dist/sort.js" +import "@ui5/webcomponents-icons/dist/crm-sales.js"; +import "@ui5/webcomponents-icons/dist/expense-report.js"; +import "@ui5/webcomponents/dist/Link.js"; import "@ui5/webcomponents-fiori/dist/ShellBar.js"; import "@ui5/webcomponents-fiori/dist/NotificationList.js"; import "@ui5/webcomponents-fiori/dist/NotificationListGroupItem.js"; import "@ui5/webcomponents-fiori/dist/NotificationListItem.js"; - -import "@ui5/webcomponents-icons/dist/employee.js"; -import "@ui5/webcomponents-icons/dist/message-error.js"; -import "@ui5/webcomponents-icons/dist/accept.js"; +import "@ui5/webcomponents-fiori/dist/IllustratedMessage.js"; +import "@ui5/webcomponents-fiori/dist/illustrations/NoNotifications.js"; const shellbar = document.querySelector("ui5-shellbar"); const notificationsPopover = document.querySelector(".notificationsPopover"); const notificationList = document.querySelector(".notificationsPopoverList"); const notificationsPopoverMessageStrip = document.querySelector(".notificationsMessageStrip"); const btnShowMessageStrip = document.querySelector("#show-message-strip"); +const btnClearAll = document.querySelector("#clear-all"); +const clearAllDialog = document.querySelector("#clear-all-dialog"); +var dialogClosers = [...clearAllDialog.querySelectorAll(".dialogCloser")]; +const btnClearAllAction = document.querySelector("#clear-all-action"); const notificationsListGroupGrowing = document.querySelector("#notificationsListGroupGrowing"); +const btnOpenMenuSort = document.getElementById("btn-sort"); +const menu = document.getElementById("sort-menu"); -const itemsToLoad = 5; -let itemsLoaded = 30; +const itemsToLoad = 10; +let itemsLoaded = 6; notificationList.addEventListener("item-close", e => { let visibleItems = 0; @@ -55,13 +64,12 @@ shellbar.addEventListener("notifications-click", e => { const insertItems = (list) => { for (var i = itemsLoaded + 1; i <= itemsLoaded + itemsToLoad; i++) { list.insertAdjacentHTML("beforeend", - ` - - Notification - 3 Days + ` + + Product Name + Now - - + Description ${i} `); @@ -88,3 +96,31 @@ notificationsListGroupGrowing.addEventListener("load-more", (e) => { btnShowMessageStrip.addEventListener("click", function() { notificationsPopoverMessageStrip.style.display = "inline-block"; }); + +notificationsPopoverMessageStrip.addEventListener("close", function() { + notificationsPopoverMessageStrip.style.display = "none"; +}); + +btnClearAll.accessibilityAttributes = { + hasPopup: "dialog", + controls: clearAllDialog.id, +}; + +btnClearAll.addEventListener("click", () => { + clearAllDialog.open = true; +}); + +dialogClosers.forEach(btn => { + btn.addEventListener("click", () => { + clearAllDialog.open = false; + }); +}); + +btnClearAllAction.addEventListener("click", () => { + notificationList.innerHTML = ``; +}); + +btnOpenMenuSort.addEventListener("click", () => { + menu.opener = btnOpenMenuSort; + menu.open = true; +}); diff --git a/packages/website/docs/_samples/fiori/NotificationList/InShellBar/sample.html b/packages/website/docs/_samples/fiori/NotificationList/InShellBar/sample.html index d2e0b375f791..b91a89de2253 100644 --- a/packages/website/docs/_samples/fiori/NotificationList/InShellBar/sample.html +++ b/packages/website/docs/_samples/fiori/NotificationList/InShellBar/sample.html @@ -15,371 +15,157 @@ primary-title="Corporate Portal" logo="../assets/images/sap-logo-svg.svg" show-notifications - notifications-count="30" + notifications-count="10" > -
+
Notifications Show M. Strip - Clear All - - + Clear All + + + Something went wrong.
+ - - - Notification - 3 Days - - - - - Description 1 - - - - Notification - 3 Days - - - - - Description 2 - - - - Notification - 3 Days - - - - - Description 3 - - - - Notification - 3 Days + + Sales + 11:13 - - + - Description 4 + Good morning! Don’t forget your daily sales target is $2,000, which needs to be fulfilled by the end of the business day. Let’s make it a great sales day! - - - Notification - 3 Days + + + Sales + 11:05 - - + + - Description 5 + You have a client meeting scheduled at 3 PM today with Acme Corp. Location: Zoom - link in calendar. - - - Notification - 3 Days + + Sales + 11:00 - - + + - Description 6 + Reminder to follow up with John Doe from XYZ Ltd. Discuss the proposal sent last week. - - - Notification - 3 Days + + + Accountant + 10:15 - - + - Description 7 + Reminder: The deadline to submit this quarter’s budget report is this Friday. - - + + Notification - 3 Days + 09:30 - - + - Description 8 + You have 5 pending expense claims awaiting your approval. Please review them by EOD. - - - Notification - 3 Days - - - - - Description 9 - - - - Notification - 3 Days + + Accountant + 09:30 - - + - Description 10 - - - - Notification - 3 Days - - - - - Description 11 - - - - Notification - 3 Days - - - - - Description 12 - - - - Notification - 3 Days - - - - - Description 13 - - - - Notification - 3 Days - - - - - Description 14 - - - - Notification - 3 Days - - - - - Description 15 - - - - Notification - 3 Days - - - - - Description 16 - - - - Notification - 3 Days - - - - - Description 17 - - - - Notification - 3 Days - - - - - Description 18 - - - - Notification - 3 Days - - - - - Description 19 - - - - Notification - 3 Days - - - - - Description 20 - - - - Notification - 3 Days - - - - - Description 21 - - - - Notification - 3 Days - - - - - Description 22 - - - - Notification - 3 Days - - - - - Description 23 - - - - Notification - 3 Days - - - - - Description 24 - - - - Notification - 3 Days - - - - - Description 25 - - - - Notification - 3 Days - - - - - Description 26 - - - - Notification - 3 Days - - - - - Description 27 - - - - Notification - 3 Days - - - - - Description 28 - - - - Notification - 3 Days - - - - - Description 29 - - - - Notification - 3 Days - - - - - Description 30 - + Just a heads-up that we will begin the financial reconciliation process for this month next Monday. - - + - - Notification - 3 Days + + Sales + 1 Day - - + - Yesterday Notification Description 1 + A new lead, Jane Smith from Innovative Tech, has been assigned to you. Contact details in CRM. - - - Notification - 3 Days - - - - - Yesterday Notification Description 2 - + + Sales + 1 Day + + + + Please submit your end-of-day sales report through the portal before logging off today. + + + + + Accountant + 1 Day + + + + Reminder: The tax filing deadline for this quarter is approaching in two weeks. + + + + Notification + 1 Day + + + + All invoices for this month have been successfully processed and payments scheduled. + + + + + + + + Are you sure you want to clear all the notifications? + + OK + Cancel + + From 27721a9518ac03efc0d2fb764442334bb07c6daf Mon Sep 17 00:00:00 2001 From: Nayden Naydenov <31909318+nnaydenow@users.noreply.github.com> Date: Mon, 20 Jan 2025 17:44:16 +0200 Subject: [PATCH 36/42] fix(popup): applying focus twice (#10556) Applying focus twice might result into an issue if navigation occurs before promise for second focus is resolved. --- packages/main/src/Popup.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/main/src/Popup.ts b/packages/main/src/Popup.ts index 2a4fd41b42b6..166420ce45b3 100644 --- a/packages/main/src/Popup.ts +++ b/packages/main/src/Popup.ts @@ -326,9 +326,6 @@ abstract class Popup extends UI5Element { await renderFinished(); - // initial focus, if focused element is dynamically created - await this.applyInitialFocus(); - if (this.isConnected) { this.fireDecoratorEvent("open"); } From c2c36080b956312e04fa8231d86e1517a58bd811 Mon Sep 17 00:00:00 2001 From: Nikola Anachkov <87311182+NakataCode@users.noreply.github.com> Date: Tue, 21 Jan 2025 09:22:04 +0200 Subject: [PATCH 37/42] fix(ui5-dynamic-page): prevent layout shift with container queries (#10578) Replace media-range attributes with container queries for responsive paddings Fixes: #10564 --- packages/fiori/src/DynamicPage.ts | 27 ------- packages/fiori/src/themes/DynamicPage.css | 97 ++++++++++++----------- 2 files changed, 51 insertions(+), 73 deletions(-) diff --git a/packages/fiori/src/DynamicPage.ts b/packages/fiori/src/DynamicPage.ts index a9bd4eac6e13..3756e044f0d9 100644 --- a/packages/fiori/src/DynamicPage.ts +++ b/packages/fiori/src/DynamicPage.ts @@ -7,9 +7,6 @@ import event from "@ui5/webcomponents-base/dist/decorators/event-strict.js"; import i18n from "@ui5/webcomponents-base/dist/decorators/i18n.js"; import jsxRenderer from "@ui5/webcomponents-base/dist/renderer/JsxRenderer.js"; import { renderFinished } from "@ui5/webcomponents-base/dist/Render.js"; -import ResizeHandler from "@ui5/webcomponents-base/dist/delegate/ResizeHandler.js"; -import type { ResizeObserverCallback } from "@ui5/webcomponents-base/dist/delegate/ResizeHandler.js"; -import MediaRange from "@ui5/webcomponents-base/dist/MediaRange.js"; import announce from "@ui5/webcomponents-base/dist/util/InvisibleMessage.js"; import InvisibleMessageMode from "@ui5/webcomponents-base/dist/types/InvisibleMessageMode.js"; import type I18nBundle from "@ui5/webcomponents-base/dist/i18nBundle.js"; @@ -153,14 +150,6 @@ class DynamicPage extends UI5Element { @property({ type: Boolean }) showFooter = false; - /** - * Defines the current media query size. - * - * @private - */ - @property() - mediaRange?: string; - /** * Defines the content of the Dynamic Page. * @@ -203,8 +192,6 @@ class DynamicPage extends UI5Element { @property({ type: Boolean }) _headerSnapped = false; - _updateMediaRange: ResizeObserverCallback; - @query(".ui5-dynamic-page-scroll-container") scrollContainer?: HTMLElement; @@ -213,16 +200,6 @@ class DynamicPage extends UI5Element { constructor() { super(); - - this._updateMediaRange = this.updateMediaRange.bind(this); - } - - onEnterDOM() { - ResizeHandler.register(this, this._updateMediaRange); - } - - onExitDOM() { - ResizeHandler.deregister(this, this._updateMediaRange); } onBeforeRendering() { @@ -431,10 +408,6 @@ class DynamicPage extends UI5Element { this.dynamicPageTitle?.removeAttribute("hovered"); await renderFinished(); } - - updateMediaRange() { - this.mediaRange = MediaRange.getCurrentRange(MediaRange.RANGESETS.RANGE_4STEPS, this.getDomRef()!.offsetWidth); - } } DynamicPage.define(); diff --git a/packages/fiori/src/themes/DynamicPage.css b/packages/fiori/src/themes/DynamicPage.css index bd7bd0af5717..a1fb9eeb3f6b 100644 --- a/packages/fiori/src/themes/DynamicPage.css +++ b/packages/fiori/src/themes/DynamicPage.css @@ -12,6 +12,7 @@ } .ui5-dynamic-page-root { + container-type: size; height: inherit; overflow-y: hidden; } @@ -80,50 +81,54 @@ /* Responsive paddings */ -:host([media-range="S"]) .ui5-dynamic-page-fit-content { - padding: var(--_ui5_dynamic_page_content_padding_S); -} - -:host([media-range="S"]) ::slotted([slot="titleArea"]) { - padding: var(--_ui5_dynamic_page_title_padding_S); -} - -:host([media-range="S"]) ::slotted([slot="headerArea"]) { - padding: var(--_ui5_dynamic_page_header_padding_S); -} - -:host([media-range="M"]) .ui5-dynamic-page-fit-content { - padding: var(--_ui5_dynamic_page_content_padding_M); -} - -:host([media-range="M"]) ::slotted([slot="titleArea"]) { - padding: var(--_ui5_dynamic_page_title_padding_M); -} - -:host([media-range="M"]) ::slotted([slot="headerArea"]) { - padding: var(--_ui5_dynamic_page_header_padding_M); -} - -:host([media-range="L"]) .ui5-dynamic-page-fit-content { - padding: var(--_ui5_dynamic_page_content_padding_L); -} - -:host([media-range="L"]) ::slotted([slot="titleArea"]) { - padding: var(--_ui5_dynamic_page_title_padding_L); -} - -:host([media-range="L"]) ::slotted([slot="headerArea"]) { - padding: var(--_ui5_dynamic_page_header_padding_L); -} - -:host([media-range="XL"]) .ui5-dynamic-page-fit-content { - padding: var(--_ui5_dynamic_page_content_padding_XL); -} - -:host([media-range="XL"]) ::slotted([slot="titleArea"]) { - padding: var(--_ui5_dynamic_page_title_padding_XL); -} - -:host([media-range="XL"]) ::slotted([slot="headerArea"]) { - padding: var(--_ui5_dynamic_page_header_padding_XL); +/* S Size */ +@container (max-width: 599px) { + .ui5-dynamic-page-fit-content { + padding: var(--_ui5_dynamic_page_content_padding_S); + } + ::slotted([slot="titleArea"]) { + padding: var(--_ui5_dynamic_page_title_padding_S); + } + ::slotted([slot="headerArea"]) { + padding: var(--_ui5_dynamic_page_header_padding_S); + } +} + +/* M Size */ +@container (min-width: 600px) and (max-width: 1023px) { + .ui5-dynamic-page-fit-content { + padding: var(--_ui5_dynamic_page_content_padding_M); + } + ::slotted([slot="titleArea"]) { + padding: var(--_ui5_dynamic_page_title_padding_M); + } + ::slotted([slot="headerArea"]) { + padding: var(--_ui5_dynamic_page_header_padding_M); + } +} + +/* L Size */ +@container (min-width: 1024px) and (max-width: 1439px) { + .ui5-dynamic-page-fit-content { + padding: var(--_ui5_dynamic_page_content_padding_L); + } + ::slotted([slot="titleArea"]) { + padding: var(--_ui5_dynamic_page_title_padding_L); + } + ::slotted([slot="headerArea"]) { + padding: var(--_ui5_dynamic_page_header_padding_L); + } +} + +/* XL Size */ +@container (min-width: 1440px) { + .ui5-dynamic-page-fit-content { + padding: var(--_ui5_dynamic_page_content_padding_XL); + } + ::slotted([slot="titleArea"]) { + padding: var(--_ui5_dynamic_page_title_padding_XL); + } + ::slotted([slot="headerArea"]) { + padding: var(--_ui5_dynamic_page_header_padding_XL); + } } \ No newline at end of file From 491538befe698e2c8957549be9d0eccf9014bd7e Mon Sep 17 00:00:00 2001 From: Nikola Anachkov <87311182+NakataCode@users.noreply.github.com> Date: Tue, 21 Jan 2025 09:25:47 +0200 Subject: [PATCH 38/42] fix(ui5-dynamic-page): remove redundant padding (#10448) Removed unnecessary padding-top and padding-bottom from ui5-dynamic-page-header-root to reduce spacing between the title and content. Fixes: #10413 --- packages/fiori/src/themes/DynamicPageHeader.css | 2 -- .../fiori/src/themes/base/DynamicPageHeader-parameters.css | 3 --- 2 files changed, 5 deletions(-) diff --git a/packages/fiori/src/themes/DynamicPageHeader.css b/packages/fiori/src/themes/DynamicPageHeader.css index 47e77347c0e8..485f37a120f2 100644 --- a/packages/fiori/src/themes/DynamicPageHeader.css +++ b/packages/fiori/src/themes/DynamicPageHeader.css @@ -6,6 +6,4 @@ .ui5-dynamic-page-header-root { background: inherit; - padding-top: var(--_ui5_dynamic_page_header_padding_top); - padding-bottom: var(--_ui5_dynamic_page_header_padding_bottom); } \ No newline at end of file diff --git a/packages/fiori/src/themes/base/DynamicPageHeader-parameters.css b/packages/fiori/src/themes/base/DynamicPageHeader-parameters.css index 276099c82faa..814aff0929f3 100644 --- a/packages/fiori/src/themes/base/DynamicPageHeader-parameters.css +++ b/packages/fiori/src/themes/base/DynamicPageHeader-parameters.css @@ -1,7 +1,4 @@ :root { - --_ui5_dynamic_page_header_padding_top: 1rem; - --_ui5_dynamic_page_header_padding_bottom: 1rem; - --_ui5_dynamic_page_header_background_color: var(--sapObjectHeader_Background); --_ui5_dynamic_page_header-actions-box-shadow: var(--sapContent_Shadow0); --_ui5_dynamic_page_header-box-shadow: var(--sapContent_HeaderShadow); From 1e7b89e35226c145f0ac1950795b6171fbbfbc0c Mon Sep 17 00:00:00 2001 From: ilhan orhan Date: Tue, 21 Jan 2025 13:05:55 +0200 Subject: [PATCH 39/42] chore: remove source maps refs for thirdparty folder (#10596) --- packages/base/src/thirdparty/preact/jsxRuntime.module.js | 1 - packages/base/src/thirdparty/preact/preact.module.js | 1 - 2 files changed, 2 deletions(-) diff --git a/packages/base/src/thirdparty/preact/jsxRuntime.module.js b/packages/base/src/thirdparty/preact/jsxRuntime.module.js index a4dcda26aaf0..c690262a08fa 100644 --- a/packages/base/src/thirdparty/preact/jsxRuntime.module.js +++ b/packages/base/src/thirdparty/preact/jsxRuntime.module.js @@ -1,2 +1 @@ import{options as r,Fragment as e}from"./preact.module.js";export{Fragment}from"./preact.module.js";var t=/["&<]/;function n(r){if(0===r.length||!1===t.test(r))return r;for(var e=0,n=0,o="",f="";n2&&(e.children=arguments.length>3?n.call(arguments,2):t),"function"==typeof l&&null!=l.defaultProps)for(r in l.defaultProps)void 0===e[r]&&(e[r]=l.defaultProps[r]);return m(l,e,i,o,null)}function m(n,t,i,o,r){var e={type:n,props:t,key:i,ref:o,__k:null,__:null,__b:0,__e:null,__c:null,constructor:void 0,__v:null==r?++u:r,__i:-1,__u:0};return null==r&&null!=l.vnode&&l.vnode(e),e}function b(){return{current:null}}function k(n){return n.children}function x(n,l){this.props=n,this.context=l}function C(n,l){if(null==l)return n.__?C(n.__,n.__i+1):null;for(var u;lu&&i.sort(e));P.__r=0}function $(n,l,u,t,i,o,r,e,f,c,s){var a,h,y,d,w,_,g=t&&t.__k||v,m=l.length;for(f=I(u,l,g,f),a=0;a0?m(o.type,o.props,o.key,o.ref?o.ref:null,o.__v):o).__=n,o.__b=n.__b+1,r=null,-1!==(f=o.__i=O(o,u,e,a))&&(a--,(r=u[f])&&(r.__u|=2)),null==r||null===r.__v?(-1==f&&h--,"function"!=typeof o.type&&(o.__u|=4)):f!==e&&(f==e-1?h--:f==e+1?h++:(f>e?h--:h++,o.__u|=4))):o=n.__k[i]=null;if(a)for(i=0;i(null!=f&&0==(2&f.__u)?1:0))for(;r>=0||e=0){if((f=l[r])&&0==(2&f.__u)&&i==f.key&&o===f.type)return r;r--}if(e2&&(f.children=arguments.length>3?n.call(arguments,2):t),m(l.type,f,i||l.key,o||l.ref,null)}function J(n,l){var u={__c:l="__cC"+h++,__:n,Consumer:function(n,l){return n.children(l)},Provider:function(n){var u,t;return this.getChildContext||(u=new Set,(t={})[l]=this,this.getChildContext=function(){return t},this.componentWillUnmount=function(){u=null},this.shouldComponentUpdate=function(n){this.props.value!==n.value&&u.forEach(function(n){n.__e=!0,M(n)})},this.sub=function(n){u.add(n);var l=n.componentWillUnmount;n.componentWillUnmount=function(){u&&u.delete(n),l&&l.call(n)}}),n.children}};return u.Provider.__=u.Consumer.contextType=u}n=v.slice,l={__e:function(n,l,u,t){for(var i,o,r;l=l.__;)if((i=l.__c)&&!i.__)try{if((o=i.constructor)&&null!=o.getDerivedStateFromError&&(i.setState(o.getDerivedStateFromError(n)),r=i.__d),null!=i.componentDidCatch&&(i.componentDidCatch(n,t||{}),r=i.__d),r)return i.__E=i}catch(l){n=l}throw n}},u=0,t=function(n){return null!=n&&null==n.constructor},x.prototype.setState=function(n,l){var u;u=null!=this.__s&&this.__s!==this.state?this.__s:this.__s=w({},this.state),"function"==typeof n&&(n=n(w({},u),this.props)),n&&w(u,n),null!=n&&this.__v&&(l&&this._sb.push(l),M(this))},x.prototype.forceUpdate=function(n){this.__v&&(this.__e=!0,n&&this.__h.push(n),M(this))},x.prototype.render=k,i=[],r="function"==typeof Promise?Promise.prototype.then.bind(Promise.resolve()):setTimeout,e=function(n,l){return n.__v.__b-l.__v.__b},P.__r=0,f=/(PointerCapture)$|Capture$/i,c=0,s=A(!1),a=A(!0),h=0;export{x as Component,k as Fragment,G as cloneElement,J as createContext,g as createElement,b as createRef,g as h,E as hydrate,t as isValidElement,l as options,D as render,L as toChildArray}; -//# sourceMappingURL=preact.module.js.map From 19f7857ffed9672d3560e6f5a365436119061846 Mon Sep 17 00:00:00 2001 From: Nikoleta Ivanova <31706628+nikoletavnv@users.noreply.github.com> Date: Tue, 21 Jan 2025 13:42:00 +0200 Subject: [PATCH 40/42] fix(ui5-page): fix floating footer layout (#10496) When ui5-bar is displayed in the page footer, the footer looks duplicated. This fix resets the paddings of the slotted ui5-bar when footer is floating. Fixes: #10358 --- packages/fiori/src/themes/Page.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/fiori/src/themes/Page.css b/packages/fiori/src/themes/Page.css index 780d90e884a0..4f2aab14a50b 100644 --- a/packages/fiori/src/themes/Page.css +++ b/packages/fiori/src/themes/Page.css @@ -47,7 +47,7 @@ } /*** Responsive paddings ***/ -::slotted([ui5-bar][design="FloatingFooter"]) { +::slotted([ui5-bar][slot="footer"][design="FloatingFooter"]) { margin: auto; padding: 0; } From 395b122c2649c30378e7f7367f13f2ceac074daa Mon Sep 17 00:00:00 2001 From: Georgieva Date: Tue, 21 Jan 2025 13:58:58 +0200 Subject: [PATCH 41/42] chore: add Cypress tests for Label, Tag, Text, Title (#10587) * chore: add Cypress tests for Label, Tag, Text, Title Jira: BGSOFUIRODOPI-3347 --- packages/main/cypress/specs/Label.cy.ts | 128 ++++++++++++++++++++++++ packages/main/cypress/specs/Tag.cy.ts | 76 ++++++++++++++ packages/main/cypress/specs/Text.cy.ts | 31 ++++++ packages/main/cypress/specs/Title.cy.ts | 37 +++++++ 4 files changed, 272 insertions(+) create mode 100644 packages/main/cypress/specs/Label.cy.ts create mode 100644 packages/main/cypress/specs/Tag.cy.ts create mode 100644 packages/main/cypress/specs/Text.cy.ts create mode 100644 packages/main/cypress/specs/Title.cy.ts diff --git a/packages/main/cypress/specs/Label.cy.ts b/packages/main/cypress/specs/Label.cy.ts new file mode 100644 index 000000000000..257983603975 --- /dev/null +++ b/packages/main/cypress/specs/Label.cy.ts @@ -0,0 +1,128 @@ +import { html } from "lit"; +import "../../src/Label.js"; +import "../../src/Input.js"; +import "../../src/TextArea.js"; +import "../../src/DatePicker.js"; +import "../../test/pages/modules/LabelPageCustomElement.js"; +import { + LABEL_COLON, +} from "../../src/generated/i18n/i18n-defaults.js"; + +describe("Label", () => { + describe("General API ", () => { + it("tests initial rendering - root and slot", () => { + cy.mount(html`Basic Label`); + cy.get("[ui5-label]").shadow().find(".ui5-label-root").should("exist"); + cy.get("[ui5-label]").shadow().find("slot:not([name])"); + }); + + it("should show required star", () => { + cy.mount(html`Required Label`); + cy.get("[ui5-label]") + .shadow() + .find(".ui5-label-required-colon") + .then($el => { + return getComputedStyle($el[0], ":after").content; + }) + .should("equal", `"*"`); + }); + + it("tests show-colon does not force truncation", () => { + cy.mount(html` + Basic Label + Basic Label + `); + + cy.get("#showColon-true").shadow().find(".ui5-label-text-wrapper").invoke("width") + .then($labelWithColonWidth => { + cy.get("#showColon-false").shadow().find(".ui5-label-text-wrapper").should("have.css", "width", `${$labelWithColonWidth}px`); + }); + }); + + it("should wrap the text of the label by default and truncate when wrappingType is None", () => { + cy.mount(html` + Reprehenderit amet cillum tempor ex eu dolor adipisicing reprehenderit pariatur. + Reprehenderit amet cillum tempor ex eu dolor adipisicing reprehenderit pariatur. + `); + + cy.get("#wrapping-label-1").invoke("height").then($wrappingLabelHeight => { + cy.get("#truncated-label-1").invoke("height").should($truncatedLabelHeight => { + expect($wrappingLabelHeight).to.be.greaterThan(16); + expect($truncatedLabelHeight).to.be.lessThan(17); + }); + }); + }); + + it("colon symbol should be taken from the i18n bundle", () => { + cy.mount(html`Basic Label`); + + cy.get("#showColon-true").shadow().find(".ui5-label-required-colon").then($el => { + return getComputedStyle($el[0], ":before").content; + }) + .should("equal", `"${LABEL_COLON.defaultText}"`); + }); + }); + + describe("linked element with 'for' property", () => { + it("should focus ui5-input on click and set correct aria-label", () => { + cy.mount(html` + Label for Input + + `); + + cy.get("[ui5-label]").realClick(); + cy.get("[ui5-input]").should("be.focused"); + + cy.get("[ui5-input]").shadow().find(".ui5-input-inner").should("have.attr", "aria-label", "Label for Input"); + }); + + it("should focus native HTML input on click", () => { + cy.mount(html` + Label for Native Input + + `); + + cy.get("[ui5-label]").realClick(); + cy.get("#native-input").should("be.focused"); + }); + + it("should focus ui5-textarea on click", () => { + cy.mount(html` + Label for Textarea + + `); + + cy.get("[ui5-label]").realClick(); + cy.get("#ui5-textarea").should("be.focused"); + }); + + it("should focus native HTML textarea on click", () => { + cy.mount(html` + Label for Native Textarea + + `); + + cy.get("[ui5-label]").realClick(); + cy.get("#native-textarea").should("be.focused"); + }); + + it("should focus ui5-date-picker on click", () => { + cy.mount(html` + Label for Date Picker + + `); + + cy.get("[ui5-label]").realClick(); + cy.get("#ui5-datepicker").should("be.focused"); + }); + + it("should focus within a shadow root", () => { + cy.mount(html` + + `); + + cy.get("#custom-element-with-label").shadow().find("[ui5-label]").realClick(); + cy.get("#custom-element-with-label").shadow().find("#input").should("be.focused"); + }); + }); +}); diff --git a/packages/main/cypress/specs/Tag.cy.ts b/packages/main/cypress/specs/Tag.cy.ts new file mode 100644 index 000000000000..183ca492c8e6 --- /dev/null +++ b/packages/main/cypress/specs/Tag.cy.ts @@ -0,0 +1,76 @@ +import { html } from "lit"; +import "../../src/Tag.js"; +import "@ui5/webcomponents-icons/dist/accept.js"; +import { + TAG_ROLE_DESCRIPTION, + TAG_SUCCESS, + TAG_DESCRIPTION_TAG, +} from "../../src/generated/i18n/i18n-defaults.js"; + +describe("Tag", () => { + describe("Tag rendering", () => { + it("initial rendering", () => { + cy.mount(html` + bigger width + + + Interactive + + + Noninteractive + `); + + cy.get("#tagWithTextAndIcon").shadow().find(".ui5-tag-root").should("have.prop", "tagName", "DIV"); + + cy.get("#interactiveTag").shadow().find(".ui5-tag-root").should("have.prop", "tagName", "BUTTON"); + + cy.get("#interactiveTag").shadow().find(".ui5-tag-root").should("have.attr", "aria-roledescription", `${TAG_ROLE_DESCRIPTION.defaultText}`); + + cy.get("#interactiveTag").shadow().find(".ui5-tag-root").should("have.attr", "aria-description", `${TAG_SUCCESS.defaultText}`); + + cy.get("#noninteractiveTag").shadow().find(".ui5-hidden-text").should("have.text", `${TAG_DESCRIPTION_TAG.defaultText} ${TAG_SUCCESS.defaultText}`); + }); + + it("tests that label is rendered if there is text content", () => { + cy.mount(html` + bigger width + `); + + cy.get("[ui5-tag]").shadow().find(".ui5-tag-text").should("exist"); + }); + + it("tests that label is NOT rendered if there is only icon", () => { + cy.mount(html` + + `); + + cy.get("[ui5-tag]").shadow().find(".ui5-tag-text").should("not.exist"); + }); + }); + + describe("Wrapping", () => { + it("tests if tag text wraps - default wrappingType", () => { + cy.mount(html` + Some long text with more lines text wrapping-type="Normal" + `); + + cy.get("#tagWithWrappingDefault").shadow().find(".ui5-tag-root").should("have.css", "white-space", "normal"); + }); + + it("tests if tag text wraps - wrappingType Normal", () => { + cy.mount(html` + Some long text with more lines text wrapping-type="Normal" + `); + + cy.get("#tagWithWrappingNormal").shadow().find(".ui5-tag-root").should("have.css", "white-space", "normal"); + }); + + it("tests if tag text wraps - wrappingType None", () => { + cy.mount(html` + Some long text with more lines text wrapping-type="None" + `); + + cy.get("#tagWithWrappingNone").shadow().find(".ui5-tag-root").should("have.css", "white-space", "nowrap"); + }); + }); +}); diff --git a/packages/main/cypress/specs/Text.cy.ts b/packages/main/cypress/specs/Text.cy.ts new file mode 100644 index 000000000000..432de066d27f --- /dev/null +++ b/packages/main/cypress/specs/Text.cy.ts @@ -0,0 +1,31 @@ +import { html } from "lit"; +import "../../src/Text.js"; + +describe("Text", () => { + it("tests root element is bdi", () => { + cy.mount(html`Text`); + cy.get("[ui5-text]").shadow().find(":first-child").should("have.prop", "tagName", "SPAN"); + }); + + it("tests default wrapping behavior", () => { + cy.mount(html`Text`); + cy.get("[ui5-text]").should("have.css", "word-wrap", "break-word"); + }); + + it("tests maxLines default behavior", () => { + cy.mount(html`Text`); + cy.get("[ui5-text]").should("have.css", "-webkit-line-clamp", "none"); + }); + + it("tests maxLines", () => { + cy.mount(html`Text`); + cy.get("[ui5-text]").should("have.css", "-webkit-line-clamp", "1"); + }); + + it("tests emptyIndicatorMode", () => { + cy.mount(html``); + + cy.get("[ui5-text]").shadow().find(".empty-indicator").should("have.text", "–"); + cy.get("[ui5-text]").shadow().find(".empty-indicator-aria-label").should("have.text", "Empty Value"); + }); +}); diff --git a/packages/main/cypress/specs/Title.cy.ts b/packages/main/cypress/specs/Title.cy.ts new file mode 100644 index 000000000000..9fc3a5d0c19a --- /dev/null +++ b/packages/main/cypress/specs/Title.cy.ts @@ -0,0 +1,37 @@ +import { html } from "lit"; +import "../../src/Title.js"; + +describe("Title", () => { + describe("Rendering ", () => { + it("h{n} tags rendered correctly", () => { + cy.mount(html`Title Size 1`); + cy.get("#titleH1").shadow().find("h1").should("exist"); + + cy.mount(html`Title Size Auto (2)`); + cy.get("#titleAuto").shadow().find("h2").should("exist"); + + cy.mount(html`Title Size 2`); + cy.get("#titleH2").shadow().find("h2").should("exist"); + + cy.mount(html`Title Size 3`); + cy.get("#titleH3").shadow().find("h3").should("exist"); + + cy.mount(html`Title Size 4`); + cy.get("#titleH4").shadow().find("h4").should("exist"); + + cy.mount(html`Title Size 5`); + cy.get("#titleH5").shadow().find("h5").should("exist"); + + cy.mount(html`Title Size 6`); + cy.get("#titleH6").shadow().find("h6").should("exist"); + }); + + it("should wrap the text of the title", () => { + cy.mount(html`Wrapping Title Lorem Ipsum Dolor, Sit Amet Consectetur Adipisicing Elit. Numquam, Ab.`); + cy.get("#wrapping-title").should("have.css", "height", "64px"); + + cy.mount(html`Truncated Title Lorem Ipsum Dolor, Sit Amet Consectetur Adipisicing Elit. Numquam, Ab.`); + cy.get("#truncated-title").should("have.css", "height", "16px"); + }); + }); +}); From 475c293fe5797aee9dd8a160d69c7baa118a6f07 Mon Sep 17 00:00:00 2001 From: Martin Date: Tue, 21 Jan 2025 14:47:30 +0200 Subject: [PATCH 42/42] fix(ui5-wizard): replace resize observer with container query (#7996) Related to: #7666 --- packages/fiori/src/Wizard.ts | 22 --------- packages/fiori/src/themes/Wizard.css | 61 ++++++++++++++---------- packages/fiori/test/specs/Wizard.spec.js | 21 -------- 3 files changed, 37 insertions(+), 67 deletions(-) diff --git a/packages/fiori/src/Wizard.ts b/packages/fiori/src/Wizard.ts index 7277164bed70..bde17115f802 100644 --- a/packages/fiori/src/Wizard.ts +++ b/packages/fiori/src/Wizard.ts @@ -55,23 +55,12 @@ const STEP_SWITCH_THRESHOLDS = { MAX: 1, }; -type ResponsiveBreakpoints = { - [key: string]: string, -} - type WizardStepChangeEventDetail = { step: WizardStep, previousStep: WizardStep, withScroll: boolean, } -const RESPONSIVE_BREAKPOINTS: ResponsiveBreakpoints = { - "0": "S", - "599": "M", - "1023": "L", - "1439": "XL", -}; - type AccessibilityInformation = { ariaSetsize: number, ariaPosinset: number, @@ -257,9 +246,6 @@ class Wizard extends UI5Element { @property({ type: Array }) _groupedTabs: Array = []; - @property() - _breakpoint?: string - /** * Defines the steps. * @@ -486,8 +472,6 @@ class Wizard extends UI5Element { this._prevWidth = this.width; this._prevContentHeight = this.contentHeight; - - this._calcCurrentBreakpoint(); } attachStepsResizeObserver() { @@ -503,12 +487,6 @@ class Wizard extends UI5Element { }); } - _calcCurrentBreakpoint() { - const breakpointDimensions = Object.keys(RESPONSIVE_BREAKPOINTS).reverse(); - const breakpoint = breakpointDimensions.find((size: string) => Number(size) < this.width!); - this._breakpoint = breakpoint ? RESPONSIVE_BREAKPOINTS[breakpoint] : RESPONSIVE_BREAKPOINTS["0"]; - } - /** * Updates the expanded attribute for each ui5-wizard-tab based on the ui5-wizard width * @private diff --git a/packages/fiori/src/themes/Wizard.css b/packages/fiori/src/themes/Wizard.css index 7864833f73b5..f62067abc7c1 100644 --- a/packages/fiori/src/themes/Wizard.css +++ b/packages/fiori/src/themes/Wizard.css @@ -5,30 +5,43 @@ height: 100%; width: 100%; overflow: auto; -} - -:host([_breakpoint="S"])::part(navigator), -:host([_breakpoint="S"])::part(step-content) { - padding-left: 1rem; - padding-right: 1rem; -} - -:host([_breakpoint="M"])::part(navigator), -:host([_breakpoint="M"])::part(step-content) { - padding-left: 2rem; - padding-right: 2rem; -} - -:host([_breakpoint="L"])::part(navigator), -:host([_breakpoint="L"])::part(step-content) { - padding-left: 2rem; - padding-right: 2rem; -} - -:host([_breakpoint="XL"])::part(navigator), -:host([_breakpoint="XL"])::part(step-content) { - padding-left: 3rem; - padding-right: 3rem; + container-type: inline-size; +} + +/* S Size */ +@container (max-width: 599px) { + :host::part(navigator), + :host::part(step-content) { + padding-left: 1rem; + padding-right: 1rem; + } +} + +/* M Size */ +@container (min-width: 600px) and (max-width: 1023px) { + :host::part(navigator), + :host::part(step-content) { + padding-left: 2rem; + padding-right: 2rem; + } +} + +/* L Size */ +@container (min-width: 1024px) and (max-width: 1439px) { + :host::part(navigator), + :host::part(step-content) { + padding-left: 2rem; + padding-right: 2rem; + } +} + +/* XL Size */ +@container (min-width: 1440px) { + :host::part(navigator), + :host::part(step-content) { + padding-left: 3rem; + padding-right: 3rem; + } } .ui5-wiz-root { diff --git a/packages/fiori/test/specs/Wizard.spec.js b/packages/fiori/test/specs/Wizard.spec.js index d7308931f7a0..f5b6cd60489d 100644 --- a/packages/fiori/test/specs/Wizard.spec.js +++ b/packages/fiori/test/specs/Wizard.spec.js @@ -404,27 +404,6 @@ describe("Wizard general interaction", () => { assert.ok(await disabledPopover.isDisplayedInViewport(), "Popover is opened."); }); - it("tests responsive paddings", async () => { - await browser.url(`test/pages/Wizard.html`); - const wizard = $("#wiz"); - - // resize window S - await browser.setWindowSize(500, 1000); - assert.strictEqual(await wizard.getProperty("_breakpoint"), "S", "Small breakpoint is enabled"); - - // resize window M - await browser.setWindowSize(1000, 1000); - assert.strictEqual(await wizard.getProperty("_breakpoint"), "M", "Medium breakpoint is enabled"); - - // resize window L - await browser.setWindowSize(1200, 1000); - assert.strictEqual(await wizard.getProperty("_breakpoint"), "L", "Large breakpoint is enabled"); - - // resize window XL - await browser.setWindowSize(1600, 1000); - assert.strictEqual(await wizard.getProperty("_breakpoint"), "XL", "Extra Large breakpoint is enabled"); - }); - it("WizardPageMode: move to next step", async () => { await browser.url(`test/pages/WizardPageMode_test.html`);