diff --git a/docs/api/modal.mdx b/docs/api/modal.mdx index e68e368290..c42f823e77 100644 --- a/docs/api/modal.mdx +++ b/docs/api/modal.mdx @@ -127,7 +127,7 @@ import CardExample from '@site/static/usage/v9/modal/card/basic/index.mdx'; :::info -[Content](./content) should be used inside of the sheet modal if you want your modal content to be scrollable. +[Content](./content.mdx) should be used inside of the sheet modal if you want your modal content to be scrollable. ::: @@ -175,34 +175,58 @@ import SheetScrollingContentExample from '@site/static/usage/v9/modal/sheet/expa -## Styling +## Theming -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. +[Controller modals](#controller-modals) are appended to the root of your application, outside of the component that presented them. Component-scoped styles will not reach these modals, so their styles must be applied globally, from a stylesheet that is not scoped to a component. -:::note +[Inline modals](#inline-modals-recommended) stay where they are declared in your template, so component-scoped styles do apply to them. -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. +### Styling -::: +Modals expose [CSS Custom Properties](#css-custom-properties) and [CSS Shadow Parts](#css-shadow-parts) for customizing their appearance. -:::note +import ThemeExample from '@site/static/usage/v9/modal/styling/theming/index.mdx'; -`ion-modal` works under the assumption that stacked modals are the same size. As a result, each subsequent modal will have no box shadow and a backdrop opacity of `0`. This is to avoid the effect of shadows and backdrops getting darker with each added modal. This can be changed by setting the `--box-shadow` and `--backdrop-opacity` CSS variables: + -::: +### Stacked Modals -``` +`ion-modal` works under the assumption that stacked modals are the same size. As a result, each subsequent modal will have no box shadow and a backdrop opacity of `0`. This is to avoid the effect of shadows and backdrops getting darker with each added modal. This can be changed by setting the `--box-shadow` and `--backdrop-opacity` CSS variables: + +```css ion-modal.stack-modal { --box-shadow: 0 28px 48px rgba(0, 0, 0, 0.4); --backdrop-opacity: var(--ion-backdrop-opacity, 0.32); } ``` -import ThemeExample from '@site/static/usage/v9/modal/styling/theming/index.mdx'; +### Sizing to Content - +A modal fills the height of its container by default. Setting the `--height` CSS variable to `auto`, `fit-content`, `min-content`, or `max-content` sizes the modal to the height of what it renders instead. + +:::warning + +The height must be set on the modal through the `--height` CSS variable. Setting `height` on the `content` [CSS Shadow Part](#css-shadow-parts) will still resize the modal, but any [Content](./content.mdx) inside of it will collapse to a height of `0`, leaving only the header visible. + +```css +/* DO NOT DO THIS */ +ion-modal::part(content) { + height: fit-content; +} + +/* Do this instead */ +ion-modal { + --height: fit-content; +} +``` + +::: + +import SizingToContentExample from '@site/static/usage/v9/modal/styling/sizing-to-content/index.mdx'; + + -### Animations +## Animations The enter and leave animations can be customized by using our animation builder and assigning animations to `enterAnimation` and `leaveAnimation`. @@ -220,7 +244,7 @@ import CustomDialogs from '@site/static/usage/v9/modal/custom-dialogs/index.mdx' 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. +- `ion-content` can be used in a custom dialog, including one that is sized to its contents. The dialog's height must come from the `--height` CSS variable rather than from the dialog's children. See [Sizing to Content](#sizing-to-content). - 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. ## Event Handling diff --git a/static/usage/v9/modal/styling/sizing-to-content/angular/example_component_css.md b/static/usage/v9/modal/styling/sizing-to-content/angular/example_component_css.md new file mode 100644 index 0000000000..92b72024d7 --- /dev/null +++ b/static/usage/v9/modal/styling/sizing-to-content/angular/example_component_css.md @@ -0,0 +1,8 @@ +```css +ion-modal { + --height: fit-content; + --width: 90%; + --border-radius: 8px; + --box-shadow: 0 28px 48px rgba(0, 0, 0, 0.4); +} +``` diff --git a/static/usage/v9/modal/styling/sizing-to-content/angular/example_component_html.md b/static/usage/v9/modal/styling/sizing-to-content/angular/example_component_html.md new file mode 100644 index 0000000000..3e5f8f3d89 --- /dev/null +++ b/static/usage/v9/modal/styling/sizing-to-content/angular/example_component_html.md @@ -0,0 +1,32 @@ +```html + + + App + + + + Open Modal + + + + + + Modal + + Close + + + + + + @for (item of ['Item 1', 'Item 2', 'Item 3']; track item) { + + {{ item }} + + } + + + + + +``` diff --git a/static/usage/v9/modal/styling/sizing-to-content/angular/example_component_ts.md b/static/usage/v9/modal/styling/sizing-to-content/angular/example_component_ts.md new file mode 100644 index 0000000000..45071ee743 --- /dev/null +++ b/static/usage/v9/modal/styling/sizing-to-content/angular/example_component_ts.md @@ -0,0 +1,23 @@ +```ts +import { Component } from '@angular/core'; +import { + IonButton, + IonButtons, + IonContent, + IonHeader, + IonItem, + IonLabel, + IonList, + IonModal, + IonTitle, + IonToolbar, +} from '@ionic/angular'; + +@Component({ + selector: 'app-example', + templateUrl: 'example.component.html', + styleUrls: ['example.component.css'], + imports: [IonButton, IonButtons, IonContent, IonHeader, IonItem, IonLabel, IonList, IonModal, IonTitle, IonToolbar], +}) +export class ExampleComponent {} +``` diff --git a/static/usage/v9/modal/styling/sizing-to-content/demo.html b/static/usage/v9/modal/styling/sizing-to-content/demo.html new file mode 100644 index 0000000000..33eab3e0af --- /dev/null +++ b/static/usage/v9/modal/styling/sizing-to-content/demo.html @@ -0,0 +1,61 @@ + + + + + + Modal | Sizing to Content + + + + + + + + + + + + App + + + + Open Modal + + + + + Modal + + Close + + + + + + + Item 1 + + + Item 2 + + + Item 3 + + + + + + + + + + diff --git a/static/usage/v9/modal/styling/sizing-to-content/index.mdx b/static/usage/v9/modal/styling/sizing-to-content/index.mdx new file mode 100644 index 0000000000..2421774fa2 --- /dev/null +++ b/static/usage/v9/modal/styling/sizing-to-content/index.mdx @@ -0,0 +1,35 @@ +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_example_component_html from './angular/example_component_html.md'; +import angular_example_component_css from './angular/example_component_css.md'; +import angular_example_component_ts from './angular/example_component_ts.md'; + + diff --git a/static/usage/v9/modal/styling/sizing-to-content/javascript.md b/static/usage/v9/modal/styling/sizing-to-content/javascript.md new file mode 100644 index 0000000000..abbaaaaa6c --- /dev/null +++ b/static/usage/v9/modal/styling/sizing-to-content/javascript.md @@ -0,0 +1,47 @@ +```html + + + + + App + + + + Open Modal + + + + + Modal + + Close + + + + + + + Item 1 + + + Item 2 + + + Item 3 + + + + + + + +``` diff --git a/static/usage/v9/modal/styling/sizing-to-content/react/main_css.md b/static/usage/v9/modal/styling/sizing-to-content/react/main_css.md new file mode 100644 index 0000000000..92b72024d7 --- /dev/null +++ b/static/usage/v9/modal/styling/sizing-to-content/react/main_css.md @@ -0,0 +1,8 @@ +```css +ion-modal { + --height: fit-content; + --width: 90%; + --border-radius: 8px; + --box-shadow: 0 28px 48px rgba(0, 0, 0, 0.4); +} +``` diff --git a/static/usage/v9/modal/styling/sizing-to-content/react/main_tsx.md b/static/usage/v9/modal/styling/sizing-to-content/react/main_tsx.md new file mode 100644 index 0000000000..834160ac40 --- /dev/null +++ b/static/usage/v9/modal/styling/sizing-to-content/react/main_tsx.md @@ -0,0 +1,63 @@ +```tsx +import React, { useRef } from 'react'; +import { + IonButton, + IonButtons, + IonContent, + IonHeader, + IonItem, + IonLabel, + IonList, + IonModal, + IonPage, + IonTitle, + IonToolbar, +} from '@ionic/react'; + +import './main.css'; + +function Example() { + const modal = useRef(null); + + function dismiss() { + modal.current?.dismiss(); + } + + return ( + + + + App + + + + + Open Modal + + + + + + Modal + + dismiss()}>Close + + + + + + {['Item 1', 'Item 2', 'Item 3'].map((item) => ( + + {item} + + ))} + + + + + + ); +} + +export default Example; +``` diff --git a/static/usage/v9/modal/styling/sizing-to-content/vue.md b/static/usage/v9/modal/styling/sizing-to-content/vue.md new file mode 100644 index 0000000000..33dedffb3a --- /dev/null +++ b/static/usage/v9/modal/styling/sizing-to-content/vue.md @@ -0,0 +1,59 @@ +```vue + + + + + +``` diff --git a/versioned_docs/version-v6/api/modal.mdx b/versioned_docs/version-v6/api/modal.mdx index e9f562d368..2f37874f04 100644 --- a/versioned_docs/version-v6/api/modal.mdx +++ b/versioned_docs/version-v6/api/modal.mdx @@ -137,30 +137,30 @@ import SheetHandleBehaviorExample from '@site/static/usage/v6/modal/sheet/handle -## Styling +## Theming -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. +[Controller modals](#controller-modals) are appended to the root of your application, outside of the component that presented them. Component-scoped styles will not reach these modals, so their styles must be applied globally, from a stylesheet that is not scoped to a component. -:::note -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. -::: +[Inline modals](#inline-modals-recommended) stay where they are declared in your template, so component-scoped styles do apply to them. + +### Styling + +import ThemeExample from '@site/static/usage/v6/modal/styling/theming/index.mdx'; + + + +### Stacked Modals -:::note `ion-modal` works under the assumption that stacked modals are the same size. As a result, each subsequent modal will have no box shadow and a backdrop opacity of `0`. This is to avoid the effect of shadows and backdrops getting darker with each added modal. This can be changed by setting the `--box-shadow` and `--backdrop-opacity` CSS variables: -::: -``` +```css ion-modal.stack-modal { --box-shadow: 0 28px 48px rgba(0, 0, 0, 0.4); --backdrop-opacity: var(--ion-backdrop-opacity, 0.32); } ``` -import ThemeExample from '@site/static/usage/v6/modal/styling/theming/index.mdx'; - - - -### Animations +## Animations The enter and leave animations can be customized by using our animation builder and assigning animations to `enterAnimation` and `leaveAnimation`. diff --git a/versioned_docs/version-v7/api/modal.mdx b/versioned_docs/version-v7/api/modal.mdx index c098fe75b2..1ec436cd96 100644 --- a/versioned_docs/version-v7/api/modal.mdx +++ b/versioned_docs/version-v7/api/modal.mdx @@ -161,30 +161,30 @@ import SheetHandleBehaviorExample from '@site/static/usage/v7/modal/sheet/handle -## Styling +## Theming -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. +[Controller modals](#controller-modals) are appended to the root of your application, outside of the component that presented them. Component-scoped styles will not reach these modals, so their styles must be applied globally, from a stylesheet that is not scoped to a component. -:::note -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. -::: +[Inline modals](#inline-modals-recommended) stay where they are declared in your template, so component-scoped styles do apply to them. + +### Styling + +import ThemeExample from '@site/static/usage/v7/modal/styling/theming/index.mdx'; + + + +### Stacked Modals -:::note `ion-modal` works under the assumption that stacked modals are the same size. As a result, each subsequent modal will have no box shadow and a backdrop opacity of `0`. This is to avoid the effect of shadows and backdrops getting darker with each added modal. This can be changed by setting the `--box-shadow` and `--backdrop-opacity` CSS variables: -::: -``` +```css ion-modal.stack-modal { --box-shadow: 0 28px 48px rgba(0, 0, 0, 0.4); --backdrop-opacity: var(--ion-backdrop-opacity, 0.32); } ``` -import ThemeExample from '@site/static/usage/v7/modal/styling/theming/index.mdx'; - - - -### Animations +## Animations The enter and leave animations can be customized by using our animation builder and assigning animations to `enterAnimation` and `leaveAnimation`. diff --git a/versioned_docs/version-v8/api/modal.mdx b/versioned_docs/version-v8/api/modal.mdx index 8f38444c64..f352f77999 100644 --- a/versioned_docs/version-v8/api/modal.mdx +++ b/versioned_docs/version-v8/api/modal.mdx @@ -175,34 +175,30 @@ import SheetScrollingContentExample from '@site/static/usage/v8/modal/sheet/expa -## Styling +## Theming -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. +[Controller modals](#controller-modals) are appended to the root of your application, outside of the component that presented them. Component-scoped styles will not reach these modals, so their styles must be applied globally, from a stylesheet that is not scoped to a component. -:::note +[Inline modals](#inline-modals-recommended) stay where they are declared in your template, so component-scoped styles do apply to them. -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. +### Styling -::: +import ThemeExample from '@site/static/usage/v8/modal/styling/theming/index.mdx'; -:::note + -`ion-modal` works under the assumption that stacked modals are the same size. As a result, each subsequent modal will have no box shadow and a backdrop opacity of `0`. This is to avoid the effect of shadows and backdrops getting darker with each added modal. This can be changed by setting the `--box-shadow` and `--backdrop-opacity` CSS variables: +### Stacked Modals -::: +`ion-modal` works under the assumption that stacked modals are the same size. As a result, each subsequent modal will have no box shadow and a backdrop opacity of `0`. This is to avoid the effect of shadows and backdrops getting darker with each added modal. This can be changed by setting the `--box-shadow` and `--backdrop-opacity` CSS variables: -``` +```css ion-modal.stack-modal { --box-shadow: 0 28px 48px rgba(0, 0, 0, 0.4); --backdrop-opacity: var(--ion-backdrop-opacity, 0.32); } ``` -import ThemeExample from '@site/static/usage/v8/modal/styling/theming/index.mdx'; - - - -### Animations +## Animations The enter and leave animations can be customized by using our animation builder and assigning animations to `enterAnimation` and `leaveAnimation`.