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,shadow
|
||||||
ion-segment-view,prop,disabled,boolean,false,false,false
|
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-segment-view,event,ionSegmentViewScroll,SegmentViewScrollEvent,true
|
||||||
|
|
||||||
ion-select,shadow
|
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.
|
* @param smoothScroll : Whether to animate the scroll transition.
|
||||||
*/
|
*/
|
||||||
"setContent": (id: string, smoothScroll?: boolean) => Promise<void>;
|
"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 {
|
interface IonSelect {
|
||||||
/**
|
/**
|
||||||
@@ -8424,6 +8429,11 @@ declare namespace LocalJSX {
|
|||||||
* Emitted when the segment view is scrolled.
|
* Emitted when the segment view is scrolled.
|
||||||
*/
|
*/
|
||||||
"onIonSegmentViewScroll"?: (event: IonSegmentViewCustomEvent<SegmentViewScrollEvent>) => void;
|
"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 {
|
interface IonSelect {
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -21,7 +21,8 @@
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
:host(.segment-view-disabled) {
|
:host(.segment-view-disabled),
|
||||||
|
:host(.segment-view-swipe-disabled) {
|
||||||
touch-action: none;
|
touch-action: none;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,11 @@ export class SegmentView implements ComponentInterface {
|
|||||||
*/
|
*/
|
||||||
@Prop() disabled = false;
|
@Prop() disabled = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If `true`, users will be able to swipe the segment view to navigate between segment contents.
|
||||||
|
*/
|
||||||
|
@Prop() swipeGesture = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
*
|
*
|
||||||
@@ -141,13 +146,14 @@ export class SegmentView implements ComponentInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { disabled, isManualScroll } = this;
|
const { disabled, isManualScroll, swipeGesture } = this;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Host
|
<Host
|
||||||
class={{
|
class={{
|
||||||
'segment-view-disabled': disabled,
|
'segment-view-disabled': disabled,
|
||||||
'segment-view-scroll-disabled': isManualScroll === false,
|
'segment-view-scroll-disabled': isManualScroll === false,
|
||||||
|
'segment-view-swipe-disabled': swipeGesture === false,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<slot></slot>
|
<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({
|
@ProxyCmp({
|
||||||
inputs: ['disabled']
|
inputs: ['disabled', 'swipeGesture']
|
||||||
})
|
})
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ion-segment-view',
|
selector: 'ion-segment-view',
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
template: '<ng-content></ng-content>',
|
template: '<ng-content></ng-content>',
|
||||||
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
|
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
|
||||||
inputs: ['disabled'],
|
inputs: ['disabled', 'swipeGesture'],
|
||||||
})
|
})
|
||||||
export class IonSegmentView {
|
export class IonSegmentView {
|
||||||
protected el: HTMLIonSegmentViewElement;
|
protected el: HTMLIonSegmentViewElement;
|
||||||
|
|||||||
@@ -1889,14 +1889,14 @@ export declare interface IonSegmentContent extends Components.IonSegmentContent
|
|||||||
|
|
||||||
@ProxyCmp({
|
@ProxyCmp({
|
||||||
defineCustomElementFn: defineIonSegmentView,
|
defineCustomElementFn: defineIonSegmentView,
|
||||||
inputs: ['disabled']
|
inputs: ['disabled', 'swipeGesture']
|
||||||
})
|
})
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ion-segment-view',
|
selector: 'ion-segment-view',
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
template: '<ng-content></ng-content>',
|
template: '<ng-content></ng-content>',
|
||||||
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
|
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
|
||||||
inputs: ['disabled'],
|
inputs: ['disabled', 'swipeGesture'],
|
||||||
standalone: true
|
standalone: true
|
||||||
})
|
})
|
||||||
export class IonSegmentView {
|
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, [
|
export const IonSegmentView: StencilVueComponent<JSX.IonSegmentView> = /*@__PURE__*/ defineContainer<JSX.IonSegmentView>('ion-segment-view', defineIonSegmentView, [
|
||||||
'disabled',
|
'disabled',
|
||||||
|
'swipeGesture',
|
||||||
'ionSegmentViewScroll'
|
'ionSegmentViewScroll'
|
||||||
], [
|
], [
|
||||||
'ionSegmentViewScroll'
|
'ionSegmentViewScroll'
|
||||||
|
|||||||
Reference in New Issue
Block a user