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): add custom dialog playground #2444

Merged
merged 2 commits into from
Jul 20, 2022
Merged
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
18 changes: 14 additions & 4 deletions docs/api/modal.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,11 @@ import Slots from '@site/static/auto-generated/modal/slots.md';
</head>

import EncapsulationPill from '@components/page/api/EncapsulationPill';
import APITOCInline from '@components/page/api/APITOCInline';

<EncapsulationPill type="shadow" />


A Modal is a dialog that appears on top of the app's content, and must be dismissed by the app before interaction can resume. It is useful as a select component when there are a lot of options to choose from, or when filtering items in a list, as well as many other use cases.


## Inline Modals (Recommended)

`ion-modal` can be used by writing the component directly in your template. This reduces the number of handlers you need to wire up in order to present the modal.
Expand Down Expand Up @@ -159,6 +156,19 @@ import AnimationsExample from '@site/static/usage/modal/styling/animations/index

<AnimationsExample />

## Custom Dialogs

While `ion-modal` is most often used for full-page views, cards, or sheets, it is also possible to use it for custom dialogs. This is useful if developers need an interface that is more complex than what components such as [ion-alert](./alert) or [ion-loading](./loading) provide.

import CustomDialogs from '@site/static/usage/modal/custom-dialogs/index.md';

<CustomDialogs />

A few things to keep in mind when creating custom dialogs:

* `ion-content` is intended to be used in full-page modals, cards, and sheets. If your custom dialog has a dynamic or unknown size, `ion-content` should not be used.
* Creating custom dialogs provides a way of ejecting from the default modal experience. As a result, custom dialogs should not be used with card or sheet modals.

## Interfaces

### ModalOptions
Expand Down Expand Up @@ -226,7 +236,7 @@ Sheet modals that have had their backdrop disabled by the `backdropBreakpoint` p

Sheet modals allow users to interact with content behind the modal when the `backdropBreakpoint` property is used. The backdrop will be disabled up to and including the specified `backdropBreakpoint` and will be enabled after it.

When the backdrop is disabled, users will be able to interact with elements outside the sheet modal using a pointer or keyboard. Assistive technologies may not focus outside the sheet modal by default due to the usage of `aria-modal`. We recommend avoiding features such as autofocus here as it can cause assistive technologies to jump between two interactive contexts without warning the user.
When the backdrop is disabled, users will be able to interact with elements outside the sheet modal using a pointer or keyboard. Assistive technologies may not focus outside the sheet modal by default due to the usage of `aria-modal`. We recommend avoiding features such as autofocus here as it can cause assistive technologies to jump between two interactive contexts without warning the user.


## Properties
Expand Down
28 changes: 28 additions & 0 deletions static/usage/modal/custom-dialogs/angular/app_component_css.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
```css
ion-modal#example-modal {
--width: fit-content;
--min-width: 250px;
--height: fit-content;
--border-radius: 6px;
--box-shadow: 0 28px 48px rgba(0, 0, 0, 0.4);
}

ion-modal#example-modal h1 {
margin: 20px 20px 10px 20px;
}

ion-modal#example-modal ion-icon {
margin-right: 6px;

width: 48px;
height: 48px;

padding: 4px 0;

color: #aaaaaa;
}

ion-modal#example-modal .wrapper {
margin-bottom: 10px;
}
```
35 changes: 35 additions & 0 deletions static/usage/modal/custom-dialogs/angular/app_component_html.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
```html
<ion-app>
<ion-header>
<ion-toolbar>
<ion-title>App</ion-title>
</ion-toolbar>
</ion-header>
<ion-content class="ion-padding">
<ion-button id="open-custom-dialog" expand="block">Open Custom Dialog</ion-button>

<ion-modal id="example-modal" #modal trigger="open-custom-dialog">
<ng-template>
<div class="wrapper">
<h1>Dialog header</h1>

<ion-list lines="none">
<ion-item button="true" detail="false" (click)="modal.dismiss()">
<ion-icon name="person-circle"></ion-icon>
<ion-label>Item 1</ion-label>
</ion-item>
<ion-item button="true" detail="false" (click)="modal.dismiss()">
<ion-icon name="person-circle"></ion-icon>
<ion-label>Item 2</ion-label>
</ion-item>
<ion-item button="true" detail="false" (click)="modal.dismiss()">
<ion-icon name="person-circle"></ion-icon>
<ion-label>Item 3</ion-label>
</ion-item>
</ion-list>
</div>
</ng-template>
</ion-modal>
</ion-content>
</ion-app>
```
81 changes: 81 additions & 0 deletions static/usage/modal/custom-dialogs/demo.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Modal | Custom Dialog</title>
<link rel="stylesheet" href="../../common.css" />
<script src="../../common.js"></script>
<script type="module" src="https://cdn.jsdelivr.net/npm/@ionic/[email protected]/dist/ionic/ionic.esm.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ionic/[email protected]/css/ionic.bundle.css" />
<style>
ion-modal {
--width: fit-content;
--min-width: 250px;
--height: fit-content;
--border-radius: 6px;
--box-shadow: 0 28px 48px rgba(0, 0, 0, 0.4);
}

ion-modal h1 {
margin: 20px 20px 10px 20px;
}

ion-modal ion-icon {
margin-right: 6px;

width: 48px;
height: 48px;

padding: 4px 0;

color: #aaaaaa;
}

ion-modal .wrapper {
margin-bottom: 10px;
}
</style>
</head>

<body>
<ion-app>
<ion-header>
<ion-toolbar>
<ion-title>App</ion-title>
</ion-toolbar>
</ion-header>
<ion-content class="ion-padding">
<ion-button id="custom-modal" expand="block">Open Custom Dialog</ion-button>

