Skip to content
Open
134 changes: 134 additions & 0 deletions packages/fiori/cypress/specs/ProductSwitch.cy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,26 @@ describe("List - getFocusDomRef Method", () => {
});

describe("ProductSwitch general interaction", () => {
it("tests 2-column desktop layout", () => {
cy.mount(
<ProductSwitch>
<ProductSwitchItem titleText="Home" subtitleText="Central Home" icon="home"></ProductSwitchItem>
<ProductSwitchItem titleText="Analytics Cloud" subtitleText="Analytics Cloud" icon="business-objects-experience"></ProductSwitchItem>
</ProductSwitch>
);

cy.get("[ui5-product-switch]")
.should("have.attr", "desktop-columns", "2")
.invoke("prop", "items")
.should("have.length", 2)
.should("have.length.at.most", 2);

cy.get("[ui5-product-switch]")
.shadow()
.find(".ui5-product-switch-root")
.should("have.css", "width", "376px");
});

it("tests 3-column desktop layout", () => {
cy.mount(
<ProductSwitch desktopColumns={3}>
Expand Down Expand Up @@ -152,3 +172,117 @@ describe("ProductSwitch styles", () => {
.should("have.css", "align-items", "center");
});
});

describe("ProductSwitchItem text wrapping", () => {
it("title and subtitle wrap freely without truncation", () => {
cy.mount(
<ProductSwitch>
<ProductSwitchItem
id="longItem"
titleText="Analytics Cloud toooooo long text that must wrap onto multiple lines"
subtitleText="Analytics Cloud again toooooo long subtitle that must also wrap freely"
icon="business-objects-experience"
></ProductSwitchItem>
<ProductSwitchItem
id="shortItem"
titleText="Home"
subtitleText="Central Home"
icon="home"
></ProductSwitchItem>
</ProductSwitch>
);

cy.get("#longItem")
.shadow()
.find(".ui5-product-switch-item-title")
.should("have.css", "white-space", "normal")
.should("not.have.css", "text-overflow", "ellipsis");

cy.get("#longItem")
.shadow()
.find(".ui5-product-switch-item-subtitle")
.should("have.css", "white-space", "normal")
.should("not.have.css", "text-overflow", "ellipsis");

// text is not clipped — the rendered scroll height fits the visible height
cy.get("#longItem")
.shadow()
.find(".ui5-product-switch-item-title")
.then($el => {
const el = $el[0];
expect(el.scrollHeight).to.equal(el.clientHeight);
});
});

it("host grows vertically when text wraps", () => {
cy.mount(
<ProductSwitch>
<ProductSwitchItem
id="longItem"
titleText="Analytics Cloud toooooo long text that must wrap onto multiple lines"
subtitleText="Analytics Cloud again toooooo long subtitle that must also wrap freely"
icon="business-objects-experience"
></ProductSwitchItem>
<ProductSwitchItem
id="shortItem"
titleText="Home"
subtitleText="Central Home"
icon="home"
></ProductSwitchItem>
</ProductSwitch>
);

// the long-text item's host renders taller than the default 7rem (112px) baseline
cy.get("#longItem").then($long => {
expect($long[0].getBoundingClientRect().height).to.be.greaterThan(112);
});
});

it("items in the same row stretch to the tallest sibling", () => {
cy.mount(
<ProductSwitch>
<ProductSwitchItem
id="longItem"
titleText="Analytics Cloud toooooo long text that must wrap onto multiple lines"
subtitleText="Analytics Cloud again toooooo long subtitle that must also wrap freely"
icon="business-objects-experience"
></ProductSwitchItem>
<ProductSwitchItem
id="shortItem"
titleText="Home"
subtitleText="Central Home"
icon="home"
></ProductSwitchItem>
</ProductSwitch>
);

cy.get("#longItem").then($long => {
cy.get("#shortItem").then($short => {
expect($short[0].getBoundingClientRect().height)
.to.equal($long[0].getBoundingClientRect().height);
});
});
});

it("title-only item wraps freely (no 2-line clamp)", () => {
cy.mount(
<ProductSwitch>
<ProductSwitchItem
id="titleOnly"
titleText="A very long title without any subtitle that should wrap onto more than two lines when the copy is long enough to require it"
icon="home"
></ProductSwitchItem>
</ProductSwitch>
);

cy.get("#titleOnly")
.shadow()
.find(".ui5-product-switch-item-title")
.should("have.css", "white-space", "normal")
.then($title => {
const el = $title[0];
// nothing is clipped
expect(el.scrollHeight).to.equal(el.clientHeight);
});
});
});
10 changes: 9 additions & 1 deletion packages/fiori/src/ProductSwitch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,14 +126,22 @@ class ProductSwitch extends UI5Element {
}

onBeforeRendering() {
this.desktopColumns = this.items.length > 6 ? 4 : 3;
if (this.items.length > 6) {
this.desktopColumns = 4;
} else if (this.items.length <= 2) {
this.desktopColumns = 2;
} else {
this.desktopColumns = 3;
}
}

_handleResize() {
const documentWidth = document.body.clientWidth;

if (documentWidth <= (this.constructor as typeof ProductSwitch).ROW_MIN_WIDTH.ONE_COLUMN) {
this._setRowSize(1);
} else if (this.items.length <= 2) {
this._setRowSize(2);
} else if (documentWidth <= (this.constructor as typeof ProductSwitch).ROW_MIN_WIDTH.THREE_COLUMN || this.items.length <= 6) {
this._setRowSize(3);
} else {
Expand Down
7 changes: 6 additions & 1 deletion packages/fiori/src/themes/ProductSwitch.css
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@
width: 564px; /* 3 * item size */
}

:host([desktop-columns="2"]) .ui5-product-switch-root {
width: 376px; /* 2 * item size */
}

@media only screen and (max-width: 900px) {
.ui5-product-switch-root {
width: 564px; /* 3 * item size */
Expand All @@ -24,7 +28,8 @@

@media only screen and (max-width: 600px) {
.ui5-product-switch-root,
:host([desktop-columns="3"]) .ui5-product-switch-root {
:host([desktop-columns="3"]) .ui5-product-switch-root,
:host([desktop-columns="2"]) .ui5-product-switch-root {
flex-direction: column;
padding: 0;
width: 100%;
Expand Down
17 changes: 5 additions & 12 deletions packages/fiori/src/themes/ProductSwitchItem.css
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
:host {
width: var(--_ui5_product_switch_item_width);
height: var(--_ui5_product_switch_item_height);
min-height: var(--_ui5_product_switch_item_height);
margin: .25rem;
border-radius: .25rem;
box-sizing: border-box;
Expand Down Expand Up @@ -88,9 +88,8 @@
.ui5-product-switch-item-root .ui5-product-switch-item-text-content .ui5-product-switch-item-subtitle,
.ui5-product-switch-item-root .ui5-product-switch-item-text-content .ui5-product-switch-item-title {
line-height: 1.25rem;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
white-space: normal;
overflow-wrap: break-word;
max-width: 100%;
pointer-events: none;
text-align: center;
Expand All @@ -101,13 +100,6 @@
color:var(--sapGroup_TitleTextColor);
}

.ui5-product-switch-item-root .ui5-product-switch-item-text-content .ui5-product-switch-item-title:only-child {
white-space: normal;
-webkit-line-clamp: 2;
display: -webkit-box;
-webkit-box-orient: vertical;
}

.ui5-product-switch-item-root .ui5-product-switch-item-text-content .ui5-product-switch-item-subtitle {
font-size:var(--sapFontSmallSize);
color:var(--sapContent_LabelColor);
Expand All @@ -119,7 +111,8 @@
width: 100%;
width: 100%;
max-width: 600px;
height: 5rem;
min-height: 5rem;
height: auto;
border-radius: 0;
}

Expand Down
5 changes: 5 additions & 0 deletions packages/fiori/test/pages/ProductSwitch.html
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@
<ui5-product-switch-item title-text="Analytics Cloud" subtitle-text="Analytics Cloud" icon="business-objects-experience"></ui5-product-switch-item>
</ui5-product-switch>

<ui5-product-switch id="productSwitchTextWrapping">
<ui5-product-switch-item title-text="Analytics Cloud Intelligence" subtitle-text="Business intelligence and reporting" icon="business-objects-experience"></ui5-product-switch-item>
<ui5-product-switch-item title-text="Home" subtitle-text="Central Home" icon="home"></ui5-product-switch-item>
</ui5-product-switch>

<ui5-input id="eventTest"></ui5-input>

<script>
Expand Down
Loading