Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs(modal): playground example to prevent swipe to dismiss #2820

Merged
merged 10 commits into from
Mar 24, 2023
10 changes: 9 additions & 1 deletion docs/api/modal.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ import ControllerExample from '@site/static/usage/v7/modal/controller/index.md';

When entering data into a modal, it is often desirable to have a way of preventing accidental data loss. The `canDismiss` property on `ion-modal` gives developers control over when a modal is allowed to dismiss.

There are two different ways of using the `canDismiss` property.
There are two different ways of using the `canDismiss` property: setting a boolean value or setting a callback function.

:::note
Note: When using a sheet modal, `canDismiss` will not be checked on swipe if there is no `0` breakpoint set. However, it will still be checked when pressing `Esc` or the hardware back button.
Expand Down Expand Up @@ -79,6 +79,14 @@ import CanDismissFunctionExample from '@site/static/usage/v7/modal/can-dismiss/f

<CanDismissFunctionExample />

### Prevent swipe to close

Developers may want to prevent users from swiping to close a modal. This can be done by setting a callback function for `canDismiss` and checking if the `role` is not `gesture`.

import CanDismissPreventSwipeToCloseExample from '@site/static/usage/v7/modal/can-dismiss/prevent-swipe-to-close/index.md';

<CanDismissPreventSwipeToCloseExample />

## Types of modals

### Card Modal
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
```html
<div class="ion-page" #page>
<ion-header>
<ion-toolbar>
<ion-title>App</ion-title>
</ion-toolbar>
</ion-header>
<ion-content class="ion-padding">
<ion-button id="open-modal" expand="block">Open</ion-button>
<ion-modal #modal trigger="open-modal" [canDismiss]="canDismiss" [presentingElement]="page">
<ng-template>
<ion-header>
<ion-toolbar>
<ion-title>Modal</ion-title>
<ion-buttons slot="end">
<ion-button (click)="modal.dismiss()">Close</ion-button>
</ion-buttons>
</ion-toolbar>
</ion-header>
<ion-content class="ion-padding">
<p>
To close this modal, please use the "Close" button provided. Note that swiping the modal will not dismiss
it.
</p>
</ion-content>
</ng-template>
</ion-modal>
</ion-content>
</div>
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
```ts
import { Component } from '@angular/core';

@Component({
selector: 'app-example',
templateUrl: 'example.component.html',
})
export class ExampleComponent {
async canDismiss(data?: any, role?: string) {
return role !== 'gesture';
}
}
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Modal | Can Dismiss</title>
<link rel="stylesheet" href="../../../../common.css" />
<script src="../../../../common.js"></script>
<script type="module" src="https://cdn.jsdelivr.net/npm/@ionic/core@6/dist/ionic/ionic.esm.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ionic/core@6/css/ionic.bundle.css" />

</head>

<body>
<ion-app>
<div class="ion-page">
<ion-header>
<ion-toolbar>
<ion-title>App</ion-title>
</ion-toolbar>
</ion-header>
<ion-content class="ion-padding">
<ion-button id="open-modal" expand="block">Open</ion-button>

<ion-modal trigger="open-modal">
<ion-header>
<ion-toolbar>
<ion-title>Modal</ion-title>
<ion-buttons slot="end">
<ion-button onclick="dismiss()">Close</ion-button>
</ion-buttons>
</ion-toolbar>
</ion-header>
<ion-content class="ion-padding">
<p>To close this modal, please use the "Close" button provided. Note that swiping the modal will not dismiss
it.</p>
</ion-content>
</ion-modal>
</ion-content>
</div>
</ion-app>

<script>
const modal = document.querySelector('ion-modal');

modal.canDismiss = (data, role) => role !== 'gesture';
modal.presentingElement = document.querySelector('.ion-page');

function dismiss() {
modal.dismiss();
}

</script>
</body>

</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import Playground from '@site/src/components/global/Playground';

import javascript from './javascript.md';
import vue from './vue.md';

import react from './react.md';

import angular_example_component_html from './angular/example_component_html.md';
import angular_example_component_ts from './angular/example_component_ts.md';

