diff --git a/core/api.txt b/core/api.txt index b4036e6b8e8..43e95807d4c 100644 --- a/core/api.txt +++ b/core/api.txt @@ -1693,6 +1693,7 @@ ion-segment-content,shadow ion-segment-view,shadow ion-segment-view,prop,disabled,boolean,false,false,false +ion-segment-view,prop,swipeGesture,boolean,true,false,false ion-segment-view,event,ionSegmentViewScroll,SegmentViewScrollEvent,true ion-select,shadow diff --git a/core/src/components.d.ts b/core/src/components.d.ts index ae6d9f4c2fb..d690184aff6 100644 --- a/core/src/components.d.ts +++ b/core/src/components.d.ts @@ -3113,6 +3113,11 @@ export namespace Components { * @param smoothScroll : Whether to animate the scroll transition. */ "setContent": (id: string, smoothScroll?: boolean) => Promise; + /** + * If `true`, users will be able to swipe the segment view to navigate between segment contents. + * @default true + */ + "swipeGesture": boolean; } interface IonSelect { /** @@ -8424,6 +8429,11 @@ declare namespace LocalJSX { * Emitted when the segment view is scrolled. */ "onIonSegmentViewScroll"?: (event: IonSegmentViewCustomEvent) => void; + /** + * If `true`, users will be able to swipe the segment view to navigate between segment contents. + * @default true + */ + "swipeGesture"?: boolean; } interface IonSelect { /** diff --git a/core/src/components/segment-view/segment-view.scss b/core/src/components/segment-view/segment-view.scss index a41030992f6..52210425a63 100644 --- a/core/src/components/segment-view/segment-view.scss +++ b/core/src/components/segment-view/segment-view.scss @@ -21,7 +21,8 @@ display: none; } -:host(.segment-view-disabled) { +:host(.segment-view-disabled), +:host(.segment-view-swipe-disabled) { touch-action: none; overflow-x: hidden; } diff --git a/core/src/components/segment-view/segment-view.tsx b/core/src/components/segment-view/segment-view.tsx index 21de96590a3..a503b5e2637 100644 --- a/core/src/components/segment-view/segment-view.tsx +++ b/core/src/components/segment-view/segment-view.tsx @@ -23,6 +23,11 @@ export class SegmentView implements ComponentInterface { */ @Prop() disabled = false; + /** + * If `true`, users will be able to swipe the segment view to navigate between segment contents. + */ + @Prop() swipeGesture = true; + /** * @internal * @@ -141,13 +146,14 @@ export class SegmentView implements ComponentInterface { } render() { - const { disabled, isManualScroll } = this; + const { disabled, isManualScroll, swipeGesture } = this; return ( diff --git a/core/src/components/segment-view/test/swipe-gesture/index.html b/core/src/components/segment-view/test/swipe-gesture/index.html new file mode 100644 index 00000000000..8a5c39b6cc2 --- /dev/null +++ b/core/src/components/segment-view/test/swipe-gesture/index.html @@ -0,0 +1,147 @@ + + + + + Segment View - Swipe Gesture + + + + + + + + + + + + + + + Segment View - Swipe Gesture + + + + +

+ Swipe Gesture: Segment Enabled; Segment View + Enabled +

+ + + Paid + + + Free + + + Top + + + + + Free + Top + + +

+ Swipe Gesture: Segment Disabled; Segment View + Enabled +

+ + + Paid + + + Free + + + Top + + + + Paid + Free + Top + + +

+ Swipe Gesture: Segment Enabled; Segment View + Disabled +

+ + + Paid + + + Free + + + Top + + + + Paid + Free + Top + + +

+ Swipe Gesture: Segment Disabled; Segment View + Disabled +

+ + + Paid + + + Free + + + Top + + + + Paid + Free + Top + +
+
+ + diff --git a/core/src/components/segment-view/test/swipe-gesture/segment-view.e2e.ts b/core/src/components/segment-view/test/swipe-gesture/segment-view.e2e.ts new file mode 100644 index 00000000000..f250cb142db --- /dev/null +++ b/core/src/components/segment-view/test/swipe-gesture/segment-view.e2e.ts @@ -0,0 +1,51 @@ +import { expect } from '@playwright/test'; +import { configs, test } from '@utils/test/playwright'; + +/** + * This behavior does not vary across modes/directions + */ +configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => { + test.describe(title('segment-view: swipe gesture'), () => { + test('should allow swiping the segment view by default', async ({ page }) => { + await page.setContent( + ` + + + Free + Top + + `, + config + ); + + const segmentView = page.locator('ion-segment-view'); + + const allowsSwipe = await segmentView.evaluate((el: HTMLElement) => { + const style = getComputedStyle(el); + return style.overflowX !== 'hidden' && style.touchAction !== 'none'; + }); + expect(allowsSwipe).toBe(true); + }); + + test('should not allow swiping the segment view when swipeGesture is false', async ({ page }) => { + await page.setContent( + ` + + + Free + Top + + `, + config + ); + + const segmentView = page.locator('ion-segment-view'); + + const allowsSwipe = await segmentView.evaluate((el: HTMLElement) => { + const style = getComputedStyle(el); + return style.overflowX !== 'hidden' && style.touchAction !== 'none'; + }); + expect(allowsSwipe).toBe(false); + }); + }); +}); diff --git a/packages/angular/src/directives/proxies.ts b/packages/angular/src/directives/proxies.ts index beaf411cec5..d5b1a91baca 100644 --- a/packages/angular/src/directives/proxies.ts +++ b/packages/angular/src/directives/proxies.ts @@ -2113,14 +2113,14 @@ export declare interface IonSegmentContent extends Components.IonSegmentContent @ProxyCmp({ - inputs: ['disabled'] + inputs: ['disabled', 'swipeGesture'] }) @Component({ selector: 'ion-segment-view', changeDetection: ChangeDetectionStrategy.OnPush, template: '', // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property - inputs: ['disabled'], + inputs: ['disabled', 'swipeGesture'], }) export class IonSegmentView { protected el: HTMLIonSegmentViewElement; diff --git a/packages/angular/standalone/src/directives/proxies.ts b/packages/angular/standalone/src/directives/proxies.ts index 2fa0482d3d6..3d2693c0b83 100644 --- a/packages/angular/standalone/src/directives/proxies.ts +++ b/packages/angular/standalone/src/directives/proxies.ts @@ -1889,14 +1889,14 @@ export declare interface IonSegmentContent extends Components.IonSegmentContent @ProxyCmp({ defineCustomElementFn: defineIonSegmentView, - inputs: ['disabled'] + inputs: ['disabled', 'swipeGesture'] }) @Component({ selector: 'ion-segment-view', changeDetection: ChangeDetectionStrategy.OnPush, template: '', // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property - inputs: ['disabled'], + inputs: ['disabled', 'swipeGesture'], standalone: true }) export class IonSegmentView { diff --git a/packages/vue/src/proxies.ts b/packages/vue/src/proxies.ts index 72e22d2c7b4..31d13970a4c 100644 --- a/packages/vue/src/proxies.ts +++ b/packages/vue/src/proxies.ts @@ -899,6 +899,7 @@ export const IonSegmentContent: StencilVueComponent = /*@ export const IonSegmentView: StencilVueComponent = /*@__PURE__*/ defineContainer('ion-segment-view', defineIonSegmentView, [ 'disabled', + 'swipeGesture', 'ionSegmentViewScroll' ], [ 'ionSegmentViewScroll'