From ade21d3b1994438cd8d0da89f6a4e1791f43e942 Mon Sep 17 00:00:00 2001 From: Liam DeBeasi Date: Tue, 30 Nov 2021 14:22:45 -0500 Subject: [PATCH] docs(modal): add inline modal docs (#24269) --- core/src/components/modal/readme.md | 374 ++++++++++++++---- core/src/components/modal/usage/angular.md | 84 +++- core/src/components/modal/usage/javascript.md | 37 ++ core/src/components/modal/usage/react.md | 77 +++- core/src/components/modal/usage/stencil.md | 60 +++ core/src/components/modal/usage/vue.md | 89 +++-- 6 files changed, 585 insertions(+), 136 deletions(-) diff --git a/core/src/components/modal/readme.md b/core/src/components/modal/readme.md index 6c41cd55eb..97a6cb3dd9 100644 --- a/core/src/components/modal/readme.md +++ b/core/src/components/modal/readme.md @@ -90,31 +90,9 @@ interface ModalOptions { The modal can be dismissed after creation by calling the `dismiss()` method on the modal controller. The `onDidDismiss` function can be called to perform an action after the modal is dismissed. -## Customization +## Styling -Modal uses scoped encapsulation, which means it will automatically scope its CSS by appending each of the styles with an additional class at runtime. Overriding scoped selectors in CSS requires a [higher specificity](https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity) selector. - -We recommend passing a custom class to `cssClass` in the `create` method and using that to add custom styles to the host and inner elements. This property can also accept multiple classes separated by spaces. View the [Usage](#usage) section for an example of how to pass a class using `cssClass`. - -```css -/* DOES NOT WORK - not specific enough */ -.modal-wrapper { - background: #222; -} - -/* Works - pass "my-custom-class" in cssClass to increase specificity */ -.my-custom-class .modal-wrapper { - background: #222; -} -``` - -Any of the defined [CSS Custom Properties](#css-custom-properties) can be used to style the Modal without needing to target individual elements: - -```css -.my-custom-class { - --background: #222; -} -``` +Modals are presented at the root of your application so they overlay your entire app. This behavior applies to both inline modals and modals presented from a controller. As a result, custom modal styles can not be scoped to a particular component as they will not apply to the modal. Instead, styles must be applied globally. For most developers, placing the custom styles in `global.css` is sufficient. > If you are building an Ionic Angular app, the styles need to be added to a global stylesheet file. Read [Style Placement](#style-placement) in the Angular section below for more information. @@ -170,6 +148,70 @@ interface ModalAttributes extends JSXBase.HTMLAttributes {} ### Angular +### Inline Modal + +```html + + + + Modal Content + + + + +Click to open modal + + + Modal Content + + + + + + + Modal Content + + + + + + + Modal Content + + + + + + + + + +``` + +```typescript +import { Component } from '@angular/core'; +import { IonRouterOutlet } from '@ionic/angular'; + +@Component({ + selector: 'modal-example', + templateUrl: 'modal-example.html', + styleUrls: ['./modal-example.css'] +}) +export class ModalExample { + constructor(public routerOutlet: IonRouterOutlet) {} +} +``` + +### Modal Controller + ```typescript import { Component } from '@angular/core'; import { ModalController } from '@ionic/angular'; @@ -210,7 +252,7 @@ export class ModalPage { > If you need a wrapper element inside of your modal component, we recommend using a `
` so that the component dimensions are still computed properly. -### Passing Data +#### Passing Data During creation of a modal, data can be passed in through the `componentProps`. The previous example can be written to include data: @@ -243,7 +285,7 @@ export class ModalPage { } ``` -### Dismissing a Modal +#### Dismissing a Modal A modal can be dismissed by calling the dismiss method on the modal controller and optionally passing any data from the modal. @@ -300,7 +342,7 @@ import { EventModalModule } from '../modals/event/event.module'; export class CalendarComponentModule {} ``` -### Card Modals +#### Card Modals Modals in iOS mode have the ability to be presented in a card-style and swiped to close. The card-style presentation and swipe to close gesture are not mutually exclusive, meaning you can pick and choose which features you want to use. For example, you can have a card-style modal that cannot be swiped or a full sized modal that can be swiped. @@ -342,9 +384,8 @@ async presentModal() { } ``` -### Sheet Modals +#### Sheet Modals -**Controller** ```javascript import { IonRouterOutlet } from '@ionic/angular'; @@ -360,17 +401,6 @@ async presentModal() { } ``` - -**Inline** -```html - - - - - -``` - - ### Style Placement In Angular, the CSS of a specific page is scoped only to elements of that page. Even though the Modal can be presented from within a page, the `ion-modal` element is appended outside of the current page. This means that any custom styles need to go in a global stylesheet file. In an Ionic Angular starter this can be the `src/global.scss` file or you can register a new global style file by [adding to the `styles` build option in `angular.json`](https://angular.io/guide/workspace-config#style-script-config). @@ -378,6 +408,44 @@ In Angular, the CSS of a specific page is scoped only to elements of that page. ### Javascript +### Inline Modal + +```html + + + Modal Content + + + +Click to open modal + + Modal Content + + + + + Modal Content + + + + + Modal Content + + + +``` + +### Using JavaScript + ```javascript customElements.define('modal-page', class extends HTMLElement { connectedCallback() { @@ -497,6 +565,77 @@ modalElement.breakpoints = [0, 0.5, 1]; ### React +### Inline Modal + +```tsx +import { React, useRef } from 'react'; +const App: React.FC = () => { + const routerRef = useRef(null); + + return ( + + + + } exact={true} /> + + + + ) +}; + +... + +interface Props { + router: HTMLIonRouterOutletElement | null; +} + +import React from 'react'; +import AppReactComponent from './AppReactComponent'; +import { IonModal, IonContent, IonButton } from '@ionic/react'; +export const ModalExample: React.FC = ({ router }) => { + return ( + <> + {/* Default */} + + Modal Content + + + {/* Use a trigger */} + Click to open modal + + Modal Content + + + {/* Sheet Modal */} + + Modal Content + + + {/* Card Modal */} + + Modal Content + + + {/* Passing Props */} + + + + + ); +}; +``` + + +### useIonModal Hook + > `useIonModal` requires being a descendant of ``. If you need to use a modal outside of an ``, consider using the component method instead. @@ -583,7 +722,7 @@ export const ModalExample: React.FC = () => { }; ``` -### Card Modals +#### Card Modals Modals in iOS mode have the ability to be presented in a card-style and swiped to close. The card-style presentation and swipe to close gesture are not mutually exclusive, meaning you can pick and choose which features you want to use. For example, you can have a card-style modal that cannot be swiped or a full sized modal that can be swiped. @@ -631,7 +770,7 @@ const Home: React.FC = ({ router }) => { ``` -In most scenarios, setting a ref on `IonRouterOutlet` and passing that ref's `current` value to `presentingElement` is fine. In cases where you are presenting a card-style modal from within another modal, you should pass in the top-most `ion-modal` ref as the `presentingElement`. +In most scenarios, setting a ref on `IonRouterOutlet` and passing that ref's `current` value to `presentingElement` is fine. In cases where you are presenting a card-style modal from within another modal, you should pass in the top-most `IonModal` ref as the `presentingElement`. ```tsx { @@ -699,6 +838,66 @@ const Home: React.FC = () => { ### Stencil +### Inline Modal + +```tsx +import { Component, Element, h } from '@stencil/core'; + +@Component({ + tag: 'modal-example', + styleUrl: 'modal-example.css' +}) +export class ModalExample { + @Element() el: any; + + componentDidLoad() { + this.routerOutlet = this.el.closest('ion-router-outlet'); + } + + render() { + return ( +
+ {/* Default */} + + Modal Content + + + {/* Use a trigger */} + Click to open modal + + Modal Content + + + {/* Sheet Modal */} + + Modal Content + + + {/* Card Modal */} + + Modal Content + + + {/* Passing Props */} + + + +
+ ) + } +} +``` + +### Modal Controller + ```tsx import { Component, h } from '@stencil/core'; @@ -909,6 +1108,56 @@ export class ModalExample { ### Vue +### Inline Modal + +```html + + + Modal Content + + + +Click to open modal + + Modal Content + + + + + Modal Content + + + + + Modal Content + + + + + + + + +``` + +### Modal Controller + ```html