diff --git a/packages/main/cypress/specs/RatingIndicator.cy.tsx b/packages/main/cypress/specs/RatingIndicator.cy.tsx
index c0eafc8ab876..6af958374c92 100644
--- a/packages/main/cypress/specs/RatingIndicator.cy.tsx
+++ b/packages/main/cypress/specs/RatingIndicator.cy.tsx
@@ -1,39 +1,116 @@
import RatingIndicator from "../../src/RatingIndicator.js";
import { RATING_INDICATOR_ARIA_DESCRIPTION } from "../../src/generated/i18n/i18n-defaults.js";
+import "@ui5/webcomponents-icons/dist/heart.js";
+import "@ui5/webcomponents-icons/dist/heart-2.js";
+import "@ui5/webcomponents-icons/dist/thumb-up.js";
+import "@ui5/webcomponents-icons/dist/thumb-down.js";
describe("RatingIndicator", () => {
- describe("Half Icon appearance", () => {
- it("Half icon should be filled when rating indicator is disabled", () => {
- const attributeValue = "favorite";
+ describe("Custom Icons", () => {
+ it("should render default icons when no custom icons are specified", () => {
+ cy.mount();
- cy.mount();
+ cy.get("[ui5-rating-indicator]")
+ .shadow()
+ .find(".ui5-rating-indicator-item-sel [ui5-icon]")
+ .first()
+ .should("have.attr", "name", "favorite");
+
+ cy.get("[ui5-rating-indicator]")
+ .shadow()
+ .find(".ui5-rating-indicator-item-unsel [ui5-icon]")
+ .first()
+ .should("have.attr", "name", "unfavorite");
+ });
+
+ it("should render custom icons for selected and unselected states", () => {
+ cy.mount();
+
+ cy.get("[ui5-rating-indicator]")
+ .shadow()
+ .find(".ui5-rating-indicator-item-sel [ui5-icon]")
+ .first()
+ .should("have.attr", "name", "heart");
+
+ cy.get("[ui5-rating-indicator]")
+ .shadow()
+ .find(".ui5-rating-indicator-item-unsel [ui5-icon]")
+ .first()
+ .should("have.attr", "name", "heart-2");
+ });
+
+ it("should render custom icon with default unselected icon when only iconSelected is specified", () => {
+ cy.mount();
+
+ cy.get("[ui5-rating-indicator]")
+ .shadow()
+ .find(".ui5-rating-indicator-item-sel [ui5-icon]")
+ .first()
+ .should("have.attr", "name", "thumb-up");
+
+ cy.get("[ui5-rating-indicator]")
+ .shadow()
+ .find(".ui5-rating-indicator-item-unsel [ui5-icon]")
+ .first()
+ .should("have.attr", "name", "unfavorite");
+ });
+
+ it("should render custom unselected icon with default selected icon when only iconUnselected is specified", () => {
+ cy.mount();
+
+ cy.get("[ui5-rating-indicator]")
+ .shadow()
+ .find(".ui5-rating-indicator-item-sel [ui5-icon]")
+ .first()
+ .should("have.attr", "name", "favorite");
cy.get("[ui5-rating-indicator]")
.shadow()
- .find(".ui5-rating-indicator-item-half [ui5-icon]")
- .should("have.attr", "name", attributeValue);
+ .find(".ui5-rating-indicator-item-unsel [ui5-icon]")
+ .first()
+ .should("have.attr", "name", "thumb-down");
});
- it("Half icon should be filled when rating indicator is readonly", () => {
- const attributeValue = "favorite";
+ it("should render custom icons in half-star state", () => {
+ cy.mount();
- cy.mount();
+ cy.get("[ui5-rating-indicator]")
+ .shadow()
+ .find(".ui5-rating-indicator-item-half .ui5-rating-indicator-half-icon-left [ui5-icon]")
+ .should("have.attr", "name", "heart");
cy.get("[ui5-rating-indicator]")
.shadow()
- .find(".ui5-rating-indicator-item-half [ui5-icon]")
- .should("have.attr", "name", attributeValue);
+ .find(".ui5-rating-indicator-item-half .ui5-rating-indicator-half-icon-right [ui5-icon]")
+ .should("have.attr", "name", "heart-2");
});
- it("Half icon should be border only when rating indicator is regular", () => {
- const attributeValue = "unfavorite";
+ it("should render custom icon (filled) in half-star state when readonly", () => {
+ cy.mount();
- cy.mount();
+ cy.get("[ui5-rating-indicator]")
+ .shadow()
+ .find(".ui5-rating-indicator-item-half .ui5-rating-indicator-half-icon-left [ui5-icon]")
+ .should("have.attr", "name", "heart");
+
+ cy.get("[ui5-rating-indicator]")
+ .shadow()
+ .find(".ui5-rating-indicator-item-half .ui5-rating-indicator-half-icon-right [ui5-icon]")
+ .should("have.attr", "name", "heart");
+ });
+
+ it("should render custom icon (filled) in half-star state when disabled", () => {
+ cy.mount();
+
+ cy.get("[ui5-rating-indicator]")
+ .shadow()
+ .find(".ui5-rating-indicator-item-half .ui5-rating-indicator-half-icon-left [ui5-icon]")
+ .should("have.attr", "name", "heart");
cy.get("[ui5-rating-indicator]")
.shadow()
- .find(".ui5-rating-indicator-item-half [ui5-icon]")
- .should("have.attr", "name", attributeValue);
+ .find(".ui5-rating-indicator-item-half .ui5-rating-indicator-half-icon-right [ui5-icon]")
+ .should("have.attr", "name", "heart");
});
});
diff --git a/packages/main/src/RatingIndicator.ts b/packages/main/src/RatingIndicator.ts
index f9f2793f1831..976dee370ed9 100644
--- a/packages/main/src/RatingIndicator.ts
+++ b/packages/main/src/RatingIndicator.ts
@@ -177,6 +177,25 @@ class RatingIndicator extends UI5Element {
@property()
tooltip?: string;
+ /**
+ * Defines the icon to be displayed for the selected (filled) rating symbol.
+ *
+ * @default "favorite"
+ * @public
+ * @since 2.20
+ */
+ @property()
+ iconSelected?: string;
+
+ /**
+ * Defines the icon to be displayed for the unselected (empty) rating symbol.
+ * @default "unfavorite"
+ * @public
+ * @since 2.20
+ */
+ @property()
+ iconUnselected?: string;
+
/**
* @private
*/
@@ -341,6 +360,14 @@ class RatingIndicator extends UI5Element {
get ariaReadonly() {
return this.readonly ? "true" : undefined;
}
+
+ get effectiveIconSelected() {
+ return this.iconSelected || "favorite";
+ }
+
+ get effectiveIconUnselected() {
+ return this.iconUnselected || "unfavorite";
+ }
}
RatingIndicator.define();
diff --git a/packages/main/src/RatingIndicatorTemplate.tsx b/packages/main/src/RatingIndicatorTemplate.tsx
index 80fd0aa8f4bb..d5843ec80a8f 100644
--- a/packages/main/src/RatingIndicatorTemplate.tsx
+++ b/packages/main/src/RatingIndicatorTemplate.tsx
@@ -1,8 +1,6 @@
import type RatingIndicator from "./RatingIndicator.js";
import type { Star } from "./RatingIndicator.js";
import Icon from "./Icon.js";
-import favorite from "@ui5/webcomponents-icons/dist/favorite.js";
-import unfavorite from "@ui5/webcomponents-icons/dist/unfavorite.js";
export default function RatingIndicatorTemplate(this: RatingIndicator) {
return (
@@ -37,38 +35,40 @@ function starLi(this: RatingIndicator, star: Star) {
if (star.selected) {
return (
-
+
);
} if (star.halfStar) {
return (
-
-
-
+
+
+
+
+
);
} if (this.readonly) {
return (
-
+
);
} if (this.disabled) {
return (
-
+
);
}
return (
-
+
);
}
function halfStarIconName(this: RatingIndicator) {
- return this.disabled || this.readonly ? favorite : unfavorite;
+ return this.disabled || this.readonly ? this.effectiveIconSelected : this.effectiveIconUnselected;
}
diff --git a/packages/main/src/themes/RatingIndicator.css b/packages/main/src/themes/RatingIndicator.css
index 30e759f2691c..f587d87b7a0b 100644
--- a/packages/main/src/themes/RatingIndicator.css
+++ b/packages/main/src/themes/RatingIndicator.css
@@ -91,21 +91,35 @@
}
.ui5-rating-indicator-item.ui5-rating-indicator-item-half {
- color: var(--sapContent_UnratedColor);
+ display: flex;
+ flex-direction: row;
+}
+
+.ui5-rating-indicator-half-icon-wrapper {
+ width: 50%;
+ height: 100%;
+ overflow: hidden;
+ position: relative;
}
-.ui5-rating-indicator-item [ui5-icon].ui5-rating-indicator-half-icon {
+.ui5-rating-indicator-half-icon-wrapper [ui5-icon] {
position: absolute;
- inset-inline-start: 50%;
+ width: var(--_ui5_rating_indicator_item_width);
+ height: var(--_ui5_rating_indicator_item_height);
+}
+
+.ui5-rating-indicator-half-icon-left {
color: var(--sapContent_RatedColor);
}
-.ui5-rating-indicator-half-icon-wrapper {
- width: 100%;
- height: 100%;
- position: absolute;
- inset-inline-start: -50%;
- top: 0;
- z-index: 32;
- overflow: hidden;
-}
\ No newline at end of file
+.ui5-rating-indicator-half-icon-left [ui5-icon] {
+ inset-inline-start: 0;
+}
+
+.ui5-rating-indicator-half-icon-right {
+ color: var(--sapContent_UnratedColor);
+}
+
+.ui5-rating-indicator-half-icon-right [ui5-icon] {
+ inset-inline-end: 0;
+}
diff --git a/packages/main/test/pages/RatingIndicator.html b/packages/main/test/pages/RatingIndicator.html
index 700648e3db52..f9b4568f774c 100644
--- a/packages/main/test/pages/RatingIndicator.html
+++ b/packages/main/test/pages/RatingIndicator.html
@@ -134,6 +134,32 @@
sizes
+
+
Custom Icons - Hearts
+
+
+
+
+
Custom Icons - Thumbs Up
+
+
+
+
+
Custom Icons - Hearts (readonly)
+
+
+
+
+
Custom Icons - Hearts (disabled)
+
+
+
+
+
Custom Icons - Only selected icon (circles)
+
+
+
+
+