From 112d4f5490d3e962b34a7900a537f9d7b6d73763 Mon Sep 17 00:00:00 2001 From: Mike Hartington Date: Tue, 26 Sep 2017 13:27:34 -0400 Subject: [PATCH] feat(): initial iphoneX support * feat(cordova): add ios11 safeAreaInsets support * feat(cordova): ios11 padding mixin * chore(dependencies): go to angular 4.1.3 * chore(build): temporarily disable git pull and status from master as part of build * fix(sass): add a mixin for the safe-area-padding * style(sass): fix sass lint errors * style(): tabs, footer, content changes * fix(): lint * style(sass): fix sass linter error * refactor(footer): use safe area for all modes * fix(tabs): increase font-weight of tabs for iOS 11 * style(): fix content padding and sizing * style(sass): fix linter and remove unused vars * style(): actionsheet, toast, header updates * fix(): sass lint * chore(): backout release changes * chore(): update to lastest master --- scripts/gulp/tasks/release.ts | 1 + .../action-sheet/action-sheet.ios.scss | 4 + src/components/content/content.scss | 54 ++++++--- src/components/content/content.ts | 3 +- src/components/item/item.ios.scss | 4 +- src/components/picker/picker.scss | 1 + src/components/tabs/tabs.ios.scss | 4 + src/components/toast/toast.ios.scss | 2 + src/platform/cordova.ios.scss | 6 +- src/platform/cordova.md.scss | 2 + src/platform/cordova.scss | 29 ++++- src/platform/cordova.wp.scss | 2 + src/themes/ionic.mixins.scss | 108 ++++++++++++++++++ 13 files changed, 199 insertions(+), 21 deletions(-) diff --git a/scripts/gulp/tasks/release.ts b/scripts/gulp/tasks/release.ts index 65303064ce..ccbf2a434d 100644 --- a/scripts/gulp/tasks/release.ts +++ b/scripts/gulp/tasks/release.ts @@ -277,6 +277,7 @@ task('release.pullLatest', (done: Function) => { done(); } }); + done(); }); task('release.prepareChangelog', () => { diff --git a/src/components/action-sheet/action-sheet.ios.scss b/src/components/action-sheet/action-sheet.ios.scss index 682c854831..32703bb35e 100644 --- a/src/components/action-sheet/action-sheet.ios.scss +++ b/src/components/action-sheet/action-sheet.ios.scss @@ -89,6 +89,10 @@ $action-sheet-ios-button-cancel-font-weight: 600 !default; @include text-align($action-sheet-ios-text-align); } +.action-sheet-ios .action-sheet-wrapper { + @include margin(auto, auto, constant(safe-area-inset-bottom), auto); +} + .action-sheet-ios .action-sheet-container { @include deprecated-variable(padding, $action-sheet-ios-padding) { @include padding($action-sheet-ios-padding-top, $action-sheet-ios-padding-end, $action-sheet-ios-padding-bottom, $action-sheet-ios-padding-start); diff --git a/src/components/content/content.scss b/src/components/content/content.scss index 2dba358a7c..3fd54f3cc4 100644 --- a/src/components/content/content.scss +++ b/src/components/content/content.scss @@ -91,40 +91,66 @@ ion-app [no-padding] .scroll-content { } @mixin content-padding($mode, $content-padding) { - ion-app.#{$mode} [padding], - ion-app.#{$mode} [padding] .scroll-content { + ion-app.#{$mode} [padding] { @include padding($content-padding); } - ion-app.#{$mode} [padding-top], - ion-app.#{$mode} [padding-top] .scroll-content { + ion-app.#{$mode} [padding-top] { @include padding($content-padding, null, null, null); } - ion-app.#{$mode} [padding-left], - ion-app.#{$mode} [padding-left] .scroll-content { + ion-app.#{$mode} [padding-left] { @include padding-horizontal($content-padding, null); } - ion-app.#{$mode} [padding-right], - ion-app.#{$mode} [padding-right] .scroll-content { + ion-app.#{$mode} [padding-right] { @include padding-horizontal(null, $content-padding); } - ion-app.#{$mode} [padding-bottom], - ion-app.#{$mode} [padding-bottom] .scroll-content { + ion-app.#{$mode} [padding-bottom] { @include padding(null, null, $content-padding, null); } - ion-app.#{$mode} [padding-vertical], - ion-app.#{$mode} [padding-vertical] .scroll-content { + ion-app.#{$mode} [padding-vertical] { @include padding($content-padding, null, $content-padding, null); } - ion-app.#{$mode} [padding-horizontal], - ion-app.#{$mode} [padding-horizontal] .scroll-content { + ion-app.#{$mode} [padding-horizontal] { @include padding-horizontal($content-padding); } + + // Scroll content should use safe-area-padding + ion-app.#{$mode} [padding] .scroll-content { + @include safe-area-padding($content-padding); + } + + ion-app.#{$mode} .scroll-content { + @include safe-area-no-padding($content-padding); + } + + ion-app.#{$mode} [padding-top] .scroll-content { + @include safe-area-padding($content-padding, null, null, null); + } + + ion-app.#{$mode} [padding-left] .scroll-content { + @include safe-area-padding-horizontal($content-padding, null); + } + + ion-app.#{$mode} [padding-right] .scroll-content { + @include safe-area-padding-horizontal(null, $content-padding); + } + + ion-app.#{$mode} [padding-bottom] .scroll-content { + @include safe-area-padding(null, null, $content-padding, null); + } + + ion-app.#{$mode} [padding-vertical] .scroll-content { + @include safe-area-padding($content-padding, null, $content-padding, null); + } + + ion-app.#{$mode} [padding-horizontal] .scroll-content { + @include safe-area-padding-horizontal($content-padding); + } } diff --git a/src/components/content/content.ts b/src/components/content/content.ts index 8a00a36518..1bfd65ee71 100644 --- a/src/components/content/content.ts +++ b/src/components/content/content.ts @@ -1,4 +1,4 @@ -import { AfterViewInit, ChangeDetectionStrategy, Component, ElementRef, EventEmitter, Input, NgZone, OnDestroy, Optional, Output, Renderer, ViewChild, ViewEncapsulation } from '@angular/core'; +import { AfterViewInit, ChangeDetectionStrategy, Component, ElementRef, EventEmitter, HostListener, Input, NgZone, OnDestroy, Optional, Output, Renderer, ViewChild, ViewEncapsulation } from '@angular/core'; import { App } from '../app/app'; import { Config } from '../../config/config'; @@ -670,6 +670,7 @@ export class Content extends Ion implements OnDestroy, AfterViewInit, IContent { * Tell the content to recalculate its dimensions. This should be called * after dynamically adding/removing headers, footers, or tabs. */ + @HostListener('window:resize') resize() { this._dom.read(this._readDimensions.bind(this)); this._dom.write(this._writeDimensions.bind(this)); diff --git a/src/components/item/item.ios.scss b/src/components/item/item.ios.scss index 4493c7eb14..5896df3a2b 100644 --- a/src/components/item/item.ios.scss +++ b/src/components/item/item.ios.scss @@ -139,7 +139,9 @@ $item-ios-sliding-content-background: $list-ios-background-color !default; .item-ios [item-right], // deprecated .item-ios [item-end] { - @include margin($item-ios-padding-media-top, ($item-ios-padding-start / 2), $item-ios-padding-media-bottom, ($item-ios-padding-end / 2)); + @include margin($item-ios-padding-media-top, null, $item-ios-padding-media-bottom, ($item-ios-padding-end / 2)); + + @include safe-area-padding-horizontal(null, ($item-ios-padding-start / 4)); } .item-ios ion-icon[item-left], // deprecated diff --git a/src/components/picker/picker.scss b/src/components/picker/picker.scss index bf41d3b628..acd24b2192 100644 --- a/src/components/picker/picker.scss +++ b/src/components/picker/picker.scss @@ -51,6 +51,7 @@ ion-picker-cmp { } .picker-columns { + @include margin(null, null, constant(safe-area-inset-bottom), null); position: relative; display: flex; diff --git a/src/components/tabs/tabs.ios.scss b/src/components/tabs/tabs.ios.scss index 4307620a98..b6213240be 100644 --- a/src/components/tabs/tabs.ios.scss +++ b/src/components/tabs/tabs.ios.scss @@ -42,6 +42,9 @@ $tabs-ios-tab-icon-color-active: $tabs-ios-tab-color-active !default; /// @prop - Font size of the tab button text $tabs-ios-tab-font-size: 10px !default; +/// @prop - Font weight of the tab button text +$tabs-ios-tab-font-weight: 500 !default; + /// @prop - Size of the tab button icon $tabs-ios-tab-icon-size: 30px !default; @@ -63,6 +66,7 @@ $tabs-ios-tab-icon-size: 30px !default; min-height: $tabs-ios-tab-min-height; font-size: $tabs-ios-tab-font-size; + font-weight: $tabs-ios-tab-font-weight; color: $tabs-ios-tab-text-color; @include deprecated-variable(padding, $tabs-ios-tab-padding) { diff --git a/src/components/toast/toast.ios.scss b/src/components/toast/toast.ios.scss index 75cc1c6e5c..0a9432dfe8 100644 --- a/src/components/toast/toast.ios.scss +++ b/src/components/toast/toast.ios.scss @@ -48,6 +48,7 @@ $toast-ios-title-padding-start: $toast-ios-title-padding-end ! .toast-ios .toast-wrapper.toast-top { @include transform(translate3d(0, -100%, 0)); + @include margin(constant(safe-area-inset-top), auto, auto, auto); top: 0; } @@ -55,6 +56,7 @@ $toast-ios-title-padding-start: $toast-ios-title-padding-end ! .toast-ios .toast-wrapper.toast-bottom { @include transform(translate3d(0, 100%, 0)); + @include margin(auto, auto, constant(safe-area-inset-bottom), auto); bottom: 0; } diff --git a/src/platform/cordova.ios.scss b/src/platform/cordova.ios.scss index a35a77f0b7..7821dce32e 100644 --- a/src/platform/cordova.ios.scss +++ b/src/platform/cordova.ios.scss @@ -11,5 +11,7 @@ $cordova-ios-statusbar-padding-modal-max-width: $cordova-statusbar-paddi // Cordova mixins are in the main cordova file .ios { - @include statusbar-padding($toolbar-ios-height, $toolbar-ios-padding, $content-ios-padding, $cordova-ios-statusbar-padding, $cordova-ios-statusbar-padding-modal-max-width, true); -} \ No newline at end of file + @include statusbar-padding($toolbar-ios-height, $toolbar-ios-padding, $content-ios-padding, $cordova-ios-statusbar-padding, $cordova-ios-statusbar-padding-modal-max-width, true); + + @include footer-safe-area($toolbar-ios-height, $toolbar-ios-padding); +} diff --git a/src/platform/cordova.md.scss b/src/platform/cordova.md.scss index 4449c019aa..66b7701a61 100644 --- a/src/platform/cordova.md.scss +++ b/src/platform/cordova.md.scss @@ -12,5 +12,7 @@ $cordova-md-statusbar-padding-modal-max-width: $cordova-statusbar-paddin // Cordova mixins are in the main cordova file .md { @include statusbar-padding($toolbar-md-height, $toolbar-md-padding, $content-md-padding, $cordova-md-statusbar-padding, $cordova-md-statusbar-padding-modal-max-width); + + @include footer-safe-area($toolbar-md-height, $toolbar-md-padding); } diff --git a/src/platform/cordova.scss b/src/platform/cordova.scss index c459a53542..a60a773a88 100644 --- a/src/platform/cordova.scss +++ b/src/platform/cordova.scss @@ -11,6 +11,7 @@ $cordova-statusbar-padding-modal-max-width: 767px !default; ion-nav > .ion-page, ion-nav > .ion-page > ion-header, + ion-tab > .ion-page, ion-tab > .ion-page > ion-header, ion-tabs > .ion-page.tab-subpage > ion-header, ion-menu > .menu-inner, @@ -20,7 +21,7 @@ $cordova-statusbar-padding-modal-max-width: 767px !default; // If we should style the title elements in the toolbar @if ($style-title) { - @include toolbar-title-statusbar-padding($toolbar-height, $content-padding, $cordova-statusbar-padding); + @include toolbar-title-statusbar-padding($toolbar-height, $toolbar-padding, $content-padding, $cordova-statusbar-padding); } } @@ -30,7 +31,7 @@ $cordova-statusbar-padding-modal-max-width: 767px !default; // If we should style the title elements in the toolbar @if ($style-title) { - @include toolbar-title-statusbar-padding($toolbar-height, $content-padding, $cordova-statusbar-padding); + @include toolbar-title-statusbar-padding($toolbar-height, $toolbar-padding, $content-padding, $cordova-statusbar-padding); } } } @@ -42,19 +43,24 @@ $cordova-statusbar-padding-modal-max-width: 767px !default; @mixin toolbar-statusbar-padding($toolbar-height, $toolbar-padding, $content-padding, $cordova-statusbar-padding) { + > .toolbar.statusbar-padding:first-child { @include padding(calc(#{$cordova-statusbar-padding} + #{$toolbar-padding}), null, null, null); + @include padding(calc(constant(safe-area-inset-top) + #{$toolbar-padding}), calc(constant(safe-area-inset-right) + #{$toolbar-padding}), null, calc(constant(safe-area-inset-left) + #{$toolbar-padding})); min-height: calc(#{$toolbar-height} + #{$cordova-statusbar-padding}); + min-height: calc(#{$toolbar-height} + constant(safe-area-inset-top)); } > ion-content.statusbar-padding:first-child .scroll-content { @include padding($cordova-statusbar-padding, null, null, null); + @include padding(calc(#{$cordova-statusbar-padding} + constant(safe-area-inset-top)), 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} + #{$cordova-statusbar-padding}), null, null, null); + @include padding(calc(#{$content-padding} + constant(safe-area-inset-top)), null, null, null); } } @@ -63,14 +69,31 @@ $cordova-statusbar-padding-modal-max-width: 767px !default; // iOS is the only mode that uses this mixin and it should be removed with #5036 // -------------------------------------------------------------------------------- -@mixin toolbar-title-statusbar-padding($toolbar-height, $content-padding, $cordova-statusbar-padding) { +@mixin toolbar-title-statusbar-padding($toolbar-height, $toolbar-padding, $content-padding, $cordova-statusbar-padding) { > .toolbar.statusbar-padding:first-child ion-segment, > .toolbar.statusbar-padding:first-child ion-title { @include padding($cordova-statusbar-padding, null, null, null); + @include padding(calc(constant(safe-area-inset-top) + #{$toolbar-padding}), null, null, null); height: calc(#{$toolbar-height} + #{$cordova-statusbar-padding}); + height: calc(#{$toolbar-height} + constant(safe-area-inset-top)); + min-height: calc(#{$toolbar-height} + #{$cordova-statusbar-padding}); + min-height: calc(#{$toolbar-height} + constant(safe-area-inset-top)); } } + + +@mixin footer-safe-area($toolbar-height, $toolbar-padding) { + .tabs .tabbar { + @include padding(null, null, constant(safe-area-inset-bottom), null); + } + + ion-footer .toolbar:last-child { + @include padding(null, null, calc(constant(safe-area-inset-top) + #{$toolbar-padding}), null); + height: calc(#{$toolbar-height} + constant(safe-area-inset-top)); + min-height: calc(#{$toolbar-height} + constant(safe-area-inset-top)); + } +} diff --git a/src/platform/cordova.wp.scss b/src/platform/cordova.wp.scss index a6b3928ed1..d4687d1d7e 100644 --- a/src/platform/cordova.wp.scss +++ b/src/platform/cordova.wp.scss @@ -12,4 +12,6 @@ $cordova-wp-statusbar-padding-modal-max-width: $cordova-statusbar-paddin // Cordova mixins are in the main cordova file .wp { @include statusbar-padding($toolbar-wp-height, $toolbar-wp-padding, $content-wp-padding, $cordova-wp-statusbar-padding, $cordova-wp-statusbar-padding-modal-max-width); + + @include footer-safe-area($toolbar-wp-height, $toolbar-wp-padding); } diff --git a/src/themes/ionic.mixins.scss b/src/themes/ionic.mixins.scss index 617b2bd570..413a89cc4e 100644 --- a/src/themes/ionic.mixins.scss +++ b/src/themes/ionic.mixins.scss @@ -538,3 +538,111 @@ } } } + + +// Add safe-area transform for all directions +// Used by item-reorder +// @param {string} $transforms - comma separated list of transforms +@mixin reorder-safe-translate($transforms...) { + $extra: null; + + $x: null; + $ltr-translate: null; + $rtl-translate: null; + + @each $transform in $transforms { + @if (str-index($transform, translate3d)) { + $transform: str-replace($transform, 'translate3d('); + $transform: str-replace($transform, ')'); + + $coordinates: str-split($transform, ','); + + $x: nth($coordinates, 1); + $y: nth($coordinates, 2); + $z: nth($coordinates, 3); + + $ltr-translate: translate3d(calc(-1 * constant(safe-area-inset-right)), 0, 0); + $rtl-translate: translate3d(constant(safe-area-inset-left), $y, $z); + } @else { + @if $extra == null { + $extra: $transform; + } @else { + $extra: $extra $transform; + } + } + } + + @if $x == '0' or $x == null { + @include multi-dir() { + transform: $ltr-translate $extra; + } + } @else { + @include ltr() { + transform: $ltr-translate $extra; + } + + @include rtl() { + transform: $rtl-translate $extra; + } + } +} + +// Add safe-area-padding for all directions +// @param {string} $top +// @param {string} $end +// @param {string} $bottom +// @param {string} $start +// ---------------------------------------------------------- +@mixin safe-area-padding($top, $end: $top, $bottom: $top, $start: $end) { + $safe-area-start: null; + + @if ($start) { + $safe-area-start: calc(constant(safe-area-inset-left) + #{$start}); + } + + @include padding($top, $end, $bottom, $start); + + @media screen and (orientation: landscape) { + @include padding($top, $end, $bottom, $safe-area-start); + } +} + + +// Add safe area padding horizontal +// @param {string} $start +// @param {string} $end +// ---------------------------------------------------------- +@mixin safe-area-padding-horizontal($start, $end: $start) { + $safe-area-end: null; + $safe-area-start: null; + + @if ($end) { + $safe-area-end: calc(constant(safe-area-inset-right) + #{$end}); + } + @if ($start) { + $safe-area-start: calc(constant(safe-area-inset-left) + #{$start}); + } + + @include padding-horizontal($start, $end); + + @media screen and (orientation: landscape) { + @include padding-horizontal($safe-area-start, $safe-area-end); + } +} + + +// Add safe area padding to a screen +// only if it is landscape mode, then only on the left +// @param {string} $start +// ---------------------------------------------------------- +@mixin safe-area-no-padding($start) { + $safe-area-start: null; + + @if ($start) { + $safe-area-start: calc(constant(safe-area-inset-left) + #{$start}); + } + + @media screen and (orientation: landscape) { + @include padding-horizontal($safe-area-start, null); + } +}