diff --git a/core/src/components/segment-view/segment-view.tsx b/core/src/components/segment-view/segment-view.tsx index 633d9a37d39..21de96590a3 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,7 +40,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 max = scrollWidth - clientWidth; + const scrollRatio = (isRTL(this.el) ? -1 : 1) * (scrollLeft / max); this.ionSegmentViewScroll.emit({ scrollRatio, @@ -125,9 +127,11 @@ export class SegmentView implements ComponentInterface { this.resetScrollEndTimeout(); const contentWidth = this.el.offsetWidth; + const offset = index * contentWidth; + this.el.scrollTo({ top: 0, - left: index * contentWidth, + left: (isRTL(this.el) ? -1 : 1) * offset, behavior: smoothScroll ? 'smooth' : 'instant', }); } 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..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 @@ -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( @@ -88,86 +88,86 @@ configs({ modes: ['md'], directions: ['ltr'] }).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 value', 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(); + }); }); }); 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 + + + + + + +