mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2026-03-13 10:22:08 +08:00
feat(segment-view): add swipeGesture property to disable swiping (#30948)
Issue number: resolves #30290 --------- ## What is the current behavior? The segment view swipe gesture can only be disabled by adding the `disabled` property and setting `opacity: 1`. ## What is the new behavior? - Adds a new property, `swipeGesture`, to disable swiping on the segment view - Adds an e2e test which verifies the styles blocking the swipe are correctly applied when `swipeGesture` is `false` ## Does this introduce a breaking change? - [ ] Yes - [x] No --------- Co-authored-by: Brandy Smith <6577830+brandyscarney@users.noreply.github.com>
This commit is contained in:
@@ -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
|
||||
|
||||
10
core/src/components.d.ts
vendored
10
core/src/components.d.ts
vendored
@@ -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 {
|
||||
/**
|
||||
@@ -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 {
|
||||
/**
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 (
|
||||
<Host
|
||||
class={{
|
||||
'segment-view-disabled': disabled,
|
||||
'segment-view-scroll-disabled': isManualScroll === false,
|
||||
'segment-view-swipe-disabled': swipeGesture === false,
|
||||
}}
|
||||
>
|
||||
<slot></slot>
|
||||
|
||||
147
core/src/components/segment-view/test/swipe-gesture/index.html
Normal file
147
core/src/components/segment-view/test/swipe-gesture/index.html
Normal file
@@ -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>
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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'
|
||||
|
||||
Reference in New Issue
Block a user