Skip to content

Commit 6950b0e

Browse files
committed
docs(modal): add drag events playground for card
1 parent f028c88 commit 6950b0e

8 files changed

Lines changed: 569 additions & 0 deletions

File tree

docs/api/modal.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import Parts from '@ionic-internal/component-api/v8/modal/parts.md';
88
import CustomProps from '@ionic-internal/component-api/v8/modal/custom-props.mdx';
99
import Slots from '@ionic-internal/component-api/v8/modal/slots.md';
1010
import SheetDragEvents from '@site/static/usage/v8/modal/sheet/drag-events/index.md';
11+
import CardDragEvents from '@site/static/usage/v8/modal/card/drag-events/index.md';
1112

1213
<head>
1314
<title>ion-modal: Ionic Mobile App Custom Modal API Component</title>
@@ -116,6 +117,12 @@ import CardExample from '@site/static/usage/v8/modal/card/basic/index.md';
116117

117118
<CardExample />
118119

120+
### Drag Events
121+
122+
When using a card modal, you may want to perform certain actions based on the dragging of the card. Ionic emits several events related to dragging that can be used for this purpose, such as `ionDragStart`, `ionDragMove`, and `ionDragEnd`.
123+
124+
<CardDragEvents />
125+
119126
## Sheet Modal
120127

