mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-18 11:17:19 +08:00
feat(modal): add css vars (#16605)
* feat(modal): add css vars * add more css vars * add docs * add background * fix e2e test
This commit is contained in:
@ -636,6 +636,13 @@ ion-modal,event,ionModalDidPresent,void,true
|
||||
ion-modal,event,ionModalDidUnload,void,true
|
||||
ion-modal,event,ionModalWillDismiss,OverlayEventDetail,true
|
||||
ion-modal,event,ionModalWillPresent,void,true
|
||||
ion-modal,css-prop,--background
|
||||
ion-modal,css-prop,--border-color
|
||||
ion-modal,css-prop,--border-radius
|
||||
ion-modal,css-prop,--border-style
|
||||
ion-modal,css-prop,--border-width
|
||||
ion-modal,css-prop,--height
|
||||
ion-modal,css-prop,--width
|
||||
|
||||
ion-nav-pop
|
||||
|
||||
|
@ -41,6 +41,9 @@
|
||||
--width: auto;
|
||||
--overflow: hidden;
|
||||
--ripple-color: currentColor;
|
||||
--border-width: initial;
|
||||
--border-color: initial;
|
||||
--border-style: initial;
|
||||
|
||||
display: inline-block;
|
||||
|
||||
|
@ -4,14 +4,13 @@
|
||||
// iOS Modals
|
||||
// --------------------------------------------------
|
||||
|
||||
.modal-wrapper-ios {
|
||||
// hidden by default to prevent flickers, the animation will show it
|
||||
|
||||
@include transform(translate3d(0, 100%, 0));
|
||||
|
||||
@media only screen and (min-width: $modal-inset-min-width) and (min-height: $modal-inset-min-height-small) {
|
||||
@include border-radius($modal-ios-border-radius);
|
||||
|
||||
overflow: hidden;
|
||||
@media only screen and (min-width: $modal-inset-min-width) and (min-height: $modal-inset-min-height-small) {
|
||||
:host {
|
||||
--border-radius: #{$modal-ios-border-radius};
|
||||
}
|
||||
}
|
||||
|
||||
.modal-wrapper {
|
||||
// hidden by default to prevent flickers, the animation will show it
|
||||
@include transform(translate3d(0, 100%, 0));
|
||||
}
|
||||
|
@ -5,16 +5,15 @@
|
||||
// Material Design Modals
|
||||
// --------------------------------------------------
|
||||
|
||||
.modal-wrapper-md {
|
||||
@media only screen and (min-width: $modal-inset-min-width) and (min-height: $modal-inset-min-height-small) {
|
||||
:host {
|
||||
--border-radius: 2px;
|
||||
--box-shadow: #{$modal-inset-box-shadow};
|
||||
}
|
||||
}
|
||||
|
||||
.modal-wrapper {
|
||||
@include transform(translate3d(0, 40px, 0));
|
||||
|
||||
@media only screen and (min-width: $modal-inset-min-width) and (min-height: $modal-inset-min-height-small) {
|
||||
@include border-radius(2px);
|
||||
|
||||
box-shadow: $modal-inset-box-shadow;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
opacity: .01;
|
||||
|
||||
}
|
||||
|
@ -3,7 +3,25 @@
|
||||
// Modals
|
||||
// --------------------------------------------------
|
||||
|
||||
ion-modal {
|
||||
:host {
|
||||
/**
|
||||
* @prop --background: Background of the modal content
|
||||
* @prop --border-color: Border color of the modal content
|
||||
* @prop --border-radius: Border radius of the modal content
|
||||
* @prop --border-width: Border width of the modal content
|
||||
* @prop --border-style: Border style of the modal content
|
||||
* @prop --height: Height of the modal content
|
||||
* @prop --width: Width of the modal content
|
||||
*/
|
||||
--width: 100%;
|
||||
--height: 100%;
|
||||
--overflow: hidden;
|
||||
--border-radius: 0;
|
||||
--border-width: 0;
|
||||
--border-style: none;
|
||||
--border-color: transparent;
|
||||
--background: #{$background-color};
|
||||
|
||||
@include position(0, 0, 0, 0);
|
||||
|
||||
display: flex;
|
||||
@ -15,32 +33,36 @@ ion-modal {
|
||||
contain: strict;
|
||||
}
|
||||
|
||||
ion-modal-controller {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
@media not all and (min-width: $modal-inset-min-width) and (min-height: $modal-inset-min-height-small) {
|
||||
ion-modal ion-backdrop {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.modal-wrapper {
|
||||
@media only screen and (min-width: $modal-inset-min-width) and (min-height: $modal-inset-min-height-small) {
|
||||
width: $modal-inset-width;
|
||||
height: $modal-inset-height-small;
|
||||
}
|
||||
@include border-radius(var(--border-radius));
|
||||
|
||||
@media only screen and (min-width: $modal-inset-min-width) and (min-height: $modal-inset-min-height-large) {
|
||||
width: $modal-inset-width;
|
||||
height: $modal-inset-height-large;
|
||||
}
|
||||
width: var(--width);
|
||||
height: var(--height);
|
||||
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-width: var(--border-width);
|
||||
border-style: var(--border-style);
|
||||
border-color: var(--border-color);
|
||||
|
||||
contain: strict;
|
||||
background: var(--background);
|
||||
|
||||
overflow: var(--overflow);
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
@media only screen and (min-width: $modal-inset-min-width) and (min-height: $modal-inset-min-height-small) {
|
||||
:host {
|
||||
--width: #{$modal-inset-width};
|
||||
--height: #{$modal-inset-height-small};
|
||||
--ion-safe-area-top: 0px;
|
||||
--ion-safe-area-bottom: 0px;
|
||||
--ion-safe-area-right: 0px;
|
||||
--ion-safe-area-left: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width: $modal-inset-min-width) and (min-height: $modal-inset-min-height-large) {
|
||||
:host {
|
||||
--width: #{$modal-inset-width};
|
||||
--height: #{$modal-inset-height-large};
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,8 @@ import { mdLeaveAnimation } from './animations/md.leave';
|
||||
styleUrls: {
|
||||
ios: 'modal.ios.scss',
|
||||
md: 'modal.md.scss'
|
||||
}
|
||||
},
|
||||
scoped: true
|
||||
})
|
||||
export class Modal implements ComponentInterface, OverlayInterface {
|
||||
|
||||
@ -29,6 +30,7 @@ export class Modal implements ComponentInterface, OverlayInterface {
|
||||
|
||||
@Prop({ connect: 'ion-animation-controller' }) animationCtrl!: HTMLIonAnimationControllerElement;
|
||||
@Prop({ context: 'config' }) config!: Config;
|
||||
|
||||
/** @internal */
|
||||
@Prop() overlayIndex!: number;
|
||||
|
||||
|
@ -156,6 +156,19 @@ Type: `Promise<void>`
|
||||
|
||||
|
||||
|
||||
## CSS Custom Properties
|
||||
|
||||
| Name | Description |
|
||||
| ----------------- | ---------------------------------- |
|
||||
| `--background` | Background of the modal content |
|
||||
| `--border-color` | Border color of the modal content |
|
||||
| `--border-radius` | Border radius of the modal content |
|
||||
| `--border-style` | Border style of the modal content |
|
||||
| `--border-width` | Border width of the modal content |
|
||||
| `--height` | Height of the modal content |
|
||||
| `--width` | Width of the modal content |
|
||||
|
||||
|
||||
----------------------------------------------
|
||||
|
||||
*Built with [StencilJS](https://stenciljs.com/)*
|
||||
|
@ -8,6 +8,15 @@
|
||||
<link href="../../../../../css/ionic.bundle.css" rel="stylesheet">
|
||||
<link href="../../../../../scripts/testing/styles.css" rel="stylesheet">
|
||||
<script src="../../../../../dist/ionic.js"></script>
|
||||
|
||||
<style>
|
||||
:root {
|
||||
--ion-safe-area-top: 20px;
|
||||
--ion-safe-area-bottom: 20px;
|
||||
--ion-safe-area-right: 20px;
|
||||
--ion-safe-area-left: 20px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
16
core/src/components/modal/test/custom/e2e.ts
Normal file
16
core/src/components/modal/test/custom/e2e.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import { newE2EPage } from '@stencil/core/testing';
|
||||
|
||||
test('modal: custom', async () => {
|
||||
const page = await newE2EPage({
|
||||
url: '/src/components/modal/test/custom?ionic:_testing=true'
|
||||
});
|
||||
|
||||
await page.click('.e2ePresentModal');
|
||||
|
||||
const modal = await page.find('ion-modal');
|
||||
await modal.waitForVisible();
|
||||
await page.waitFor(250);
|
||||
|
||||
const compare = await page.compareScreenshot();
|
||||
expect(compare).toMatchScreenshot();
|
||||
});
|
98
core/src/components/modal/test/custom/index.html
Normal file
98
core/src/components/modal/test/custom/index.html
Normal file
@ -0,0 +1,98 @@
|
||||
<!DOCTYPE html>
|
||||
<html dir="ltr">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Modal - Basic</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
||||
<link href="../../../../../css/ionic.bundle.css" rel="stylesheet">
|
||||
<link href="../../../../../scripts/testing/styles.css" rel="stylesheet">
|
||||
<script src="../../../../../dist/ionic.js"></script>
|
||||
|
||||
<style>
|
||||
.custom-modal {
|
||||
--height: 70%;
|
||||
--border-style: solid;
|
||||
--border-width: 7px 0 0 0;
|
||||
--border-color: #0d51aa;
|
||||
--border-radius: 20px 20px 0 0;
|
||||
align-items: flex-end;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<ion-app>
|
||||
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>Modal - Basic</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<ion-content padding>
|
||||
<p>
|
||||
<ion-button id="presentModal" class="e2ePresentModal" onclick="presentModal()">Present modal</ion-button>
|
||||
</p>
|
||||
</ion-content>
|
||||
<ion-modal-controller></ion-modal-controller>
|
||||
|
||||
</ion-app>
|
||||
|
||||
<script>
|
||||
|
||||
async function createModal() {
|
||||
// initialize controller
|
||||
const modalController = document.querySelector('ion-modal-controller');
|
||||
await modalController.componentOnReady();
|
||||
|
||||
// create component to open
|
||||
const element = document.createElement('div');
|
||||
element.innerHTML = `
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>Super Modal</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content>
|
||||
<h1>Content of doom</h1>
|
||||
<div>Here's some more content</div>
|
||||
<ion-button class="dismiss">Dismiss Modal</ion-button>
|
||||
</ion-content>
|
||||
`;
|
||||
|
||||
// listen for close event
|
||||
const button = element.querySelector('ion-button');
|
||||
button.addEventListener('click', () => {
|
||||
modalController.dismiss();
|
||||
});
|
||||
|
||||
// present the modal
|
||||
const modalElement = await modalController.create({
|
||||
component: element,
|
||||
cssClass: 'custom-modal',
|
||||
});
|
||||
return modalElement;
|
||||
}
|
||||
|
||||
async function presentModal() {
|
||||
const modal = await createModal();
|
||||
await modal.present();
|
||||
}
|
||||
async function presentCloseModal() {
|
||||
const modal = await createModal();
|
||||
await modal.present();
|
||||
await modal.dismiss();
|
||||
}
|
||||
|
||||
async function presentCloseModal2() {
|
||||
const modal = await createModal();
|
||||
modal.present();
|
||||
setTimeout(() => {
|
||||
modal.dismiss();
|
||||
}, 20);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
@ -30,6 +30,11 @@
|
||||
</style>
|
||||
|
||||
<script>
|
||||
customElements.define('page-one', class extends HTMLElement {
|
||||
connectedCallback() {
|
||||
this.textContent = 'this is a modal';
|
||||
}
|
||||
});
|
||||
async function presentModal() {
|
||||
const modalController = document.querySelector('ion-modal-controller');
|
||||
await modalController.componentOnReady();
|
||||
|
Reference in New Issue
Block a user