diff --git a/docs/api/modal.mdx b/docs/api/modal.mdx index e68e3682909..c42f823e770 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/code/stackblitz/v9/angular/package-lock.json b/static/code/stackblitz/v9/angular/package-lock.json index 88ba71f36ab..0be6ce50393 100644 --- a/static/code/stackblitz/v9/angular/package-lock.json +++ b/static/code/stackblitz/v9/angular/package-lock.json @@ -14,8 +14,8 @@ "@angular/platform-browser": "^22.0.0", "@angular/platform-browser-dynamic": "^22.0.0", "@angular/router": "^22.0.0", - "@ionic/angular": "9.0.1", - "@ionic/core": "9.0.1", + "@ionic/angular": "9.0.1-dev.11788212611.154b1596", + "@ionic/core": "9.0.1-dev.11788212611.154b1596", "ionicons": "8.1.0", "rxjs": "^7.8.1", "tslib": "^2.5.0" @@ -2578,12 +2578,12 @@ } }, "node_modules/@ionic/angular": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@ionic/angular/-/angular-9.0.1.tgz", + "version": "9.0.1-dev.11788212611.154b1596", + "resolved": "https://registry.npmjs.org/@ionic/angular/-/angular-9.0.1-dev.11788212611.154b1596.tgz", "integrity": "sha512-q6HQdwIb5/uqZewVoBhRfz07Y9tR/cswWCY5Viy0BV5mUoLfOciAbeWqDaAK5YDc3QGZ2UH1bztsbj/VlpmOoQ==", "license": "MIT", "dependencies": { - "@ionic/core": "9.0.1", + "@ionic/core": "9.0.1-dev.11788212611.154b1596", "ionicons": "^8.0.13", "jsonc-parser": "^3.0.0", "tslib": "^2.3.0" @@ -2602,8 +2602,8 @@ } }, "node_modules/@ionic/core": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@ionic/core/-/core-9.0.1.tgz", + "version": "9.0.1-dev.11788212611.154b1596", + "resolved": "https://registry.npmjs.org/@ionic/core/-/core-9.0.1-dev.11788212611.154b1596.tgz", "integrity": "sha512-70fIYFxGuBFYOanWIl1PF3/emB+xVQjLQ9OZqgI+9ki8nEZH1y90YkTtAmleLl2jTx6TUpSaJpdUnzkBreIt7w==", "license": "MIT", "dependencies": { diff --git a/static/code/stackblitz/v9/angular/package.json b/static/code/stackblitz/v9/angular/package.json index d6cfcdf288b..1668310fc8e 100644 --- a/static/code/stackblitz/v9/angular/package.json +++ b/static/code/stackblitz/v9/angular/package.json @@ -15,8 +15,8 @@ "@angular/platform-browser": "^22.0.0", "@angular/platform-browser-dynamic": "^22.0.0", "@angular/router": "^22.0.0", - "@ionic/angular": "9.0.1", - "@ionic/core": "9.0.1", + "@ionic/angular": "9.0.1-dev.11788212611.154b1596", + "@ionic/core": "9.0.1-dev.11788212611.154b1596", "ionicons": "8.1.0", "rxjs": "^7.8.1", "tslib": "^2.5.0" diff --git a/static/code/stackblitz/v9/html/package-lock.json b/static/code/stackblitz/v9/html/package-lock.json index 6067d6733e8..1f92f7310b9 100644 --- a/static/code/stackblitz/v9/html/package-lock.json +++ b/static/code/stackblitz/v9/html/package-lock.json @@ -6,7 +6,7 @@ "": { "name": "html-starter", "dependencies": { - "@ionic/core": "9.0.1", + "@ionic/core": "9.0.1-dev.11788212611.154b1596", "ionicons": "8.1.0" }, "devDependencies": { @@ -16,8 +16,8 @@ } }, "node_modules/@ionic/core": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@ionic/core/-/core-9.0.1.tgz", + "version": "9.0.1-dev.11788212611.154b1596", + "resolved": "https://registry.npmjs.org/@ionic/core/-/core-9.0.1-dev.11788212611.154b1596.tgz", "integrity": "sha512-70fIYFxGuBFYOanWIl1PF3/emB+xVQjLQ9OZqgI+9ki8nEZH1y90YkTtAmleLl2jTx6TUpSaJpdUnzkBreIt7w==", "license": "MIT", "dependencies": { diff --git a/static/code/stackblitz/v9/html/package.json b/static/code/stackblitz/v9/html/package.json index 136cfd7608c..22d686a2c65 100644 --- a/static/code/stackblitz/v9/html/package.json +++ b/static/code/stackblitz/v9/html/package.json @@ -9,7 +9,7 @@ "start": "vite preview" }, "dependencies": { - "@ionic/core": "9.0.1", + "@ionic/core": "9.0.1-dev.11788212611.154b1596", "ionicons": "8.1.0" }, "devDependencies": { diff --git a/static/code/stackblitz/v9/react/package-lock.json b/static/code/stackblitz/v9/react/package-lock.json index 8ea6b23f5e6..47616f5ca0c 100644 --- a/static/code/stackblitz/v9/react/package-lock.json +++ b/static/code/stackblitz/v9/react/package-lock.json @@ -8,8 +8,8 @@ "name": "vite-react-typescript", "version": "0.1.0", "dependencies": { - "@ionic/react": "9.0.1", - "@ionic/react-router": "9.0.1", + "@ionic/react": "9.0.1-dev.11788212611.154b1596", + "@ionic/react-router": "9.0.1-dev.11788212611.154b1596", "@types/node": "^24.0.0", "@types/react": "^19.0.0", "@types/react-dom": "^19.0.0", @@ -254,8 +254,8 @@ "license": "MIT" }, "node_modules/@ionic/core": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@ionic/core/-/core-9.0.1.tgz", + "version": "9.0.1-dev.11788212611.154b1596", + "resolved": "https://registry.npmjs.org/@ionic/core/-/core-9.0.1-dev.11788212611.154b1596.tgz", "integrity": "sha512-70fIYFxGuBFYOanWIl1PF3/emB+xVQjLQ9OZqgI+9ki8nEZH1y90YkTtAmleLl2jTx6TUpSaJpdUnzkBreIt7w==", "license": "MIT", "dependencies": { @@ -268,12 +268,12 @@ } }, "node_modules/@ionic/react": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@ionic/react/-/react-9.0.1.tgz", + "version": "9.0.1-dev.11788212611.154b1596", + "resolved": "https://registry.npmjs.org/@ionic/react/-/react-9.0.1-dev.11788212611.154b1596.tgz", "integrity": "sha512-dO257Wl1RSz5g2X0uHkHZOKZYGafFPXcU0EYPgROHxKBUVZpM5VimUZVNcAjkyWRDwDyN0Bjz+7TVfCN3DDPUQ==", "license": "MIT", "dependencies": { - "@ionic/core": "9.0.1", + "@ionic/core": "9.0.1-dev.11788212611.154b1596", "@stencil/react-output-target": "^1.6.2", "ionicons": "^8.0.13", "tslib": "*" @@ -284,12 +284,12 @@ } }, "node_modules/@ionic/react-router": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@ionic/react-router/-/react-router-9.0.1.tgz", + "version": "9.0.1-dev.11788212611.154b1596", + "resolved": "https://registry.npmjs.org/@ionic/react-router/-/react-router-9.0.1-dev.11788212611.154b1596.tgz", "integrity": "sha512-+JIil95Z6jkJ5eYfTqfb0ssI2zUcONigoqvtZECUwCN56jfQLUoEvk9ZkaR0JBsjetQxltPBxdKcHbyhXPPAww==", "license": "MIT", "dependencies": { - "@ionic/react": "9.0.1", + "@ionic/react": "9.0.1-dev.11788212611.154b1596", "tslib": "*" }, "peerDependencies": { diff --git a/static/code/stackblitz/v9/react/package.json b/static/code/stackblitz/v9/react/package.json index 45306941fb5..86864c343db 100644 --- a/static/code/stackblitz/v9/react/package.json +++ b/static/code/stackblitz/v9/react/package.json @@ -3,8 +3,8 @@ "version": "0.1.0", "private": true, "dependencies": { - "@ionic/react": "9.0.1", - "@ionic/react-router": "9.0.1", + "@ionic/react": "9.0.1-dev.11788212611.154b1596", + "@ionic/react-router": "9.0.1-dev.11788212611.154b1596", "@types/node": "^24.0.0", "@types/react": "^19.0.0", "@types/react-dom": "^19.0.0", diff --git a/static/code/stackblitz/v9/vue/package-lock.json b/static/code/stackblitz/v9/vue/package-lock.json index cccd51c138d..91ad8a58ec1 100644 --- a/static/code/stackblitz/v9/vue/package-lock.json +++ b/static/code/stackblitz/v9/vue/package-lock.json @@ -8,8 +8,8 @@ "name": "vite-vue-starter", "version": "0.0.0", "dependencies": { - "@ionic/vue": "9.0.1", - "@ionic/vue-router": "9.0.1", + "@ionic/vue": "9.0.1-dev.11788212611.154b1596", + "@ionic/vue-router": "9.0.1-dev.11788212611.154b1596", "vue": "^3.2.25", "vue-router": "5.3.0" }, @@ -63,8 +63,8 @@ } }, "node_modules/@ionic/core": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@ionic/core/-/core-9.0.1.tgz", + "version": "9.0.1-dev.11788212611.154b1596", + "resolved": "https://registry.npmjs.org/@ionic/core/-/core-9.0.1-dev.11788212611.154b1596.tgz", "integrity": "sha512-70fIYFxGuBFYOanWIl1PF3/emB+xVQjLQ9OZqgI+9ki8nEZH1y90YkTtAmleLl2jTx6TUpSaJpdUnzkBreIt7w==", "license": "MIT", "dependencies": { @@ -77,23 +77,23 @@ } }, "node_modules/@ionic/vue": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@ionic/vue/-/vue-9.0.1.tgz", + "version": "9.0.1-dev.11788212611.154b1596", + "resolved": "https://registry.npmjs.org/@ionic/vue/-/vue-9.0.1-dev.11788212611.154b1596.tgz", "integrity": "sha512-CwgLj7HKBwv/xRIsXqqvHCH+QGQVMjSf3CIWbQ6x+NpnSqlj8Ve5biZwfGTL0zdd3OaclLiDkrbxMVCLHG1Ovw==", "license": "MIT", "dependencies": { - "@ionic/core": "9.0.1", + "@ionic/core": "9.0.1-dev.11788212611.154b1596", "@stencil/vue-output-target": "0.14.2", "ionicons": "^8.0.13" } }, "node_modules/@ionic/vue-router": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@ionic/vue-router/-/vue-router-9.0.1.tgz", + "version": "9.0.1-dev.11788212611.154b1596", + "resolved": "https://registry.npmjs.org/@ionic/vue-router/-/vue-router-9.0.1-dev.11788212611.154b1596.tgz", "integrity": "sha512-XbE++/Iepp4P3YbvMH3UX6yTJX/JLlGVOCCmcYWfQCIV7reHpwpbADxSQ/BkSyxu3oTAuaEqplhQAPPZDtFTGA==", "license": "MIT", "dependencies": { - "@ionic/vue": "9.0.1" + "@ionic/vue": "9.0.1-dev.11788212611.154b1596" } }, "node_modules/@jridgewell/gen-mapping": { diff --git a/static/code/stackblitz/v9/vue/package.json b/static/code/stackblitz/v9/vue/package.json index fdd978c5cbb..931a5e3325a 100644 --- a/static/code/stackblitz/v9/vue/package.json +++ b/static/code/stackblitz/v9/vue/package.json @@ -8,8 +8,8 @@ "preview": "vite preview" }, "dependencies": { - "@ionic/vue": "9.0.1", - "@ionic/vue-router": "9.0.1", + "@ionic/vue": "9.0.1-dev.11788212611.154b1596", + "@ionic/vue-router": "9.0.1-dev.11788212611.154b1596", "vue": "^3.2.25", "vue-router": "5.3.0" }, 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 00000000000..92b72024d72 --- /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 00000000000..3e5f8f3d892 --- /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 00000000000..45071ee7432 --- /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 00000000000..1d4e41b58e5 --- /dev/null +++ b/static/usage/v9/modal/styling/sizing-to-content/demo.html @@ -0,0 +1,67 @@ + + + + + + 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 00000000000..2421774fa2c --- /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 00000000000..abbaaaaa6c3 --- /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 00000000000..92b72024d72 --- /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 00000000000..834160ac40d --- /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 00000000000..33dedffb3ad --- /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.md b/versioned_docs/version-v6/api/modal.md index f7fb937e656..dc2b196678e 100644 --- a/versioned_docs/version-v6/api/modal.md +++ b/versioned_docs/version-v6/api/modal.md @@ -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.md'; + + + +### 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.md'; - - - -### 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.md b/versioned_docs/version-v7/api/modal.md index a3e661af9b4..38391cc9237 100644 --- a/versioned_docs/version-v7/api/modal.md +++ b/versioned_docs/version-v7/api/modal.md @@ -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.md'; + + + +### 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.md'; - - - -### 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 8f38444c646..f352f77999c 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`.