121128
:::info
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
```html
2+
<div class="ion-page" #appPage>
3+
<ion-header>
4+
<ion-toolbar>
5+
<ion-title>App</ion-title>
6+
</ion-toolbar>
7+
</ion-header>
8+
9+
<ion-content class="ion-padding">
10+
<ion-button id="open-modal" expand="block">Open Card Modal</ion-button>
11+
12+
<ion-modal
13+
#modal
14+
trigger="open-modal"
15+
[presentingElement]="presentingElement"
16+
(ionModalWillPresent)="onModalWillPresent()"
17+
(ionDragStart)="onDragStart()"
18+
(ionDragMove)="onDragMove($event)"
19+
(ionDragEnd)="onDragEnd($event)"
20+
(ionModalWillDismiss)="onModalWillDismiss()"
21+
>
22+
<ng-template>
23+
<ion-header>
24+
<ion-toolbar>
25+
<ion-title>Modal</ion-title>
26+
</ion-toolbar>
27+
</ion-header>
28+
<ion-content class="ion-padding">
29+
<div class="ion-margin-top">
30+
<ion-label> Drag the handle to adjust the background brightness based on a custom brightness. </ion-label>
31+
</div>
32+
</ion-content>
33+
</ng-template>
34+
</ion-modal>
35+
</ion-content>
36+
</div>
37+
```
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
```ts
2+
import { Component, ElementRef, ViewChild, OnInit } from '@angular/core';
3+
import { IonHeader, IonToolbar, IonTitle, IonContent, IonButton, IonModal, IonLabel } from '@ionic/angular/standalone';
4+
5+
@Component({
6+
selector: 'app-example',
7+
templateUrl: 'example.component.html',
8+
standalone: true,
9+
imports: [IonHeader, IonToolbar, IonTitle, IonContent, IonButton, IonModal, IonLabel],
10+
})
11+
export class ExampleComponent implements OnInit {
12+
@ViewChild('modal', { static: true }) modal!: IonModal;
13+
@ViewChild('appPage', { static: true }) appPage!: ElementRef<HTMLDivElement>;
14+
15+
presentingElement: HTMLElement | undefined;
16+
17+
private readonly DARKEST_PERCENT = 50;
18+
private readonly BRIGHTNESS_RANGE = 100 - this.DARKEST_PERCENT;
19+
20+
ngOnInit() {
21+
this.presentingElement = this.appPage.nativeElement;
22+
}
23+
24+
onModalWillPresent() {
25+
const appEl = this.appPage.nativeElement;
26+
27+
appEl.style.transition = 'filter 0.4s ease';
28+
// Set to max darkness immediately
29+
appEl.style.setProperty('filter', `brightness(${this.DARKEST_PERCENT}%)`, 'important');
30+
}
31+
32+
onDragStart() {
33+
const appEl = this.appPage.nativeElement;
34+
35+
// Ensure transitions are off during the active drag
36+
appEl.style.transition = 'none';
37+
}
38+
39+
onDragMove(event: any) {
40+
// `progress` is a value from 1 (top) to 0 (bottom)
41+
const { progress } = event.detail;
42+
43+
const appEl = this.appPage.nativeElement;
44+
/**
45+
* Calculate the current brightness based on how far the user has
46+
* dragged.
47+
*
48+
* When dragging up, the background should become darker,
49+
* and when dragging down, it should become lighter.
50+
*/
51+
const brightnessValue = 100 - progress * this.BRIGHTNESS_RANGE;
52+
53+
// Update the brightness in real-time as the user drags
54+
appEl.style.setProperty('filter', `brightness(${brightnessValue}%)`, 'important');
55+
}
56+
57+
onDragEnd(event: any) {
58+
// `progress` is a value from 1 (top) to 0 (bottom)
59+
const { progress } = event.detail;
60+
61+
const appEl = this.appPage.nativeElement;
62+
/**
63+
* Snap the background brightness based on the user's drag intent.
64+
* Progress > 0.4 implies an intent to open (snap dark),
65+
* while < 0.4 implies a dismissal (snap bright).
66+
*/
67+
const brightnessValue = progress > 0.4 ? this.DARKEST_PERCENT : 100;
68+
69+
// Reset to max darkness on snap-back for a nice visual effect
70+
appEl.style.setProperty('filter', `brightness(${brightnessValue}%)`, 'important');
71+
72+
// Re-enable transition for a smooth snap-back
73+
appEl.style.transition = 'filter 0.4s ease';
74+
}
75+
76+
onModalWillDismiss() {
77+
const appEl = this.appPage.nativeElement;
78+
79+
// Clean up styles when the modal is dismissed
80+
appEl.style.removeProperty('filter');
81+
appEl.style.removeProperty('transition');
82+
}
83+
}
84+
```
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+
<title>Modal</title>
7+
<link rel="stylesheet" href="../../../common.css" />
8+
<script src="../../../common.js"></script>
9+
<script type="module" src="https://cdn.jsdelivr.net/npm/@ionic/core@8/dist/ionic/ionic.esm.js"></script>
10+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ionic/core@8/css/ionic.bundle.css" />
11+
</style>
12+
</head>
13+
14+
<body>
15+
<ion-app>
16+
<div class="ion-page">
17+
<ion-header>
18+
<ion-toolbar>
19+
<ion-title>App</ion-title>
20+
</ion-toolbar>
21+
</ion-header>
22+
<ion-content class="ion-padding">
23+
<ion-button id="open-modal" expand="block">Open Sheet Modal</ion-button>
24+
25+
<ion-modal trigger="open-modal">
26+
<ion-header>
27+
<ion-toolbar>
28+
<ion-title>Modal</ion-title>
29+
</ion-toolbar>
30+
</ion-header>
31+
<ion-content class="ion-padding">
32+
<div class="ion-margin-top">
33+
<ion-label>Drag the handle to adjust the background brightness based on a custom brightness.</ion-label>
34+
</div>
35+
</ion-content>
36+
</ion-modal>
37+
</ion-content>
38+
</div>
39+
</ion-app>
40+
41+
<script>
42+
const modal = document.querySelector('ion-modal');
43+
const presentingElement = document.querySelector('.ion-page');
44+
45+
modal.presentingElement = presentingElement;
46+
47+
const DARKEST_PERCENT = 50;
48+
const BRIGHTNESS_RANGE = 100 - DARKEST_PERCENT;
49+
50+
modal.addEventListener('ionModalWillPresent', () => {
51+
presentingElement.style.transition = 'filter 0.4s ease';
52+
// Set to max darkness immediately
53+
presentingElement.style.setProperty('filter', `brightness(${DARKEST_PERCENT}%)`, 'important');
54+
});
55+
56+
modal.addEventListener('ionDragStart', () => {
57+
// Ensure transitions are off during the active drag
58+
presentingElement.style.transition = 'none';
59+
});
60+
61+
modal.addEventListener('ionDragMove', (event) => {
62+
// `progress` is a value from 1 (top) to 0 (bottom)
63+
const { progress } = event.detail;
64+
65+
/**
66+
* Calculate the current brightness based on how far the user has
67+
* dragged.
68+
*
69+
* When dragging up, the background should become darker,
70+
* and when dragging down, it should become lighter.
71+
*/
72+
const brightnessValue = 100 - progress * BRIGHTNESS_RANGE;
73+
74+
// Update the brightness in real-time as the user drags
75+
presentingElement.style.setProperty('filter', `brightness(${brightnessValue}%)`, 'important');
76+
});
77+
78+
modal.addEventListener('ionDragEnd', (event) => {
79+
// `progress` is a value from 1 (top) to 0 (bottom)
80+
const { progress } = event.detail;
81+
/**
82+
* Snap the background brightness based on the user's drag intent.
83+
* Progress > 0.4 implies an intent to open (snap dark),
84+
* while < 0.4 implies a dismissal (snap bright).
85+
*/
86+
const brightnessValue = progress > 0.4 ? DARKEST_PERCENT : 100;
87+
88+
// Reset to max darkness on snap-back for a nice visual effect
89+
presentingElement.style.setProperty('filter', `brightness(${brightnessValue}%)`, 'important');
90+
91+
// Re-enable transition for a smooth snap-back
92+
presentingElement.style.transition = 'filter 0.4s ease';
93+
});
94+
95+
modal.addEventListener('ionModalWillDismiss', () => {
96+
// Clean up styles when the modal is dismissed
97+
presentingElement.style.removeProperty('filter');
98+
presentingElement.style.removeProperty('transition');
99+
});
100+
</script>
101+
</body>
102+
</html>
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import Playground from '@site/src/components/global/Playground';
2+
3+
import javascript from './javascript.md';
4+
5+
import react from './react.md';
6+
7+
import vue from './vue.md';
8+
9+
import angular_example_component_html from './angular/example_component_html.md';
10+
import angular_example_component_ts from './angular/example_component_ts.md';
11+
12+
<Playground
13+
version="8"
14+
code={{
15+
javascript,
16+
react,
17+
vue,
18+
angular: {
19+
files: {
20+
'src/app/example.component.html': angular_example_component_html,
21+
'src/app/example.component.ts': angular_example_component_ts,
22+
},
23+
},
24+
}}
25+
src="usage/v8/modal/card/drag-events/demo.html"
26+
devicePreview
27+
mode="ios"
28+
/>
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
```html
2+
<div class="ion-page">
3+
<ion-header>
4+
<ion-toolbar>
5+
<ion-title>App</ion-title>
6+
</ion-toolbar>
7+
</ion-header>
8+
<ion-content class="ion-padding">
9+
<ion-button id="open-modal" expand="block">Open Sheet Modal</ion-button>
10+
11+
<ion-modal trigger="open-modal">
12+
<ion-header>
13+
<ion-toolbar>
14+
<ion-title>Modal</ion-title>
15+
</ion-toolbar>
16+
</ion-header>
17+
<ion-content class="ion-padding">
18+
<div class="ion-margin-top">
19+
<ion-label>Drag the handle to adjust the background brightness based on a custom brightness.</ion-label>
20+
</div>
21+
</ion-content>
22+
</ion-modal>
23+
</ion-content>
24+
</div>
25+
26+
<script>
27+
const modal = document.querySelector('ion-modal');
28+
const presentingElement = document.querySelector('.ion-page');
29+
30+
modal.presentingElement = presentingElement;
31+
32+
const DARKEST_PERCENT = 50;
33+
const BRIGHTNESS_RANGE = 100 - DARKEST_PERCENT;
34+
35+
modal.addEventListener('ionModalWillPresent', () => {
36+
presentingElement.style.transition = 'filter 0.4s ease';
37+
// Set to max darkness immediately
38+
presentingElement.style.setProperty('filter', `brightness(${DARKEST_PERCENT}%)`, 'important');
39+
});
40+
41+
modal.addEventListener('ionDragStart', () => {
42+
// Ensure transitions are off during the active drag
43+
presentingElement.style.transition = 'none';
44+
});
45+
46+
modal.addEventListener('ionDragMove', (event) => {
47+
// `progress` is a value from 1 (top) to 0 (bottom)
48+
const { progress } = event.detail;
49+
50+
/**
51+
* Calculate the current brightness based on how far the user has
52+
* dragged.
53+
*
54+
* When dragging up, the background should become darker,
55+
* and when dragging down, it should become lighter.
56+
*/
57+
const brightnessValue = 100 - progress * BRIGHTNESS_RANGE;
58+
59+
// Update the brightness in real-time as the user drags
60+
presentingElement.style.setProperty('filter', `brightness(${brightnessValue}%)`, 'important');
61+
});
62+
63+
modal.addEventListener('ionDragEnd', (event) => {
64+
// `progress` is a value from 1 (top) to 0 (bottom)
65+
const { progress } = event.detail;
66+
67+
/**
68+
* Snap the background brightness based on the user's drag intent.
69+
* Progress > 0.4 implies an intent to open (snap dark),
70+
* while < 0.4 implies a dismissal (snap bright).
71+
*/
72+
const brightnessValue = progress > 0.4 ? DARKEST_PERCENT : 100;
73+
74+
// Reset to max darkness on snap-back for a nice visual effect
75+
presentingElement.style.setProperty('filter', `brightness(${brightnessValue}%)`, 'important');
76+
77+
// Re-enable transition for a smooth snap-back
78+
presentingElement.style.transition = 'filter 0.4s ease';
79+
});
80+
81+
modal.addEventListener('ionModalWillDismiss', () => {
82+
// Clean up styles when the modal is dismissed
83+
presentingElement.style.removeProperty('filter');
84+
presentingElement.style.removeProperty('transition');
85+
});
86+
</script>
87+
```

0 commit comments

Comments
 (0)