<Playground
version="6"
code={{
javascript,
react,
vue,
angular: {
files: {
'src/app/example.component.html': angular_example_component_html,
'src/app/example.component.ts': angular_example_component_ts,
},
},
}}
src="usage/v6/modal/can-dismiss/prevent-swipe-to-close/demo.html"
sean-perkins marked this conversation as resolved.
Show resolved Hide resolved
devicePreview
mode="ios"
/>
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
```html
<div class="ion-page">
<ion-header>
<ion-toolbar>
<ion-title>App</ion-title>
</ion-toolbar>
</ion-header>
<ion-content class="ion-padding">
<ion-button id="open-modal" expand="block">Open</ion-button>

<ion-modal trigger="open-modal">
<ion-header>
<ion-toolbar>
<ion-title>Modal</ion-title>
<ion-buttons slot="end">
<ion-button onclick="dismiss()">Close</ion-button>
</ion-buttons>
</ion-toolbar>
</ion-header>
<ion-content class="ion-padding">
<p>
To close this modal, please use the "Close" button provided. Note that swiping the modal will not dismiss it.
</p>
</ion-content>
</ion-modal>
</ion-content>
</div>

<script>
var modal = document.querySelector('ion-modal');

modal.canDismiss = (data, role) => role !== 'gesture';
modal.presentingElement = document.querySelector('.ion-page');

function dismiss() {
modal.dismiss();
}
</script>
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
```tsx
import React, { useState, useRef, useEffect } from 'react';
import { IonButtons, IonButton, IonModal, IonHeader, IonContent, IonToolbar, IonTitle, IonPage } from '@ionic/react';

function Example() {
const modal = useRef<HTMLIonModalElement>(null);
const page = useRef(null);

const [presentingElement, setPresentingElement] = useState<HTMLElement | null>(null);

useEffect(() => {
setPresentingElement(page.current);
}, []);

function dismiss() {
modal.current?.dismiss();
}

async function canDismiss(data?: any, role?: string) {
return role !== 'gesture';
}

return (
<IonPage ref={page}>
<IonHeader>
<IonToolbar>
<IonTitle>App</IonTitle>
</IonToolbar>
</IonHeader>
<IonContent className="ion-padding">
<IonButton id="open-modal" expand="block">
Open
</IonButton>
<IonModal ref={modal} trigger="open-modal" canDismiss={canDismiss} presentingElement={presentingElement!}>
<IonHeader>
<IonToolbar>
<IonTitle>Modal</IonTitle>
<IonButtons slot="end">
<IonButton onClick={() => dismiss()}>Close</IonButton>
</IonButtons>
</IonToolbar>
</IonHeader>
<IonContent className="ion-padding">
<p>
To close this modal, please use the "Close" button provided. Note that swiping the modal will not dismiss
it.
</p>
</IonContent>
</IonModal>
</IonContent>
</IonPage>
);
}

export default Example;
```
47 changes: 47 additions & 0 deletions static/usage/v6/modal/can-dismiss/prevent-swipe-to-close/vue.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
```html
<template>
<ion-page ref="page">
<ion-header>
<ion-toolbar>
<ion-title>App</ion-title>
</ion-toolbar>
</ion-header>
<ion-content class="ion-padding">
<ion-button id="open-modal" expand="block">Open</ion-button>

<ion-modal ref="modal" trigger="open-modal" :can-dismiss="canDismiss" :presenting-element="page?.$el">
<ion-header>
<ion-toolbar>
<ion-title>Modal</ion-title>
<ion-buttons slot="end">
<ion-button @click="dismiss">Close</ion-button>
</ion-buttons>
</ion-toolbar>
</ion-header>
<ion-content class="ion-padding">
<p>
To close this modal, please use the "Close" button provided. Note that swiping the modal will not dismiss
it.
</p>
</ion-content>
</ion-modal>
</ion-content>
</ion-page>
</template>

<script setup lang="ts">
import { IonButtons, IonButton, IonModal, IonHeader, IonContent, IonToolbar, IonTitle, IonPage } from '@ionic/vue';
import { ref } from 'vue';

const page = ref(null);
const modal = ref(null);

function dismiss() {
modal.value.$el.dismiss();
}

async function canDismiss(data?: any, role?: string) {
return role !== 'gesture';
}
</script>
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
```html
<div class="ion-page" #page>
<ion-header>
<ion-toolbar>
<ion-title>App</ion-title>
</ion-toolbar>
</ion-header>
<ion-content class="ion-padding">
<ion-button id="open-modal" expand="block">Open</ion-button>
<ion-modal #modal trigger="open-modal" [canDismiss]="canDismiss" [presentingElement]="page">
<ng-template>
<ion-header>
<ion-toolbar>
<ion-title>Modal</ion-title>
<ion-buttons slot="end">
<ion-button (click)="modal.dismiss()">Close</ion-button>
</ion-buttons>
</ion-toolbar>
</ion-header>
<ion-content class="ion-padding">
<p>
To close this modal, please use the "Close" button provided. Note that swiping the modal will not dismiss
it.
</p>
</ion-content>
</ng-template>
</ion-modal>
</ion-content>
</div>
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
```ts
import { Component } from '@angular/core';

@Component({
selector: 'app-example',
templateUrl: 'example.component.html',
})
export class ExampleComponent {
async canDismiss(data?: any, role?: string) {
return role !== 'gesture';
}
}
```
Loading