<ion-modal trigger="custom-modal">
<div class="wrapper">
<h1>Dialog header</h1>

<ion-list lines="none">
<ion-item button="true" detail="false" onclick="dismiss()">
<ion-icon name="person-circle"></ion-icon>
<ion-label>Item 1</ion-label>
</ion-item>
<ion-item button="true" detail="false" onclick="dismiss()">
<ion-icon name="person-circle"></ion-icon>
<ion-label>Item 2</ion-label>
</ion-item>
<ion-item button="true" detail="false" onclick="dismiss()">
<ion-icon name="person-circle"></ion-icon>
<ion-label>Item 3</ion-label>
</ion-item>
</ion-list>
</div>
</ion-modal>
</ion-content>
</ion-app>

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

</html>
31 changes: 31 additions & 0 deletions static/usage/modal/custom-dialogs/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import Playground from '@site/src/components/global/Playground';

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

import react_main_tsx from './react/main_tsx.md';
import react_main_css from './react/main_css.md';

import angular_app_component_css from './angular/app_component_css.md';
import angular_app_component_html from './angular/app_component_html.md';

<Playground
code={{
javascript,
vue,
react: {
files: {
'src/main.tsx': react_main_tsx,
'src/main.css': react_main_css,
},
},
angular: {
files: {
'src/app/app.component.html': angular_app_component_html,
'src/app/app.component.css': angular_app_component_css,
},
},
}}
src="usage/modal/custom-dialogs/demo.html"
devicePreview
/>
69 changes: 69 additions & 0 deletions static/usage/modal/custom-dialogs/javascript.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
```html
<style>
ion-modal#example-modal {
--width: fit-content;
--min-width: 250px;
--height: fit-content;
--border-radius: 6px;
--box-shadow: 0 28px 48px rgba(0, 0, 0, 0.4);
}

ion-modal#example-modal h1 {
margin: 20px 20px 10px 20px;
}

ion-modal#example-modal ion-icon {
margin-right: 6px;

width: 48px;
height: 48px;

padding: 4px 0;

color: #aaaaaa;
}

ion-modal#example-modal .wrapper {
margin-bottom: 10px;
}
</style>

<ion-app>
<ion-header>
<ion-toolbar>
<ion-title>App</ion-title>
</ion-toolbar>
</ion-header>
<ion-content class="ion-padding">
<ion-button id="open-custom-dialog" expand="block">Open Custom Dialog</ion-button>

<ion-modal id="example-modal" trigger="open-custom-dialog">
<div class="wrapper">
<h1>Dialog header</h1>

<ion-list lines="none">
<ion-item button="true" detail="false" onclick="dismiss()">
<ion-icon name="person-circle"></ion-icon>
<ion-label>Item 1</ion-label>
</ion-item>
<ion-item button="true" detail="false" onclick="dismiss()">
<ion-icon name="person-circle"></ion-icon>
<ion-label>Item 2</ion-label>
</ion-item>
<ion-item button="true" detail="false" onclick="dismiss()">
<ion-icon name="person-circle"></ion-icon>
<ion-label>Item 3</ion-label>
</ion-item>
</ion-list>
</div>
</ion-modal>
</ion-content>
</ion-app>

<script>
var modal = document.querySelector('ion-modal');
function dismiss() {
modal.dismiss();
}
</script>
```
28 changes: 28 additions & 0 deletions static/usage/modal/custom-dialogs/react/main_css.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
```css
ion-modal#example-modal {
--width: fit-content;
--min-width: 250px;
--height: fit-content;
--border-radius: 6px;
--box-shadow: 0 28px 48px rgba(0, 0, 0, 0.4);
}

ion-modal#example-modal h1 {
margin: 20px 20px 10px 20px;
}

ion-modal#example-modal ion-icon {
margin-right: 6px;

width: 48px;
height: 48px;

padding: 4px 0;

color: #aaaaaa;
}

ion-modal#example-modal .wrapper {
margin-bottom: 10px;
}
```
64 changes: 64 additions & 0 deletions static/usage/modal/custom-dialogs/react/main_tsx.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
```tsx
import React, { useRef } from 'react';
import {
IonButton,
IonModal,
IonHeader,
IonContent,
IonToolbar,
IonTitle,
IonPage,
IonList,
IonItem,
IonLabel,
IonIcon,
} from '@ionic/react';
import { personCircle } from 'ionicons/icons';

import './main.css';

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

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

return (
<IonPage>
<IonHeader>
<IonToolbar>
<IonTitle>App</IonTitle>
</IonToolbar>
</IonHeader>
<IonContent class="ion-padding">
<IonButton id="open-custom-dialog" expand="block">
Open Custom Dialog
</IonButton>
<IonModal id="example-modal" ref={modal} trigger="open-custom-dialog">
<div className="wrapper">
<h1>Dialog header</h1>

<IonList lines="none">
<IonItem button={true} detail={false} onClick={dismiss}>
<IonIcon icon={personCircle}></IonIcon>
<IonLabel>Item 1</IonLabel>
</IonItem>
<IonItem button={true} detail={false} onClick={dismiss}>
<IonIcon icon={personCircle}></IonIcon>
<IonLabel>Item 2</IonLabel>
</IonItem>
<IonItem button={true} detail={false} onClick={dismiss}>
<IonIcon icon={personCircle}></IonIcon>
<IonLabel>Item 3</IonLabel>
</IonItem>
</IonList>
</div>
</IonModal>
</IonContent>
</IonPage>
);
}

export default Example;
```
Loading