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:
Manu MA
2018-12-06 15:36:09 +01:00
committed by GitHub
parent 6776e65c9c
commit 235c6859d2
11 changed files with 215 additions and 42 deletions

View File

@ -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

View File

@ -41,6 +41,9 @@
--width: auto;
--overflow: hidden;
--ripple-color: currentColor;
--border-width: initial;
--border-color: initial;
--border-style: initial;
display: inline-block;

View File

@ -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));
}

View File

@ -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;
}

View File

@ -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};
}
}

View File

@ -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;

View File

@ -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/)*

View File

@ -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>

View 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();
});

View 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>

View File

@ -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();