Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions core/api.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
10 changes: 10 additions & 0 deletions core/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3113,6 +3113,11 @@ export namespace Components {
* @param smoothScroll : Whether to animate the scroll transition.
*/
"setContent": (id: string, smoothScroll?: boolean) => Promise<void>;
/**
* If `true`, users will be able to swipe the segment view to navigate between segment contents.
* @default true
*/
"swipeGesture": boolean;
}
interface IonSelect {
/**
Expand Down Expand Up @@ -8424,6 +8429,11 @@ declare namespace LocalJSX {
* Emitted when the segment view is scrolled.
*/
"onIonSegmentViewScroll"?: (event: IonSegmentViewCustomEvent<SegmentViewScrollEvent>) => void;
/**
* If `true`, users will be able to swipe the segment view to navigate between segment contents.
* @default true
*/
"swipeGesture"?: boolean;
}
interface IonSelect {
/**
Expand Down
3 changes: 2 additions & 1 deletion core/src/components/segment-view/segment-view.scss
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
8 changes: 7 additions & 1 deletion core/src/components/segment-view/segment-view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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
*
Expand Down Expand Up @@ -141,13 +146,14 @@ export class SegmentView implements ComponentInterface {
}

render() {
const { disabled, isManualScroll } = this;
const { disabled, isManualScroll, swipeGesture } = this;

return (
<Host
class={{
'segment-view-disabled': disabled,
'segment-view-scroll-disabled': isManualScroll === false,
'segment-view-swipe-disabled': swipeGesture === false,
}}
>
<slot></slot>
Expand Down
147 changes: 147 additions & 0 deletions core/src/components/segment-view/test/swipe-gesture/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="UTF-8" />
<title>Segment View - Swipe Gesture</title>
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"
/>
<link href="../../../../../css/ionic.bundle.css" rel="stylesheet" />
<link href="../../../../../scripts/testing/styles.css" rel="stylesheet" />
<script src="../../../../../scripts/testing/scripts.js"></script>
<script nomodule src="../../../../../dist/ionic/ionic.js"></script>
<script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script>

<style>
h2 {
font-size: 12px;
font-weight: normal;

color: #6f7378;

margin: 24px 16px 8px;
}

ion-segment-view {
height: 100px;

margin-bottom: 20px;
}

ion-segment-content {
display: flex;
justify-content: center;
align-items: center;
}

ion-segment-content:nth-of-type(3n + 1) {
background: lightpink;
}

ion-segment-content:nth-of-type(3n + 2) {
background: lightblue;
}

ion-segment-content:nth-of-type(3n + 3) {
background: lightgreen;
}
</style>
</head>

<body>
<ion-app>
<ion-header>
<ion-toolbar>
<ion-title>Segment View - Swipe Gesture</ion-title>
</ion-toolbar>
</ion-header>

<ion-content>
<h2>
Swipe Gesture: Segment <ion-text color="success">Enabled</ion-text>; Segment View
<ion-text color="success">Enabled</ion-text>
</h2>
<ion-segment value="free">
<ion-segment-button content-id="paid" value="paid">
<ion-label>Paid</ion-label>
</ion-segment-button>
<ion-segment-button content-id="free" value="free">
<ion-label>Free</ion-label>
</ion-segment-button>
<ion-segment-button content-id="top" value="top">
<ion-label>Top</ion-label>
</ion-segment-button>
</ion-segment>
<ion-segment-view>
<ion-segment-content id="paid">Paid</ion-segment-content>
<ion-segment-content id="free">Free</ion-segment-content>
<ion-segment-content id="top">Top</ion-segment-content>
</ion-segment-view>

<h2>
Swipe Gesture: Segment <ion-text color="danger">Disabled</ion-text>; Segment View
<ion-text color="success">Enabled</ion-text>
</h2>
<ion-segment swipe-gesture="false" value="free2">
<ion-segment-button content-id="paid2" value="paid2">
<ion-label>Paid</ion-label>
</ion-segment-button>
<ion-segment-button content-id="free2" value="free2">
<ion-label>Free</ion-label>
</ion-segment-button>
<ion-segment-button content-id="top2" value="top2">
<ion-label>Top</ion-label>
</ion-segment-button>
</ion-segment>
<ion-segment-view>
<ion-segment-content id="paid2">Paid</ion-segment-content>
<ion-segment-content id="free2">Free</ion-segment-content>
<ion-segment-content id="top2">Top</ion-segment-content>
</ion-segment-view>

<h2>
Swipe Gesture: Segment <ion-text color="success">Enabled</ion-text>; Segment View
<ion-text color="danger">Disabled</ion-text>
</h2>
<ion-segment value="free3">
<ion-segment-button content-id="paid3" value="paid3">
<ion-label>Paid</ion-label>
</ion-segment-button>
<ion-segment-button content-id="free3" value="free3">
<ion-label>Free</ion-label>
</ion-segment-button>
<ion-segment-button content-id="top3" value="top3">
<ion-label>Top</ion-label>
</ion-segment-button>
</ion-segment>
<ion-segment-view swipe-gesture="false">
<ion-segment-content id="paid3">Paid</ion-segment-content>
<ion-segment-content id="free3">Free</ion-segment-content>
<ion-segment-content id="top3">Top</ion-segment-content>
</ion-segment-view>

<h2>
Swipe Gesture: Segment <ion-text color="danger">Disabled</ion-text>; Segment View
<ion-text color="danger">Disabled</ion-text>
</h2>
<ion-segment swipe-gesture="false" value="free4">
<ion-segment-button content-id="paid4" value="paid4">
<ion-label>Paid</ion-label>
</ion-segment-button>
<ion-segment-button content-id="free4" value="free4">
<ion-label>Free</ion-label>
</ion-segment-button>
<ion-segment-button content-id="top4" value="top4">
<ion-label>Top</ion-label>
</ion-segment-button>
</ion-segment>
<ion-segment-view swipe-gesture="false">
<ion-segment-content id="paid4">Paid</ion-segment-content>
<ion-segment-content id="free4">Free</ion-segment-content>
<ion-segment-content id="top4">Top</ion-segment-content>
</ion-segment-view>
</ion-content>
</ion-app>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -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(
`
<ion-segment-view>
<ion-segment-content id="paid">Paid</ion-segment-content>
<ion-segment-content id="free">Free</ion-segment-content>
<ion-segment-content id="top">Top</ion-segment-content>
</ion-segment-view>
`,
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(
`
<ion-segment-view swipe-gesture="false">
<ion-segment-content id="paid">Paid</ion-segment-content>
<ion-segment-content id="free">Free</ion-segment-content>
<ion-segment-content id="top">Top</ion-segment-content>
</ion-segment-view>
`,
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);
});
});
});
4 changes: 2 additions & 2 deletions packages/angular/src/directives/proxies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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: '<ng-content></ng-content>',
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
inputs: ['disabled'],
inputs: ['disabled', 'swipeGesture'],
})
export class IonSegmentView {
protected el: HTMLIonSegmentViewElement;
Expand Down
4 changes: 2 additions & 2 deletions packages/angular/standalone/src/directives/proxies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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: '<ng-content></ng-content>',
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
inputs: ['disabled'],
inputs: ['disabled', 'swipeGesture'],
standalone: true
})
export class IonSegmentView {
Expand Down
1 change: 1 addition & 0 deletions packages/vue/src/proxies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -899,6 +899,7 @@ export const IonSegmentContent: StencilVueComponent<JSX.IonSegmentContent> = /*@

export const IonSegmentView: StencilVueComponent<JSX.IonSegmentView> = /*@__PURE__*/ defineContainer<JSX.IonSegmentView>('ion-segment-view', defineIonSegmentView, [
'disabled',
'swipeGesture',
'ionSegmentViewScroll'
], [
'ionSegmentViewScroll'
Expand Down
Loading