From 107956644ca9d087aaf0b97d872ffb90463f4cd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Ferreira?= Date: Tue, 9 Sep 2025 15:55:36 +0100 Subject: [PATCH 1/7] - calculate scroll having into consideration dir value; --- core/src/components/segment-view/segment-view.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/core/src/components/segment-view/segment-view.tsx b/core/src/components/segment-view/segment-view.tsx index 633d9a37d39..55d17dd8e31 100644 --- a/core/src/components/segment-view/segment-view.tsx +++ b/core/src/components/segment-view/segment-view.tsx @@ -39,7 +39,8 @@ export class SegmentView implements ComponentInterface { @Listen('scroll') handleScroll(ev: Event) { const { scrollLeft, scrollWidth, clientWidth } = ev.target as HTMLElement; - const scrollRatio = scrollLeft / (scrollWidth - clientWidth); + const isRTL = window.getComputedStyle(this.el).direction === 'rtl'; + const scrollRatio = (isRTL ? -1 : 1) * scrollLeft / (scrollWidth - clientWidth); this.ionSegmentViewScroll.emit({ scrollRatio, @@ -118,6 +119,7 @@ export class SegmentView implements ComponentInterface { async setContent(id: string, smoothScroll = true) { const contents = this.getSegmentContents(); const index = contents.findIndex((content) => content.id === id); + const isRTL = window.getComputedStyle(this.el).direction === 'rtl'; if (index === -1) return; @@ -127,7 +129,7 @@ export class SegmentView implements ComponentInterface { const contentWidth = this.el.offsetWidth; this.el.scrollTo({ top: 0, - left: index * contentWidth, + left: (isRTL ? -1 : 1) * index * contentWidth, behavior: smoothScroll ? 'smooth' : 'instant', }); } From 0596d4d55962fa355c13b7cff636fbbb30e9f587 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Ferreira?= Date: Tue, 9 Sep 2025 17:49:39 +0100 Subject: [PATCH 2/7] - add page with dir="rtl"; - lint.fix; - reconfig the basic-tests to look into rlt too; --- .../components/segment-view/segment-view.tsx | 2 +- .../test/basic/segment-view.e2e.ts | 4 +- .../segment-view/test/rtl/index.html | 194 ++++++++++++++++++ 3 files changed, 197 insertions(+), 3 deletions(-) create mode 100644 core/src/components/segment-view/test/rtl/index.html diff --git a/core/src/components/segment-view/segment-view.tsx b/core/src/components/segment-view/segment-view.tsx index 55d17dd8e31..b8165144ad2 100644 --- a/core/src/components/segment-view/segment-view.tsx +++ b/core/src/components/segment-view/segment-view.tsx @@ -40,7 +40,7 @@ export class SegmentView implements ComponentInterface { handleScroll(ev: Event) { const { scrollLeft, scrollWidth, clientWidth } = ev.target as HTMLElement; const isRTL = window.getComputedStyle(this.el).direction === 'rtl'; - const scrollRatio = (isRTL ? -1 : 1) * scrollLeft / (scrollWidth - clientWidth); + const scrollRatio = (isRTL ? -1 : 1) * (scrollLeft / (scrollWidth - clientWidth)); this.ionSegmentViewScroll.emit({ scrollRatio, diff --git a/core/src/components/segment-view/test/basic/segment-view.e2e.ts b/core/src/components/segment-view/test/basic/segment-view.e2e.ts index 447a60be309..e7b14856683 100644 --- a/core/src/components/segment-view/test/basic/segment-view.e2e.ts +++ b/core/src/components/segment-view/test/basic/segment-view.e2e.ts @@ -2,9 +2,9 @@ import { expect } from '@playwright/test'; import { configs, test } from '@utils/test/playwright'; /** - * This behavior does not vary across modes/directions + * This behavior does not vary across modes */ -configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => { +configs({ modes: ['md'] }).forEach(({ title, config }) => { test.describe(title('segment-view: basic'), () => { test('should show the first content with no initial value', async ({ page }) => { await page.setContent( diff --git a/core/src/components/segment-view/test/rtl/index.html b/core/src/components/segment-view/test/rtl/index.html new file mode 100644 index 00000000000..81196da25ff --- /dev/null +++ b/core/src/components/segment-view/test/rtl/index.html @@ -0,0 +1,194 @@ + + + + + RTL Segment View - Basic + + + + + + + + + + + + + + + RTL Segment View - Basic + + + + + + + No + + + Value + + + + No + Value + + + + + Paid + + + Free + + + Top + + + + + Free + Top + + + + + Orange + + + Banana + + + Pear + + + Peach + + + Grape + + + Mango + + + Apple + + + Strawberry + + + Cherry + + + + Orange + Banana + Pear + Peach + Grape + Mango + Apple + Strawberry + Cherry + + + + + + + + + + + + Footer + + + + + + + From c6054409498f0345aaa0d269a45ceef1b2620f3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Ferreira?= Date: Wed, 10 Sep 2025 13:15:47 +0100 Subject: [PATCH 3/7] - fix duplicated test; --- .../test/basic/segment-view.e2e.ts | 140 +++++++++--------- 1 file changed, 70 insertions(+), 70 deletions(-) diff --git a/core/src/components/segment-view/test/basic/segment-view.e2e.ts b/core/src/components/segment-view/test/basic/segment-view.e2e.ts index e7b14856683..649e3b5b2af 100644 --- a/core/src/components/segment-view/test/basic/segment-view.e2e.ts +++ b/core/src/components/segment-view/test/basic/segment-view.e2e.ts @@ -88,86 +88,86 @@ configs({ modes: ['md'] }).forEach(({ title, config }) => { const segmentContent = page.locator('ion-segment-content[id="top"]'); await expect(segmentContent).toBeInViewport(); }); - }); - test('should set correct segment button as checked when changing the value by scrolling the segment content', async ({ - page, - }) => { - await page.setContent( - ` - - - Paid - - - Free - - - Top - - - - - Free - Top - - `, - config - ); - - await page - .locator('ion-segment-view') - .evaluate( - (segmentView: HTMLIonSegmentViewElement) => !segmentView.classList.contains('segment-view-scroll-disabled') + test('should set correct segment button as checked when changing the value by scrolling the segment content', async ({ + page, + }) => { + await page.setContent( + ` + + + Paid + + + Free + + + Top + + + + + Free + Top + + `, + config ); - await page.waitForChanges(); + await page + .locator('ion-segment-view') + .evaluate( + (segmentView: HTMLIonSegmentViewElement) => !segmentView.classList.contains('segment-view-scroll-disabled') + ); - await page.locator('ion-segment-content[id="top"]').scrollIntoViewIfNeeded(); + await page.waitForChanges(); - const segmentButton = page.locator('ion-segment-button[value="top"]'); - await expect(segmentButton).toHaveClass(/segment-button-checked/); - }); + await page.locator('ion-segment-content[id="top"]').scrollIntoViewIfNeeded(); + + const segmentButton = page.locator('ion-segment-button[value="top"]'); + await expect(segmentButton).toHaveClass(/segment-button-checked/); + }); - test('should set correct segment button as checked and show correct content when programmatically setting the segment vale', async ({ - page, - }) => { - await page.setContent( - ` - - - Paid - - - Free - - - Top - - - - - Free - Top - - `, - config - ); - - await page - .locator('ion-segment-view') - .evaluate( - (segmentView: HTMLIonSegmentViewElement) => !segmentView.classList.contains('segment-view-scroll-disabled') + test('should set correct segment button as checked and show correct content when programmatically setting the segment vale', async ({ + page, + }) => { + await page.setContent( + ` + + + Paid + + + Free + + + Top + + + + + Free + Top + + `, + config ); - await page.waitForChanges(); + await page + .locator('ion-segment-view') + .evaluate( + (segmentView: HTMLIonSegmentViewElement) => !segmentView.classList.contains('segment-view-scroll-disabled') + ); + + await page.waitForChanges(); - await page.locator('ion-segment').evaluate((segment: HTMLIonSegmentElement) => (segment.value = 'top')); + await page.locator('ion-segment').evaluate((segment: HTMLIonSegmentElement) => (segment.value = 'top')); - const segmentButton = page.locator('ion-segment-button[value="top"]'); - await expect(segmentButton).toHaveClass(/segment-button-checked/); + const segmentButton = page.locator('ion-segment-button[value="top"]'); + await expect(segmentButton).toHaveClass(/segment-button-checked/); - const segmentContent = page.locator('ion-segment-content[id="top"]'); - await expect(segmentContent).toBeInViewport(); + const segmentContent = page.locator('ion-segment-content[id="top"]'); + await expect(segmentContent).toBeInViewport(); + }); }); }); From 62ffe16ad347f4b6fdd0788d35d6cfa65d179599 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Ferreira?= <60441552+JoaoFerreira-FrontEnd@users.noreply.github.com> Date: Thu, 11 Sep 2025 11:02:06 +0100 Subject: [PATCH 4/7] Update core/src/components/segment-view/test/basic/segment-view.e2e.ts Co-authored-by: Shane --- core/src/components/segment-view/test/basic/segment-view.e2e.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/components/segment-view/test/basic/segment-view.e2e.ts b/core/src/components/segment-view/test/basic/segment-view.e2e.ts index 649e3b5b2af..f3f35626eaa 100644 --- a/core/src/components/segment-view/test/basic/segment-view.e2e.ts +++ b/core/src/components/segment-view/test/basic/segment-view.e2e.ts @@ -128,7 +128,7 @@ configs({ modes: ['md'] }).forEach(({ title, config }) => { await expect(segmentButton).toHaveClass(/segment-button-checked/); }); - test('should set correct segment button as checked and show correct content when programmatically setting the segment vale', async ({ + test('should set correct segment button as checked and show correct content when programmatically setting the segment value', async ({ page, }) => { await page.setContent( From 8053d642d195caccb7475df7f3d6145a79349ced Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Ferreira?= Date: Thu, 11 Sep 2025 11:33:35 +0100 Subject: [PATCH 5/7] - use RTL helper; --- core/src/components/segment-view/segment-view.tsx | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/core/src/components/segment-view/segment-view.tsx b/core/src/components/segment-view/segment-view.tsx index b8165144ad2..08e55360ee1 100644 --- a/core/src/components/segment-view/segment-view.tsx +++ b/core/src/components/segment-view/segment-view.tsx @@ -1,5 +1,6 @@ import type { ComponentInterface, EventEmitter } from '@stencil/core'; import { Component, Element, Event, Host, Listen, Method, Prop, State, h } from '@stencil/core'; +import { isRTL } from '@utils/rtl'; import type { SegmentViewScrollEvent } from './segment-view-interface'; @@ -39,8 +40,9 @@ export class SegmentView implements ComponentInterface { @Listen('scroll') handleScroll(ev: Event) { const { scrollLeft, scrollWidth, clientWidth } = ev.target as HTMLElement; - const isRTL = window.getComputedStyle(this.el).direction === 'rtl'; - const scrollRatio = (isRTL ? -1 : 1) * (scrollLeft / (scrollWidth - clientWidth)); + const max = scrollWidth - clientWidth; + const scrollRatio = (isRTL(this.el) ? -1 : 1) * (scrollLeft / max); + this.ionSegmentViewScroll.emit({ scrollRatio, @@ -119,7 +121,6 @@ export class SegmentView implements ComponentInterface { async setContent(id: string, smoothScroll = true) { const contents = this.getSegmentContents(); const index = contents.findIndex((content) => content.id === id); - const isRTL = window.getComputedStyle(this.el).direction === 'rtl'; if (index === -1) return; @@ -127,9 +128,11 @@ export class SegmentView implements ComponentInterface { this.resetScrollEndTimeout(); const contentWidth = this.el.offsetWidth; + const offset = index * contentWidth; + this.el.scrollTo({ top: 0, - left: (isRTL ? -1 : 1) * index * contentWidth, + left: (isRTL(this.el) ? -1 : 1 ) * offset, behavior: smoothScroll ? 'smooth' : 'instant', }); } From f56e0899e8c64ab745e0bcb9493b44305c31ac5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Ferreira?= Date: Thu, 11 Sep 2025 11:40:45 +0100 Subject: [PATCH 6/7] lint.fix --- core/src/components/segment-view/segment-view.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/src/components/segment-view/segment-view.tsx b/core/src/components/segment-view/segment-view.tsx index 08e55360ee1..566700e0b5f 100644 --- a/core/src/components/segment-view/segment-view.tsx +++ b/core/src/components/segment-view/segment-view.tsx @@ -40,7 +40,7 @@ export class SegmentView implements ComponentInterface { @Listen('scroll') handleScroll(ev: Event) { const { scrollLeft, scrollWidth, clientWidth } = ev.target as HTMLElement; - const max = scrollWidth - clientWidth; + const max = scrollWidth - clientWidth; const scrollRatio = (isRTL(this.el) ? -1 : 1) * (scrollLeft / max); @@ -128,11 +128,11 @@ export class SegmentView implements ComponentInterface { this.resetScrollEndTimeout(); const contentWidth = this.el.offsetWidth; - const offset = index * contentWidth; + const offset = index * contentWidth; this.el.scrollTo({ top: 0, - left: (isRTL(this.el) ? -1 : 1 ) * offset, + left: (isRTL(this.el) ? -1 : 1) * offset, behavior: smoothScroll ? 'smooth' : 'instant', }); } From 7fbc53afb2f21dbf0dd3092331b71d2f6130b610 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Ferreira?= Date: Thu, 11 Sep 2025 11:49:05 +0100 Subject: [PATCH 7/7] -lint.fix; --- core/src/components/segment-view/segment-view.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/core/src/components/segment-view/segment-view.tsx b/core/src/components/segment-view/segment-view.tsx index 566700e0b5f..21de96590a3 100644 --- a/core/src/components/segment-view/segment-view.tsx +++ b/core/src/components/segment-view/segment-view.tsx @@ -43,7 +43,6 @@ export class SegmentView implements ComponentInterface { const max = scrollWidth - clientWidth; const scrollRatio = (isRTL(this.el) ? -1 : 1) * (scrollLeft / max); - this.ionSegmentViewScroll.emit({ scrollRatio, isManualScroll: this.isManualScroll ?? true,