From aff9b516ac48b3eddbd09c48cd5119d1db6ee81e Mon Sep 17 00:00:00 2001 From: Mike Hartington Date: Wed, 29 Nov 2017 07:33:02 -0800 Subject: [PATCH] feat(ios): add ios 11 layout support (#13473) * feat(): support ios11 layout * style(): update ios11 layout mixins * style(): ios layout updates * style(): adjust tabs vars * refactor(app): add statusbar for md mode and move sass vars adds cordova test for app and renames sass vars to remove cordova * test(app): update app cordova test for button * test(app): add page three --- BREAKING.md | 18 +++ packages/core/src/components.d.ts | 120 +++++++++++++++++ packages/core/src/components/app/app.ios.scss | 16 +++ packages/core/src/components/app/app.md.scss | 16 +++ .../components/app/test/cordova/index.html | 67 ++++++++++ .../components/app/test/cordova/page-one.tsx | 59 +++++++++ .../components/app/test/cordova/page-tabs.tsx | 31 +++++ .../app/test/cordova/page-three.tsx | 39 ++++++ .../components/app/test/cordova/page-two.tsx | 51 ++++++++ .../core/src/components/content/content.tsx | 8 ++ .../components/item-options/item-options.tsx | 9 ++ .../item-sliding/item-sliding.ios.scss | 19 ++- .../core/src/components/item/item.ios.scss | 5 +- .../src/components/item/test/basic/index.html | 6 + packages/core/src/components/menu/menu.scss | 1 + .../src/components/menu/test/basic/index.html | 2 +- .../core/src/components/tabs/tabs.ios.scss | 48 +------ .../src/components/tabs/tabs.ios.vars.scss | 50 +++++++ .../core/src/components/tabs/tabs.md.scss | 107 +-------------- .../src/components/tabs/tabs.md.vars.scss | 106 +++++++++++++++ .../src/components/tabs/test/basic/index.html | 2 +- .../src/components/toolbar/toolbar.ios.scss | 5 +- packages/core/src/global/platform-configs.ts | 2 + packages/core/src/global/platform-utils.ts | 4 + .../core/src/themes/ionic.components.scss | 9 -- packages/core/src/themes/ionic.mixins.scss | 122 ++++++++++++++++-- 26 files changed, 732 insertions(+), 190 deletions(-) create mode 100644 packages/core/src/components/app/test/cordova/index.html create mode 100644 packages/core/src/components/app/test/cordova/page-one.tsx create mode 100644 packages/core/src/components/app/test/cordova/page-tabs.tsx create mode 100644 packages/core/src/components/app/test/cordova/page-three.tsx create mode 100644 packages/core/src/components/app/test/cordova/page-two.tsx create mode 100644 packages/core/src/components/tabs/tabs.ios.vars.scss create mode 100644 packages/core/src/components/tabs/tabs.md.vars.scss create mode 100644 packages/core/src/global/platform-utils.ts diff --git a/BREAKING.md b/BREAKING.md index 6bebd6f64f..e58a8ad932 100644 --- a/BREAKING.md +++ b/BREAKING.md @@ -6,6 +6,7 @@ A list of the breaking changes introduced in Ionic Angular v4. - [Dynamic Mode](#dynamic-mode) - [Button](#button) - [Chip](#chip) +- [Cordova](#cordova) - [Datetime](#datetime) - [FAB](#fab) - [Fixed Content](#fixed-content) @@ -148,6 +149,23 @@ import { DateTime } from 'ionic-angular'; import { Datetime } from 'ionic-angular'; ``` +## Cordova + +Sass variables for changing the cordova statusbar have been renamed to app: + +**Old Usage Example:** + +```css +$cordova-ios-statusbar-padding: 20px; +$cordova-md-statusbar-padding: 20px; +``` + +**New Usage Example:** + +```css +$app-ios-statusbar-padding: 20px; +$app-md-statusbar-padding: 20px; +``` ## FAB diff --git a/packages/core/src/components.d.ts b/packages/core/src/components.d.ts index 1ec5819229..6b2135d62d 100644 --- a/packages/core/src/components.d.ts +++ b/packages/core/src/components.d.ts @@ -242,6 +242,126 @@ declare global { } +import { + AppCordovaPageOne as AppCordovaPageOne +} from './components/app/test/cordova/page-one'; + +declare global { + interface HTMLAppCordovaPageOneElement extends AppCordovaPageOne, HTMLElement { + } + var HTMLAppCordovaPageOneElement: { + prototype: HTMLAppCordovaPageOneElement; + new (): HTMLAppCordovaPageOneElement; + }; + interface HTMLElementTagNameMap { + "app-cordova-page-one": HTMLAppCordovaPageOneElement; + } + interface ElementTagNameMap { + "app-cordova-page-one": HTMLAppCordovaPageOneElement; + } + namespace JSX { + interface IntrinsicElements { + "app-cordova-page-one": JSXElements.AppCordovaPageOneAttributes; + } + } + namespace JSXElements { + export interface AppCordovaPageOneAttributes extends HTMLAttributes { + + } + } +} + + +import { + AppCordovaPageTabs as AppCordovaPageTabs +} from './components/app/test/cordova/page-tabs'; + +declare global { + interface HTMLAppCordovaPageTabsElement extends AppCordovaPageTabs, HTMLElement { + } + var HTMLAppCordovaPageTabsElement: { + prototype: HTMLAppCordovaPageTabsElement; + new (): HTMLAppCordovaPageTabsElement; + }; + interface HTMLElementTagNameMap { + "app-cordova-page-tabs": HTMLAppCordovaPageTabsElement; + } + interface ElementTagNameMap { + "app-cordova-page-tabs": HTMLAppCordovaPageTabsElement; + } + namespace JSX { + interface IntrinsicElements { + "app-cordova-page-tabs": JSXElements.AppCordovaPageTabsAttributes; + } + } + namespace JSXElements { + export interface AppCordovaPageTabsAttributes extends HTMLAttributes { + + } + } +} + + +import { + AppCordovaPageThree as AppCordovaPageThree +} from './components/app/test/cordova/page-three'; + +declare global { + interface HTMLAppCordovaPageThreeElement extends AppCordovaPageThree, HTMLElement { + } + var HTMLAppCordovaPageThreeElement: { + prototype: HTMLAppCordovaPageThreeElement; + new (): HTMLAppCordovaPageThreeElement; + }; + interface HTMLElementTagNameMap { + "app-cordova-page-three": HTMLAppCordovaPageThreeElement; + } + interface ElementTagNameMap { + "app-cordova-page-three": HTMLAppCordovaPageThreeElement; + } + namespace JSX { + interface IntrinsicElements { + "app-cordova-page-three": JSXElements.AppCordovaPageThreeAttributes; + } + } + namespace JSXElements { + export interface AppCordovaPageThreeAttributes extends HTMLAttributes { + + } + } +} + + +import { + AppCordovaPageTwo as AppCordovaPageTwo +} from './components/app/test/cordova/page-two'; + +declare global { + interface HTMLAppCordovaPageTwoElement extends AppCordovaPageTwo, HTMLElement { + } + var HTMLAppCordovaPageTwoElement: { + prototype: HTMLAppCordovaPageTwoElement; + new (): HTMLAppCordovaPageTwoElement; + }; + interface HTMLElementTagNameMap { + "app-cordova-page-two": HTMLAppCordovaPageTwoElement; + } + interface ElementTagNameMap { + "app-cordova-page-two": HTMLAppCordovaPageTwoElement; + } + namespace JSX { + interface IntrinsicElements { + "app-cordova-page-two": JSXElements.AppCordovaPageTwoAttributes; + } + } + namespace JSXElements { + export interface AppCordovaPageTwoAttributes extends HTMLAttributes { + + } + } +} + + import { Avatar as IonAvatar } from './components/avatar/avatar'; diff --git a/packages/core/src/components/app/app.ios.scss b/packages/core/src/components/app/app.ios.scss index 2f29aaf2ed..dc659ae835 100644 --- a/packages/core/src/components/app/app.ios.scss +++ b/packages/core/src/components/app/app.ios.scss @@ -1,14 +1,30 @@ @import "../../themes/ionic.globals.ios"; @import "./app"; +@import "../tabs/tabs.ios.vars"; // iOS App // -------------------------------------------------- +$app-ios-statusbar-padding: 20px !default; + .app-ios { + + @include footer-safe-area($toolbar-ios-height, $toolbar-ios-padding, $tabs-ios-tab-height); + font-family: $font-family-ios-base; font-size: $font-size-ios-base; background-color: $background-ios-color; + + // TODO this can be simplified + .ion-page, + .ion-page > ion-header, + ion-tabs ion-tab ion-nav .ion-page > ion-header, + ion-menu > .menu-inner, + ion-menu > .menu-inner > ion-header { + @include toolbar-statusbar-padding($toolbar-ios-height, $toolbar-ios-padding, $content-ios-padding, $app-ios-statusbar-padding); + @include toolbar-title-statusbar-padding($toolbar-ios-height, $toolbar-ios-padding, $content-ios-padding, $app-ios-statusbar-padding); + } } @import "../icon/icon.ios"; diff --git a/packages/core/src/components/app/app.md.scss b/packages/core/src/components/app/app.md.scss index 497c4c616f..2c12cc1944 100644 --- a/packages/core/src/components/app/app.md.scss +++ b/packages/core/src/components/app/app.md.scss @@ -1,14 +1,30 @@ @import "../../themes/ionic.globals.md"; @import "./app"; +@import "../tabs/tabs.md.vars"; + // Material Design App // -------------------------------------------------- +$app-md-statusbar-padding: 20px !default; + .app-md { + + @include footer-safe-area($toolbar-md-height, $toolbar-md-padding, $tabs-md-tab-height); + font-family: $font-family-md-base; font-size: $font-size-md-base; background-color: $background-md-color; + + // TODO this can be simplified + .ion-page, + .ion-page > ion-header, + ion-tabs ion-tab ion-nav .ion-page > ion-header, + ion-menu > .menu-inner, + ion-menu > .menu-inner > ion-header { + @include toolbar-statusbar-padding($toolbar-md-height, $toolbar-md-padding, $content-md-padding, $app-md-statusbar-padding); + } } @import "../icon/icon.md"; diff --git a/packages/core/src/components/app/test/cordova/index.html b/packages/core/src/components/app/test/cordova/index.html new file mode 100644 index 0000000000..d20e759043 --- /dev/null +++ b/packages/core/src/components/app/test/cordova/index.html @@ -0,0 +1,67 @@ + + + + + App - Cordova + + + + + + + + + + + + Left Menu + + + + + + + + Settings + + + + Close Menu + + + + + + + + + + + + + + No toolbar + + + + Close Menu + + + + + + + + + + + + + + + + diff --git a/packages/core/src/components/app/test/cordova/page-one.tsx b/packages/core/src/components/app/test/cordova/page-one.tsx new file mode 100644 index 0000000000..49aa9bb7db --- /dev/null +++ b/packages/core/src/components/app/test/cordova/page-one.tsx @@ -0,0 +1,59 @@ +import { Component, Element } from '@stencil/core'; + +@Component({ + tag: 'app-cordova-page-one' +}) +export class AppCordovaPageOne { + + @Element() element: HTMLElement; + + componentDidEnter() { + console.log('page one did enter'); + } + + nextPage() { + const nav = this.element.closest('ion-nav') as any; + nav.push('app-cordova-page-two'); + } + + goToTabs() { + const nav = this.element.closest('ion-nav') as any; + nav.setRoot('app-cordova-page-tabs'); + } + + render() { + return [ + + + + + + + All + Favorites + + + + + + + + I'm a toolbar + + , + +
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi scelerisque dolor lacus, ut vehicula arcu dapibus id. Morbi iaculis fermentum blandit. Curabitur tempus, ante et vehicula tempor, urna velit rutrum massa, quis suscipit purus lacus eget est. Sed nisi nulla, tempus id dictum a, cursus ut felis. Aliquam orci magna, rutrum nec tempor ac, fermentum quis eros. Sed ullamcorper felis sit amet tristique sagittis. Nullam sed tempus mi. Morbi sit amet lacinia leo. Nunc facilisis orci id consectetur dignissim. Integer dictum consectetur enim. Vivamus auctor, turpis ut eleifend pharetra, purus magna mattis arcu, vel pharetra tellus orci eget ex. Integer blandit posuere vehicula. Ut ipsum lorem, efficitur vitae eleifend tincidunt, fermentum nec lacus. Ut nec fermentum dui.
+ + this.nextPage()} expand='block' class='e2eCordovaPage2'>Go to Page Two + this.goToTabs()} color='secondary' expand='block' class='e2eCordovaPage2'>Go to Tabs + +
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi scelerisque dolor lacus, ut vehicula arcu dapibus id. Morbi iaculis fermentum blandit. Curabitur tempus, ante et vehicula tempor, urna velit rutrum massa, quis suscipit purus lacus eget est. Sed nisi nulla, tempus id dictum a, cursus ut felis. Aliquam orci magna, rutrum nec tempor ac, fermentum quis eros. Sed ullamcorper felis sit amet tristique sagittis. Nullam sed tempus mi. Morbi sit amet lacinia leo. Nunc facilisis orci id consectetur dignissim. Integer dictum consectetur enim. Vivamus auctor, turpis ut eleifend pharetra, purus magna mattis arcu, vel pharetra tellus orci eget ex. Integer blandit posuere vehicula. Ut ipsum lorem, efficitur vitae eleifend tincidunt, fermentum nec lacus. Ut nec fermentum dui.
+ +
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi scelerisque dolor lacus, ut vehicula arcu dapibus id. Morbi iaculis fermentum blandit. Curabitur tempus, ante et vehicula tempor, urna velit rutrum massa, quis suscipit purus lacus eget est. Sed nisi nulla, tempus id dictum a, cursus ut felis. Aliquam orci magna, rutrum nec tempor ac, fermentum quis eros. Sed ullamcorper felis sit amet tristique sagittis. Nullam sed tempus mi. Morbi sit amet lacinia leo. Nunc facilisis orci id consectetur dignissim. Integer dictum consectetur enim. Vivamus auctor, turpis ut eleifend pharetra, purus magna mattis arcu, vel pharetra tellus orci eget ex. Integer blandit posuere vehicula. Ut ipsum lorem, efficitur vitae eleifend tincidunt, fermentum nec lacus. Ut nec fermentum dui.
+ +
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi scelerisque dolor lacus, ut vehicula arcu dapibus id. Morbi iaculis fermentum blandit. Curabitur tempus, ante et vehicula tempor, urna velit rutrum massa, quis suscipit purus lacus eget est. Sed nisi nulla, tempus id dictum a, cursus ut felis. Aliquam orci magna, rutrum nec tempor ac, fermentum quis eros. Sed ullamcorper felis sit amet tristique sagittis. Nullam sed tempus mi. Morbi sit amet lacinia leo. Nunc facilisis orci id consectetur dignissim. Integer dictum consectetur enim. Vivamus auctor, turpis ut eleifend pharetra, purus magna mattis arcu, vel pharetra tellus orci eget ex. Integer blandit posuere vehicula. Ut ipsum lorem, efficitur vitae eleifend tincidunt, fermentum nec lacus. Ut nec fermentum dui.
+ +
+ ]; + } +} diff --git a/packages/core/src/components/app/test/cordova/page-tabs.tsx b/packages/core/src/components/app/test/cordova/page-tabs.tsx new file mode 100644 index 0000000000..76eba584f0 --- /dev/null +++ b/packages/core/src/components/app/test/cordova/page-tabs.tsx @@ -0,0 +1,31 @@ +import { Component, Element } from '@stencil/core'; + +@Component({ + tag: 'app-cordova-page-tabs' +}) +export class AppCordovaPageTabs { + + @Element() element: HTMLElement; + + componentDidEnter() { + console.log('page two did enter'); + } + + render() { + return [ + + + + + + + + + + + + + + ]; + } +} diff --git a/packages/core/src/components/app/test/cordova/page-three.tsx b/packages/core/src/components/app/test/cordova/page-three.tsx new file mode 100644 index 0000000000..833a3beb7e --- /dev/null +++ b/packages/core/src/components/app/test/cordova/page-three.tsx @@ -0,0 +1,39 @@ +import { Component, Element } from '@stencil/core'; + +@Component({ + tag: 'app-cordova-page-three' +}) +export class AppCordovaPageThree { + + @Element() element: HTMLElement; + + componentDidEnter() { + console.log('page one did enter'); + } + + nextPage() { + const nav = this.element.closest('ion-nav') as any; + nav.push('app-cordova-page-one'); + } + + prevPage() { + const nav = this.element.closest('ion-nav') as any; + nav.push('app-cordova-page-two'); + } + + render() { + return [ + +

Page 3

+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi scelerisque dolor lacus, ut vehicula arcu dapibus id. Morbi iaculis fermentum blandit. Curabitur tempus, ante et vehicula tempor, urna velit rutrum massa, quis suscipit purus lacus eget est. Sed nisi nulla, tempus id dictum a, cursus ut felis. Aliquam orci magna, rutrum nec tempor ac, fermentum quis eros. Sed ullamcorper felis sit amet tristique sagittis. Nullam sed tempus mi. Morbi sit amet lacinia leo. Nunc facilisis orci id consectetur dignissim. Integer dictum consectetur enim. Vivamus auctor, turpis ut eleifend pharetra, purus magna mattis arcu, vel pharetra tellus orci eget ex. Integer blandit posuere vehicula. Ut ipsum lorem, efficitur vitae eleifend tincidunt, fermentum nec lacus. Ut nec fermentum dui.
+ this.prevPage()} expand='block' class='e2eCordovaGoBack'>Go Back +
, + + + + I'm a bottom toolbar + + + ]; + } +} diff --git a/packages/core/src/components/app/test/cordova/page-two.tsx b/packages/core/src/components/app/test/cordova/page-two.tsx new file mode 100644 index 0000000000..b710076155 --- /dev/null +++ b/packages/core/src/components/app/test/cordova/page-two.tsx @@ -0,0 +1,51 @@ +import { Component, Element } from '@stencil/core'; + +@Component({ + tag: 'app-cordova-page-two' +}) +export class AppCordovaPageTwo { + + @Element() element: HTMLElement; + + componentDidEnter() { + console.log('page two did enter'); + } + + prevPage() { + const nav = this.element.closest('ion-nav') as any; + nav.push('app-cordova-page-one'); + } + + nextPage() { + const nav = this.element.closest('ion-nav') as any; + nav.push('app-cordova-page-three'); + } + + openModal() { + + } + + render() { + return [ + + + Page Two + + + + + + Hello I am a sub header, with no border on top + + , + +
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi scelerisque dolor lacus, ut vehicula arcu dapibus id. Morbi iaculis fermentum blandit. Curabitur tempus, ante et vehicula tempor, urna velit rutrum massa, quis suscipit purus lacus eget est. Sed nisi nulla, tempus id dictum a, cursus ut felis. Aliquam orci magna, rutrum nec tempor ac, fermentum quis eros. Sed ullamcorper felis sit amet tristique sagittis. Nullam sed tempus mi. Morbi sit amet lacinia leo. Nunc facilisis orci id consectetur dignissim. Integer dictum consectetur enim. Vivamus auctor, turpis ut eleifend pharetra, purus magna mattis arcu, vel pharetra tellus orci eget ex. Integer blandit posuere vehicula. Ut ipsum lorem, efficitur vitae eleifend tincidunt, fermentum nec lacus. Ut nec fermentum dui.
+ + this.prevPage()}>Go to Page One + this.nextPage()} class='e2eCordovaPage3'>Go to Page Three + this.openModal()} class='e2eCordovaOpenModal'>Open Modal + +
+ ]; + } +} diff --git a/packages/core/src/components/content/content.tsx b/packages/core/src/components/content/content.tsx index 1440f15209..f73cff0f37 100644 --- a/packages/core/src/components/content/content.tsx +++ b/packages/core/src/components/content/content.tsx @@ -60,6 +60,14 @@ export class Content { this.scrollEl = null; } + hostData() { + return { + class: { + 'statusbar-padding': this.config.getBoolean('statusbarPadding') + } + }; + } + @Method() enableJsScroll() { this.scrollEl.jsScroll = true; diff --git a/packages/core/src/components/item-options/item-options.tsx b/packages/core/src/components/item-options/item-options.tsx index 4f27596ccc..763698324f 100644 --- a/packages/core/src/components/item-options/item-options.tsx +++ b/packages/core/src/components/item-options/item-options.tsx @@ -34,6 +34,15 @@ export class ItemOptions { this.ionSwipe.emit(value); } + hostData(){ + return { + class:{ + 'item-options-left': !this.isRightSide(), + 'item-options-right': this.isRightSide() + } + } + } + render() { return ; } diff --git a/packages/core/src/components/item-sliding/item-sliding.ios.scss b/packages/core/src/components/item-sliding/item-sliding.ios.scss index 6456f40cf2..68eff0f6ee 100644 --- a/packages/core/src/components/item-sliding/item-sliding.ios.scss +++ b/packages/core/src/components/item-sliding/item-sliding.ios.scss @@ -27,18 +27,17 @@ $item-ios-sliding-button-icon-color: color-contrast($colors-ios, $item-i .list-ios ion-item-options { border-bottom: $hairlines-width solid $list-ios-border-color; - - ion-item-option:last-child, - &[side="right"] ion-item-option:last-child { - @include safe-area-padding-horizontal(null, .7em); - } - - &[side="left"] ion-item-option:first-child { - @include safe-area-padding-horizontal(.7em, null); - } - } +.list-ios .item-options-right ion-item-option:last-child { + @include safe-area-padding-horizontal(null, .7em); +} + +.list-ios .item-options-left ion-item-option:first-child { + @include safe-area-padding-horizontal(.7em, null); +} + + .item-option-ios { font-size: $item-ios-sliding-button-font-size; color: $item-ios-sliding-button-text-color; diff --git a/packages/core/src/components/item/item.ios.scss b/packages/core/src/components/item/item.ios.scss index f4dcc2d727..7ef94e0c91 100644 --- a/packages/core/src/components/item/item.ios.scss +++ b/packages/core/src/components/item/item.ios.scss @@ -113,7 +113,10 @@ $item-ios-detail-push-svg: " isPlatformMatch(url, userAgent, IOS, [IPHONE, IPAD, 'ipod'], WINDOWS_PHONE) }, diff --git a/packages/core/src/global/platform-utils.ts b/packages/core/src/global/platform-utils.ts new file mode 100644 index 0000000000..a4e681ea3a --- /dev/null +++ b/packages/core/src/global/platform-utils.ts @@ -0,0 +1,4 @@ + +export function isCordova(): boolean { + return !!(window['cordova'] || window['PhoneGap'] || window['phonegap']); +} diff --git a/packages/core/src/themes/ionic.components.scss b/packages/core/src/themes/ionic.components.scss index b8623a0745..97875e6dea 100644 --- a/packages/core/src/themes/ionic.components.scss +++ b/packages/core/src/themes/ionic.components.scss @@ -199,15 +199,6 @@ @import "../components/virtual-scroll/virtual-scroll"; - -// Platforms -// -------------------------------------------------- -@import -"../platform/cordova", -"../platform/cordova.ios", -"../platform/cordova.md"; - - // Fonts // -------------------------------------------------- @import diff --git a/packages/core/src/themes/ionic.mixins.scss b/packages/core/src/themes/ionic.mixins.scss index 06fc03d5be..cfee41e838 100644 --- a/packages/core/src/themes/ionic.mixins.scss +++ b/packages/core/src/themes/ionic.mixins.scss @@ -549,9 +549,15 @@ // @param {string} $start // ---------------------------------------------------------- @mixin safe-area-padding($top, $end: $top, $bottom: $top, $start: $end) { + // two groups for older constant and newer env + $safe-area-top: null; $safe-area-start: null; + $safe-area-bottom: null; $safe-area-end: null; + + $safe-area-top-env: null; $safe-area-start-env: null; + $safe-area-bottom-env: null; $safe-area-end-env: null; @if ($start) { @@ -559,18 +565,22 @@ $safe-area-start-env: calc(env(safe-area-inset-left) + #{$start}); } @if ($end) { - $safe-area-end-env: calc(constant(safe-area-inset-right) + #{$end}); + $safe-area-end: calc(constant(safe-area-inset-right) + #{$end}); $safe-area-end-env: calc(env(safe-area-inset-right) + #{$end}); } - - @include padding($top, $end, $bottom, $start); - - @media screen and (orientation: landscape) { - @include padding($top, $safe-area-end, $bottom, $safe-area-start); - @include padding($top, $safe-area-end-env, $bottom, $safe-area-start-env); + @if ($top){ + $safe-area-top: calc(constant(safe-area-inset-top) + #{$top}); + $safe-area-top-env: calc(env(safe-area-inset-top) + #{$top}); + } + @if ($bottom){ + $safe-area-bottom: calc(constant(safe-area-inset-bottom) + #{$bottom}); + $safe-area-bottom-env: calc(env(safe-area-inset-bottom) + #{$bottom}); } -} + @include padding($safe-area-top, $safe-area-end, $safe-area-bottom, $safe-area-start); + @include padding($safe-area-top-env, $safe-area-end-env, $safe-area-bottom-env, $safe-area-start-env); + +} // Add safe area padding horizontal // @param {string} $start @@ -591,12 +601,8 @@ $safe-area-start-env: calc(env(safe-area-inset-left) + #{$start}); } - @include padding-horizontal($start, $end); - - @media screen and (orientation: landscape) { - @include padding-horizontal($safe-area-start, $safe-area-end); - @include padding-horizontal($safe-area-start-env, $safe-area-end-env); - } + @include padding-horizontal($safe-area-start, $safe-area-end); + @include padding-horizontal($safe-area-start-env, $safe-area-end-env); } @@ -647,3 +653,91 @@ } } + +// Add generic safe area sizing +// @param {string} $prop - css property you want to set +// @param {string} $safe-area-position - short safe-area-inset value you want to modify +// @param {string} $value - additional value you want to modify, if none, pass 0px +// ---------------------------------------------------------- +@mixin safe-area-sizing($prop, $safe-area-position, $value){ + #{$prop}: calc(#{$value} + constant(#{$safe-area-position})); + #{$prop}: calc(#{$value} + env(#{$safe-area-position})); +} + + +// Add safe area padding and sizing to the footer area +// @param {string} $toolbar-height - height of the toolbar +// @param {string} $toolbar-padding - padding of the toolbar +// @param {string} $tabs-height - height of the tabs +// ---------------------------------------------------------- +@mixin footer-safe-area($toolbar-height, $toolbar-padding, $tabs-height) { + ion-tabs ion-tabbar:not(.placement-top) { + @include safe-area-padding(null, null, 0px, null); + @include safe-area-sizing(height, safe-area-inset-bottom, $tabs-height) + } + + ion-footer .toolbar:last-child { + @include safe-area-padding(null, null, $toolbar-padding, null); + @include safe-area-sizing(min-height, safe-area-inset-bottom, $toolbar-height) + } +} + + +// Add padding to the toolbar to account for the statusbar +// @param {string} $toolbar-height - height of the toolbar +// @param {string} $toolbar-padding - padding of the toolbar +// @param {string} $content-padding - padding of the content +// @param {string} $statusbar-padding - padding of the statusbar +// -------------------------------------------------------------------------------- +@mixin toolbar-statusbar-padding($toolbar-height, $toolbar-padding, $content-padding, $statusbar-padding) { + + > .toolbar.statusbar-padding:first-child { + @include padding(calc(#{$statusbar-padding} + #{$toolbar-padding}), null, null, null); + @include safe-area-padding($toolbar-padding, null, null, null); + + min-height: calc(#{$toolbar-height} + #{$statusbar-padding}); + @include safe-area-sizing(min-height, safe-area-inset-top, $toolbar-height); + } + + > ion-content.statusbar-padding:first-child .scroll-content { + @include padding($statusbar-padding, null, null, null); + @include safe-area-padding(0px, null, null, null); + } + + > ion-content.statusbar-padding:first-child[padding] .scroll-content, + > ion-content.statusbar-padding:first-child[padding-top] .scroll-content { + @include padding(calc(#{$content-padding} + #{$statusbar-padding}), null, null, null); + @include safe-area-padding(0px, null, null, null); + } + +} + + +// Add padding to the toolbar to account for the statusbar +// @param {string} $toolbar-height - height of the toolbar +// @param {string} $toolbar-padding - padding of the toolbar +// @param {string} $content-padding - padding of the content +// @param {string} $statusbar-padding - padding of the statusbar +// +// iOS is the only mode that uses this mixin and it should be removed with #5036 +// -------------------------------------------------------------------------------- +@mixin toolbar-title-statusbar-padding($toolbar-height, $toolbar-padding, $content-padding, $statusbar-padding) { + + > .toolbar.statusbar-padding:first-child ion-segment, + > .toolbar.statusbar-padding:first-child ion-title { + @include padding($statusbar-padding, null, null, null); + @include safe-area-padding(0px, null, null, null); + + height: calc(#{$toolbar-height} + #{$statusbar-padding}); + @include safe-area-sizing(height, safe-area-inset-top, $toolbar-height) + + min-height: calc(#{$toolbar-height} + #{$statusbar-padding}); + @include safe-area-sizing(min-height, safe-area-inset-top, $toolbar-height) + } + + > ion-content.statusbar-padding:first-child ion-scroll { + @include padding($statusbar-padding, null, null, null); + @include safe-area-padding(0px, null, null, null); + } + +}