diff --git a/packages/react/src/component-tests/IcStepper/IcStepper.cy.tsx b/packages/react/src/component-tests/IcStepper/IcStepper.cy.tsx index c184358ffbb..1144035ee2d 100644 --- a/packages/react/src/component-tests/IcStepper/IcStepper.cy.tsx +++ b/packages/react/src/component-tests/IcStepper/IcStepper.cy.tsx @@ -3,6 +3,7 @@ import React from "react"; import { mount } from "cypress/react"; +import { IcStep, IcStepper } from "../../components"; import { FullWidth, Compact, @@ -319,3 +320,48 @@ describe("IcStepper visual regression tests in high contrast mode", () => { }); }); }); + +describe("IcStepper text resize accessibility regression", () => { + afterEach(() => { + cy.document().then((doc) => { + doc.documentElement.style.fontSize = ""; + }); + cy.task("generateReport"); + }); + + it("switches to compact mode at 200% text size without horizontal overflow", () => { + cy.viewport(800, 600); + cy.injectAxe(); + mount( +
+ + + + + + +
+ ); + cy.checkHydrated(STEPPER_SELECTOR); + + cy.document().then((doc) => { + doc.documentElement.style.fontSize = "32px"; + }); + + cy.get(STEPPER_SELECTOR).should("have.class", "ic-stepper-compact"); + + cy.get("#text-resize-stepper-container").then(($container) => { + const container = $container[0]; + expect(container.scrollWidth).to.be.at.most(container.clientWidth); + }); + + cy.checkA11yWithWait(); + cy.compareSnapshot({ + name: "/text-resize-200-percent", + testThreshold: setThresholdBasedOnEnv(DEFAULT_TEST_THRESHOLD + 0.015), + }); + }); +}); diff --git a/packages/web-components/src/components/ic-stepper/ic-stepper.tsx b/packages/web-components/src/components/ic-stepper/ic-stepper.tsx index 3d4cbb29762..86d1f6ee388 100644 --- a/packages/web-components/src/components/ic-stepper/ic-stepper.tsx +++ b/packages/web-components/src/components/ic-stepper/ic-stepper.tsx @@ -320,17 +320,22 @@ export class Stepper { }); }; + private getMinimumDefaultStepperWidth = (): number => { + const rootFontSize = + parseFloat(getComputedStyle(document.documentElement).fontSize) || 16; + const baseStepWidth = + this.aligned === "left" && + this.connectorWidth && + this.connectorWidth > 100 + ? this.connectorWidth + 48 + : 148; + + return (baseStepWidth / 16) * rootFontSize * this.steps.length; + }; + private overrideVariant = () => { if (this.variantOverride) { - let minDefaultStepperWidth = 148 * this.steps.length; - - if ( - this.aligned === "left" && - this.connectorWidth && - this.connectorWidth > 100 - ) { - minDefaultStepperWidth = (this.connectorWidth + 48) * this.steps.length; - } + const minDefaultStepperWidth = this.getMinimumDefaultStepperWidth(); if (this.el.clientWidth < minDefaultStepperWidth) { this.variant = "compact"; } else { @@ -339,8 +344,13 @@ export class Stepper { } }; + private observeSteps = () => { + this.steps.forEach((step) => this.resizeObserver?.observe(step)); + }; + private resizeObserverCallback = () => { this.getChildren(); + this.observeSteps(); this.checkStepTitles(); this.overrideVariant(); this.setStepperWidth(); @@ -353,6 +363,7 @@ export class Stepper { this.resizeObserverCallback(); }); this.resizeObserver.observe(this.el); + this.observeSteps(); }; render() { diff --git a/packages/web-components/src/components/ic-stepper/test/basic/ic-stepper.spec.ts b/packages/web-components/src/components/ic-stepper/test/basic/ic-stepper.spec.ts index 7b95a478808..1d1355ad321 100644 --- a/packages/web-components/src/components/ic-stepper/test/basic/ic-stepper.spec.ts +++ b/packages/web-components/src/components/ic-stepper/test/basic/ic-stepper.spec.ts @@ -1034,3 +1034,61 @@ describe("switch between the compact and default stepper depending on whether th }); }); }); + +const textResizeStepperMarkup = ` + + + + + + `; + +describe("ic-stepper text resize", () => { + const mockRootFontSize = (fontSize: string) => { + jest + .spyOn(globalThis, "getComputedStyle") + .mockReturnValue({ fontSize } as CSSStyleDeclaration); + }; + + afterEach(() => { + jest.restoreAllMocks(); + }); + + it("scales the automatic compact breakpoint with the root font size", async () => { + const page = await newSpecPage({ + components: [Stepper, Step], + html: textResizeStepperMarkup, + }); + + mockRootFontSize("32px"); + + Object.defineProperty(page.root, "clientWidth", { + configurable: true, + value: 700, + }); + + page.rootInstance.getChildren(); + page.rootInstance.overrideVariant(); + + expect(page.rootInstance.variant).toBe("compact"); + }); + + it("keeps the default variant at the same width with the normal root font size", async () => { + const page = await newSpecPage({ + components: [Stepper, Step], + html: textResizeStepperMarkup, + }); + + mockRootFontSize("16px"); + + Object.defineProperty(page.root, "clientWidth", { + configurable: true, + value: 700, + }); + + page.rootInstance.getChildren(); + page.rootInstance.overrideVariant(); + + expect(page.rootInstance.variant).toBe("default"); + }); +});