From 2273fb5d47eb64375f1608370d32b330cdc30bd9 Mon Sep 17 00:00:00 2001 From: Amit Moryossef Date: Thu, 8 Jun 2017 22:27:45 +0300 Subject: [PATCH] feat(rtl): add transform and transform-origin support for rtl (#11649) * feat(rtl): add translate3d support for directions * feat(rtl): add transform-origin support for directions * fix(transform): add missing origins * fix(transform): when given a percentage, calc on rtl * fix(transform-origin): be same as before * fix(translate3d): no double minus * fix(translate3d): use transform instead of cloning code * style(scss-lint): remove empty line * fix(merge): fix bad merge * refactor(transform-origin): nicer logic * style(): add eof line * fix(transform): remove unneeded mixin * feat(rtl): add transform mixin and str-split function * Merge remote-tracking branch 'remotes/upstream/rtl-transform' into transform-rtl # Conflicts: # src/themes/ionic.mixins.scss * fix(transform): fix string comparison --- .scss-lint.yml | 2 +- src/components/action-sheet/action-sheet.scss | 3 +- src/components/button/button.md.scss | 2 +- src/components/datetime/datetime.wp.scss | 2 +- src/components/item/item-reorder.scss | 5 +- src/components/label/label.ios.scss | 10 +- src/components/label/label.md.scss | 11 +- src/components/label/label.wp.scss | 11 +- src/components/menu/menu.scss | 7 +- src/components/modal/modal.ios.scss | 2 +- src/components/modal/modal.md.scss | 3 +- src/components/modal/modal.wp.scss | 3 +- src/components/picker/picker.ios.scss | 8 +- src/components/picker/picker.md.scss | 6 +- src/components/picker/picker.scss | 4 +- src/components/picker/picker.wp.scss | 6 +- src/components/popover/popover.md.scss | 3 +- src/components/popover/popover.wp.scss | 3 +- src/components/range/range.ios.scss | 4 +- src/components/range/range.md.scss | 4 +- src/components/range/range.wp.scss | 4 +- src/components/refresher/refresher.scss | 2 +- src/components/searchbar/searchbar.ios.scss | 2 +- src/components/slides/slides.scss | 19 ++-- src/components/spinner/spinner.scss | 2 +- src/components/tabs/tabs.md.scss | 100 ++++++++++++++---- src/components/toast/toast.ios.scss | 8 +- src/components/toast/toast.md.scss | 8 +- src/components/toggle/toggle.ios.scss | 3 +- src/components/toggle/toggle.md.scss | 3 +- src/components/toggle/toggle.wp.scss | 3 +- src/themes/ionic.functions.scss | 26 +++++ src/themes/ionic.mixins.scss | 77 +++++++++++++- src/themes/util.scss | 4 +- 34 files changed, 249 insertions(+), 111 deletions(-) diff --git a/.scss-lint.yml b/.scss-lint.yml index ed31bc61f3..66e519d65c 100644 --- a/.scss-lint.yml +++ b/.scss-lint.yml @@ -157,7 +157,6 @@ linters: - transform - transform-box - - transform-origin - transform-style - transition @@ -211,3 +210,4 @@ linters: - border-bottom-right-radius - border-bottom-left-radius - text-align + - transform-origin \ No newline at end of file diff --git a/src/components/action-sheet/action-sheet.scss b/src/components/action-sheet/action-sheet.scss index 7b772fc8ec..57c14655ac 100644 --- a/src/components/action-sheet/action-sheet.scss +++ b/src/components/action-sheet/action-sheet.scss @@ -24,6 +24,7 @@ ion-action-sheet { .action-sheet-wrapper { @include position(null, 0, 0, 0); @include margin(auto); + @include transform(translate3d(0, 100%, 0)); position: absolute; z-index: $z-index-overlay-wrapper; @@ -31,8 +32,6 @@ ion-action-sheet { width: $action-sheet-width; max-width: $action-sheet-max-width; - - transform: translate3d(0, 100%, 0); } .action-sheet-button { diff --git a/src/components/button/button.md.scss b/src/components/button/button.md.scss index 20284efc16..dc4ca05fc5 100644 --- a/src/components/button/button.md.scss +++ b/src/components/button/button.md.scss @@ -471,6 +471,7 @@ $button-md-strong-font-weight: bold !default; .button-effect { @include border-radius(50%); + @include transform-origin(center, center); position: absolute; z-index: 0; @@ -479,7 +480,6 @@ $button-md-strong-font-weight: bold !default; background-color: $button-md-ripple-background-color; opacity: .2; - transform-origin: center center; transition-timing-function: ease-in-out; pointer-events: none; diff --git a/src/components/datetime/datetime.wp.scss b/src/components/datetime/datetime.wp.scss index d2f0b975ed..3d30441852 100644 --- a/src/components/datetime/datetime.wp.scss +++ b/src/components/datetime/datetime.wp.scss @@ -48,7 +48,7 @@ $datetime-wp-placeholder-color: $input-wp-border-color !default; } .item-datetime .datetime-wp ion-label[floating] { - transform: translate3d(8px, 41px, 0); + @include transform(translate3d(8px, 41px, 0)); } .datetime-wp .datetime-placeholder { diff --git a/src/components/item/item-reorder.scss b/src/components/item/item-reorder.scss index 01f9fb82c8..1cc415e7ca 100644 --- a/src/components/item/item-reorder.scss +++ b/src/components/item/item-reorder.scss @@ -4,6 +4,8 @@ // -------------------------------------------------- ion-reorder { + @include transform(translate3d(160%, 0, 0)); + display: none; flex: 1; @@ -16,7 +18,6 @@ ion-reorder { font-size: 1.7em; opacity: .25; - transform: translate3d(160%, 0, 0); transition: transform 140ms ease-in; @@ -33,7 +34,7 @@ ion-reorder ion-icon { } .reorder-visible ion-reorder { - transform: translate3d(0, 0, 0); + @include transform(translate3d(0, 0, 0)); } .reorder-list-active .item, diff --git a/src/components/label/label.ios.scss b/src/components/label/label.ios.scss index fe8aaa5f1c..74abe0bde0 100644 --- a/src/components/label/label.ios.scss +++ b/src/components/label/label.ios.scss @@ -67,23 +67,19 @@ $label-ios-margin-start: 0 !default; .label-ios[floating] { @include margin(null, null, 0, null); + @include transform(translate3d(0, 27px, 0)); + @include transform-origin(start, top); - transform: translate3d(0, 27px, 0); - transform-origin: left top; transition: transform 150ms ease-in-out; } -[dir="rtl"] .label-ios[floating] { - transform-origin: right top; -} - // TODO remove all uses of input-has-focus in v4 // TODO remove all uses of input-has-value in v4 .item-input-has-focus .label-ios[floating], .input-has-focus .label-ios[floating], .item-input-has-value .label-ios[floating], .input-has-value .label-ios[floating] { - transform: translate3d(0, 0, 0) scale(.8); + @include transform(translate3d(0, 0, 0), scale(.8)); } .item-ios.item-label-stacked [item-right], // deprecated diff --git a/src/components/label/label.md.scss b/src/components/label/label.md.scss index daaf5edd4c..342e1dfb36 100644 --- a/src/components/label/label.md.scss +++ b/src/components/label/label.md.scss @@ -56,13 +56,10 @@ $label-md-margin-start: 0 !default; } .label-md[floating] { - transform: translate3d(0, 27px, 0); - transform-origin: left top; - transition: transform 150ms ease-in-out; -} + @include transform(translate3d(0, 27px, 0)); + @include transform-origin(start, top); -[dir="rtl"] .label-md[floating] { - transform-origin: right top; + transition: transform 150ms ease-in-out; } .label-md[stacked], @@ -83,7 +80,7 @@ $label-md-margin-start: 0 !default; .input-has-focus .label-md[floating], .item-input-has-value .label-md[floating], .input-has-value .label-md[floating] { - transform: translate3d(0, 0, 0) scale(.8); + @include transform(translate3d(0, 0, 0), scale(.8)); } .item-md.item-label-stacked [item-right], // deprecated diff --git a/src/components/label/label.wp.scss b/src/components/label/label.wp.scss index 0f6c1c09ce..0e6dabe85b 100644 --- a/src/components/label/label.wp.scss +++ b/src/components/label/label.wp.scss @@ -36,13 +36,8 @@ $label-wp-text-color-focused: color($colors-wp, primary) !default; } .label-wp[floating] { - transform: translate3d(8px, 34px, 0); - transform-origin: left top; -} - -[dir="rtl"] .label-wp[floating] { - transform: translate3d(-8px, 34px, 0); - transform-origin: right top; + @include transform(translate3d(8px, 34px, 0)); + @include transform-origin(start, top); } .label-wp[stacked], @@ -63,7 +58,7 @@ $label-wp-text-color-focused: color($colors-wp, primary) !default; .input-has-focus .label-wp[floating], .item-input-has-value .label-wp[floating], .input-has-value .label-wp[floating] { - transform: translate3d(0, 0, 0) scale(.8); + @include transform(translate3d(0, 0, 0), scale(.8)); } .item-wp.item-label-stacked [item-right], // deprecated diff --git a/src/components/menu/menu.scss b/src/components/menu/menu.scss index 163070b3af..28a65eb046 100644 --- a/src/components/menu/menu.scss +++ b/src/components/menu/menu.scss @@ -27,6 +27,7 @@ ion-menu.show-menu { .menu-inner { @include position(0, auto, 0, 0); + @include transform(translate3d(-9999px, 0, 0)); position: absolute; @@ -35,8 +36,6 @@ ion-menu.show-menu { width: $menu-width; height: 100%; - transform: translate3d(-9999px, 0, 0); - contain: strict; } @@ -74,7 +73,7 @@ ion-menu ion-backdrop { } .menu-content { - transform: translate3d(0, 0, 0); + @include transform(translate3d(0, 0, 0)); } .menu-content-open { @@ -111,7 +110,7 @@ ion-menu[type=reveal] { } ion-menu[type=reveal].show-menu .menu-inner { - transform: translate3d(0, 0, 0); + @include transform(translate3d(0, 0, 0)); } diff --git a/src/components/modal/modal.ios.scss b/src/components/modal/modal.ios.scss index 8dec9d9b1c..891d2d3405 100644 --- a/src/components/modal/modal.ios.scss +++ b/src/components/modal/modal.ios.scss @@ -11,7 +11,7 @@ $modal-ios-border-radius: 10px !default; .ios .modal-wrapper { // hidden by default to prevent flickers, the animation will show it - transform: translate3d(0, 100%, 0); + @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); diff --git a/src/components/modal/modal.md.scss b/src/components/modal/modal.md.scss index 7d685a18dc..9631f77a97 100644 --- a/src/components/modal/modal.md.scss +++ b/src/components/modal/modal.md.scss @@ -13,8 +13,9 @@ $modal-inset-box-shadow-color: rgba(0, 0, 0, .4) !default; $modal-inset-box-shadow: 0 28px 48px $modal-inset-box-shadow-color !default; .md .modal-wrapper { + @include transform(translate3d(0, 40px, 0)); + opacity: .01; - 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); diff --git a/src/components/modal/modal.wp.scss b/src/components/modal/modal.wp.scss index b369cdc197..8ca943d069 100644 --- a/src/components/modal/modal.wp.scss +++ b/src/components/modal/modal.wp.scss @@ -7,6 +7,7 @@ $modal-wp-background-color: $background-wp-color !default; .wp .modal-wrapper { + @include transform(translate3d(0, 40px, 0)); + opacity: .01; - transform: translate3d(0, 40px, 0); } diff --git a/src/components/picker/picker.ios.scss b/src/components/picker/picker.ios.scss index f5f6ebb3ba..d75876a149 100644 --- a/src/components/picker/picker.ios.scss +++ b/src/components/picker/picker.ios.scss @@ -148,6 +148,7 @@ $picker-button-ios-strong-font-weight: 600 !default; .picker-ios .picker-opt { @include margin(0); + @include transform-origin(center, center); height: 4.6rem; @@ -156,7 +157,6 @@ $picker-button-ios-strong-font-weight: 600 !default; color: $picker-ios-option-text-color; background: transparent; - transform-origin: center center; transform-style: preserve-3d; transition-timing-function: ease-out; @@ -171,6 +171,7 @@ $picker-button-ios-strong-font-weight: 600 !default; .picker-ios .picker-above-highlight { @include position(0, null, null, 0); + @include transform(translate3d(0, 0, 90px)); position: absolute; z-index: 10; @@ -184,12 +185,11 @@ $picker-button-ios-strong-font-weight: 600 !default; background: linear-gradient(to bottom, rgba($picker-ios-background-color, 1) 20%, rgba($picker-ios-background-color, .7) 100%); - - transform: translate3d(0, 0, 90px); } .picker-ios .picker-below-highlight { @include position($picker-ios-option-offset-y + $picker-ios-option-height - 4, null, null, 0); + @include transform(translate3d(0, 0, 90px)); position: absolute; @@ -204,6 +204,4 @@ $picker-button-ios-strong-font-weight: 600 !default; background: linear-gradient(to top, rgba($picker-ios-background-color, 1) 30%, rgba($picker-ios-background-color, .7) 100%); - - transform: translate3d(0, 0, 90px); } diff --git a/src/components/picker/picker.md.scss b/src/components/picker/picker.md.scss index 7c33f6b772..5c2e126b65 100644 --- a/src/components/picker/picker.md.scss +++ b/src/components/picker/picker.md.scss @@ -163,6 +163,7 @@ $picker-md-option-selected-color: color($colors-md, primary) !defaul .picker-md .picker-above-highlight { @include position(0, null, null, 0); + @include transform(translate3d(0, 0, 90px)); position: absolute; z-index: 10; @@ -175,12 +176,11 @@ $picker-md-option-selected-color: color($colors-md, primary) !defaul background: linear-gradient(to bottom, rgba($picker-md-background-color, 1) 20%, rgba($picker-md-background-color, .7) 100%); - - transform: translate3d(0, 0, 90px); } .picker-md .picker-below-highlight { @include position($picker-md-option-offset-y + $picker-md-option-height - 4, null, null, 0); + @include transform(translate3d(0, 0, 90px)); position: absolute; z-index: 11; @@ -193,6 +193,4 @@ $picker-md-option-selected-color: color($colors-md, primary) !defaul background: linear-gradient(to top, rgba($picker-md-background-color, 1) 30%, rgba($picker-md-background-color, .7) 100%); - - transform: translate3d(0, 0, 90px); } diff --git a/src/components/picker/picker.scss b/src/components/picker/picker.scss index 074f9ddd56..2d126dc81c 100644 --- a/src/components/picker/picker.scss +++ b/src/components/picker/picker.scss @@ -33,8 +33,8 @@ ion-picker-cmp { .picker-wrapper { @include position(null, 0, 0, 0); - @include margin(auto); + @include transform(translate3d(0, 100%, 0)); position: absolute; z-index: $z-index-overlay-wrapper; @@ -47,8 +47,6 @@ ion-picker-cmp { width: $picker-width; max-width: $picker-max-width; - transform: translate3d(0, 100%, 0); - contain: strict; } diff --git a/src/components/picker/picker.wp.scss b/src/components/picker/picker.wp.scss index 5482f3c1d7..e19f933215 100644 --- a/src/components/picker/picker.wp.scss +++ b/src/components/picker/picker.wp.scss @@ -175,6 +175,7 @@ $picker-wp-option-selected-color: color($colors-wp, primary) !defaul .picker-wp .picker-above-highlight { @include position(0, null, null, 0); + @include transform(translate3d(0, 0, 90px)); position: absolute; @@ -188,12 +189,11 @@ $picker-wp-option-selected-color: color($colors-wp, primary) !defaul background: linear-gradient(to bottom, rgba($picker-wp-background-color, 1) 20%, rgba($picker-wp-background-color, .7) 100%); - - transform: translate3d(0, 0, 90px); } .picker-wp .picker-below-highlight { @include position($picker-wp-option-offset-y + $picker-wp-option-height - 4, null, null, 0); + @include transform(translate3d(0, 0, 90px)); position: absolute; @@ -207,6 +207,4 @@ $picker-wp-option-selected-color: color($colors-wp, primary) !defaul background: linear-gradient(to top, rgba($picker-wp-background-color, 1) 30%, rgba($picker-wp-background-color, .7) 100%); - - transform: translate3d(0, 0, 90px); } diff --git a/src/components/popover/popover.md.scss b/src/components/popover/popover.md.scss index 25fb2ccf7c..13aa3de621 100644 --- a/src/components/popover/popover.md.scss +++ b/src/components/popover/popover.md.scss @@ -33,6 +33,7 @@ $popover-md-box-shadow: 0 3px 12px 2px $popover-md-box-shadow-col .popover-md .popover-content { @include border-radius($popover-md-border-radius); + @include transform-origin(start, top); width: $popover-md-width; min-width: $popover-md-min-width; @@ -42,8 +43,6 @@ $popover-md-box-shadow: 0 3px 12px 2px $popover-md-box-shadow-col color: $popover-md-text-color; background: $popover-md-background; box-shadow: $popover-md-box-shadow; - - transform-origin: top left; } .popover-md .popover-viewport { diff --git a/src/components/popover/popover.wp.scss b/src/components/popover/popover.wp.scss index 89e1c2b874..b7d2b11f1d 100644 --- a/src/components/popover/popover.wp.scss +++ b/src/components/popover/popover.wp.scss @@ -30,6 +30,7 @@ $popover-wp-background: $background-wp-color !default; .popover-wp .popover-content { @include border-radius($popover-wp-border-radius); + @include transform-origin(start, top); width: $popover-wp-width; min-width: $popover-wp-min-width; @@ -39,8 +40,6 @@ $popover-wp-background: $background-wp-color !default; border: $popover-wp-border; color: $popover-wp-text-color; background: $popover-wp-background; - - transform-origin: top left; } .popover-wp .popover-viewport { diff --git a/src/components/range/range.ios.scss b/src/components/range/range.ios.scss index f0b9225a0f..eded03f7aa 100644 --- a/src/components/range/range.ios.scss +++ b/src/components/range/range.ios.scss @@ -182,6 +182,7 @@ $range-ios-pin-padding-start: $range-ios-pin-padding-end !defaul .range-ios .range-pin { @include text-align(center); @include border-radius(50px); + @include transform(translate3d(0, 28px, 0), scale(.01)); position: relative; top: -20px; @@ -195,7 +196,6 @@ $range-ios-pin-padding-start: $range-ios-pin-padding-end !defaul background: $range-ios-pin-background-color; - transform: translate3d(0, 28px, 0) scale(.01); transition: transform 120ms ease; @include deprecated-variable(padding, $range-ios-pin-padding) { @@ -204,7 +204,7 @@ $range-ios-pin-padding-start: $range-ios-pin-padding-end !defaul } .range-ios .range-knob-pressed .range-pin { - transform: translate3d(0, 0, 0) scale(1); + @include transform(translate3d(0, 0, 0), scale(1)); } .range-ios.range-disabled { diff --git a/src/components/range/range.md.scss b/src/components/range/range.md.scss index 94bd0ca013..90f792e86b 100644 --- a/src/components/range/range.md.scss +++ b/src/components/range/range.md.scss @@ -184,6 +184,7 @@ $range-md-pin-min-background-color: $range-md-bar-background-color !def @include padding($range-md-pin-padding-vertical, $range-md-pin-padding-horizontal); @include text-align(center); @include border-radius(50%); + @include transform(translate3d(0, 28px, 0), scale(.01)); position: relative; top: -20px; @@ -198,7 +199,6 @@ $range-md-pin-min-background-color: $range-md-bar-background-color !def background: $range-md-pin-background-color; - transform: translate3d(0, 28px, 0) scale(.01); transition: transform 120ms ease, background-color 120ms ease; &::before { @@ -222,7 +222,7 @@ $range-md-pin-min-background-color: $range-md-bar-background-color !def } .range-md .range-knob-pressed .range-pin { - transform: translate3d(0, 0, 0) scale(1); + @include transform(translate3d(0, 0, 0), scale(1)); } .range-md:not(.range-has-pin) .range-knob-pressed .range-knob { diff --git a/src/components/range/range.wp.scss b/src/components/range/range.wp.scss index 0bee7d6e6c..b31ed01790 100644 --- a/src/components/range/range.wp.scss +++ b/src/components/range/range.wp.scss @@ -176,6 +176,7 @@ $range-wp-pin-padding-start: $range-wp-pin-padding-end !default; .range-wp .range-pin { @include text-align(center); @include border-radius(50px); + @include transform(translate3d(0, 28px, 0), scale(.01)); position: relative; top: -24px; @@ -189,7 +190,6 @@ $range-wp-pin-padding-start: $range-wp-pin-padding-end !default; background: $range-wp-pin-background-color; - transform: translate3d(0, 28px, 0) scale(.01); transition: transform 120ms ease; @include deprecated-variable(padding, $range-wp-pin-padding) { @@ -198,7 +198,7 @@ $range-wp-pin-padding-start: $range-wp-pin-padding-end !default; } .range-wp .range-knob-pressed .range-pin { - transform: translate3d(0, 0, 0) scale(1); + @include transform(translate3d(0, 0, 0), scale(1)); } .range-wp.range-disabled { diff --git a/src/components/refresher/refresher.scss b/src/components/refresher/refresher.scss index ec8f19933a..97a9f293b1 100644 --- a/src/components/refresher/refresher.scss +++ b/src/components/refresher/refresher.scss @@ -72,10 +72,10 @@ ion-refresher-content { .refresher-pulling-icon, .refresher-refreshing-icon { @include text-align(center); + @include transform-origin(center); font-size: $refresher-icon-font-size; color: $refresher-icon-color; - transform-origin: center; transition: 200ms; } diff --git a/src/components/searchbar/searchbar.ios.scss b/src/components/searchbar/searchbar.ios.scss index 0b3dd529a1..51447b583a 100644 --- a/src/components/searchbar/searchbar.ios.scss +++ b/src/components/searchbar/searchbar.ios.scss @@ -254,9 +254,9 @@ $searchbar-ios-toolbar-input-background: rgba(0, 0, 0, .08) !default; .searchbar-animated .searchbar-ios-cancel { @include margin-horizontal(null, -100%); + @include transform(translate3d(0, 0, 0)); opacity: 0; - transform: translate3d(0, 0, 0); transition: $searchbar-ios-cancel-transition; pointer-events: none; diff --git a/src/components/slides/slides.scss b/src/components/slides/slides.scss index 8b04707991..ca1aecab36 100644 --- a/src/components/slides/slides.scss +++ b/src/components/slides/slides.scss @@ -53,7 +53,7 @@ .swiper-container-android .swiper-slide, .swiper-wrapper { - transform: translate3d(0, 0, 0); + @include transform(translate3d(0, 0, 0)); } .swiper-container-multirow > .swiper-wrapper { @@ -183,11 +183,11 @@ // Pagination Styles .swiper-pagination { @include text-align(center); + @include transform(translate3d(0, 0, 0)); position: absolute; z-index: 10; - transform: translate3d(0, 0, 0); transition: 300ms; pointer-events: none; @@ -253,8 +253,7 @@ button.swiper-pagination-bullet { .swiper-container-vertical > .swiper-pagination-bullets { @include position(50%, 10px, null, null); - - transform: translate3d(0, -50%, 0); + @include transform(translate3d(0, -50%, 0)); } .swiper-container-vertical > .swiper-pagination-bullets .swiper-pagination-bullet { @@ -276,6 +275,7 @@ button.swiper-pagination-bullet { .swiper-pagination-progress .swiper-pagination-progressbar { @include position(0, null, null, 0); + @include transform-origin(start, top); position: absolute; @@ -285,11 +285,10 @@ button.swiper-pagination-bullet { background: #007aff; transform: scale(0); - transform-origin: left top; } .swiper-container-rtl .swiper-pagination-progress .swiper-pagination-progressbar { - transform-origin: right top; + @include transform-origin(end, top); } .swiper-container-horizontal > .swiper-pagination-progress { @@ -413,15 +412,16 @@ button.swiper-pagination-bullet { // Cube .swiper-container-cube .swiper-slide { + @include transform-origin(0, 0); + width: 100%; height: 100%; visibility: hidden; - transform-origin: 0 0; } .swiper-container-cube.swiper-container-rtl .swiper-slide { - transform-origin: 100% 0; + @include transform-origin(100%, 0); } .swiper-container-cube .swiper-slide-active, @@ -540,6 +540,7 @@ button.swiper-pagination-bullet { .swiper-lazy-preloader { @include position(50%, null, null, 50%); @include margin(-21px, null, null, -21px); + @include transform-origin(50%); position: absolute; z-index: 10; @@ -547,8 +548,6 @@ button.swiper-pagination-bullet { width: 42px; height: 42px; - transform-origin: 50%; - animation: swiper-preloader-spin 1s steps(12, end) infinite; } diff --git a/src/components/spinner/spinner.scss b/src/components/spinner/spinner.scss index 9601e289c9..46d0dd894f 100644 --- a/src/components/spinner/spinner.scss +++ b/src/components/spinner/spinner.scss @@ -81,7 +81,7 @@ ion-spinner.spinner-paused svg { } .spinner-dots svg { - transform-origin: center; + @include transform-origin(center); animation: spinner-dots 1s linear infinite; } diff --git a/src/components/tabs/tabs.md.scss b/src/components/tabs/tabs.md.scss index c5970e7b2e..8bc4772178 100644 --- a/src/components/tabs/tabs.md.scss +++ b/src/components/tabs/tabs.md.scss @@ -78,8 +78,14 @@ $tabs-md-tab-text-margin-start: $tabs-md-tab-text-margin-end !defa /// @prop - Capitalization of the tab button text $tabs-md-tab-text-capitalization: none !default; -/// @prop - Transform origin for the tab button text -$tabs-md-tab-text-transform-origin: 50% 80% !default; +// deprecated +$tabs-md-tab-text-transform-origin: null !default; + +/// @prop - Transform origin x for the tab button text +$tabs-md-tab-text-transform-origin-x: 50% !default; + +/// @prop - Transform origin y for the tab button text +$tabs-md-tab-text-transform-origin-y: 80% !default; /// @prop - Transform for the active tab button text $tabs-md-tab-text-transform-active: scale3d($tabs-md-tab-font-size-active / $tabs-md-tab-font-size, $tabs-md-tab-font-size-active / $tabs-md-tab-font-size, 1) !default; @@ -87,24 +93,62 @@ $tabs-md-tab-text-transform-active: scale3d($tabs-md-tab-font-size-act /// @prop - Text transition for the tab button text $tabs-md-tab-text-transition: transform .3s ease-in-out !default; -/// @prop - Transform for the active tab button icon when the layout is icon-top, icon-only, or title-only -$tabs-md-tab-icon-transform-active: translate3d(0, -2px, 0) !default; +// deprecated +$tabs-md-tab-icon-transform-active: null !default; + +/// @prop - Transform x for the active tab button icon when the layout is icon-top, icon-only, or title-only +$tabs-md-tab-icon-transform-x-active: 0 !default; + +/// @prop - Transform y for the active tab button icon when the layout is icon-top, icon-only, or title-only +$tabs-md-tab-icon-transform-y-active: -2px !default; + +/// @prop - Transform z for the active tab button icon when the layout is icon-top, icon-only, or title-only +$tabs-md-tab-icon-transform-z-active: 0 !default; // deprecated -$tabs-md-tab-icon-right-transform-active: translate3d(2px, 0, 0) !default; -/// @prop - Transform for the active tab button icon when the layout is icon-end -$tabs-md-tab-icon-end-transform-active: $tabs-md-tab-icon-right-transform-active !default; +$tabs-md-tab-icon-end-transform-active: null !default; -/// @prop - Transform for the active tab button icon when the layout is icon-bottom -$tabs-md-tab-icon-bottom-transform-active: translate3d(0, 2px, 0) !default; +/// @prop - Transform x for the active tab button icon when the layout is icon-right +$tabs-md-tab-icon-right-transform-x-active: 2px !default; + +/// @prop - Transform y for the active tab button icon when the layout is icon-right +$tabs-md-tab-icon-right-transform-y-active: 0 !default; + +/// @prop - Transform z for the active tab button icon when the layout is icon-right +$tabs-md-tab-icon-right-transform-z-active: 0 !default; // deprecated -$tabs-md-tab-icon-left-transform-active: translate3d(-2px, 0, 0) !default; -/// @prop - Transform for the active tab button icon when the layout is icon-start -$tabs-md-tab-icon-start-transform-active: $tabs-md-tab-icon-left-transform-active !default; +$tabs-md-tab-icon-bottom-transform-active: null !default; -/// @prop - Transform origin for the tab button text -$tabs-md-tab-icon-transform-origin: 50% 150% !default; +/// @prop - Transform x for the active tab button icon when the layout is icon-bottom +$tabs-md-tab-icon-bottom-transform-x-active: 0 !default; + +/// @prop - Transform y for the active tab button icon when the layout is icon-bottom +$tabs-md-tab-icon-bottom-transform-y-active: 2px !default; + +/// @prop - Transform z for the active tab button icon when the layout is icon-bottom +$tabs-md-tab-icon-bottom-transform-z-active: 0 !default; + +// deprecated +$tabs-md-tab-icon-start-transform-active: null !default; + +/// @prop - Transform x for the active tab button icon when the layout is icon-left +$tabs-md-tab-icon-left-transform-x-active: -2px !default; + +/// @prop - Transform y for the active tab button icon when the layout is icon-left +$tabs-md-tab-icon-left-transform-y-active: 0 !default; + +/// @prop - Transform z for the active tab button icon when the layout is icon-left +$tabs-md-tab-icon-left-transform-z-active: 0 !default; + +// deprecated +$tabs-md-tab-icon-transform-origin: null !default; + +/// @prop - Transform origin x for the tab button text +$tabs-md-tab-icon-transform-origin-x: 50% !default; + +/// @prop - Transform origin y for the tab button text +$tabs-md-tab-icon-transform-origin-y: 150% !default; /// @prop - Text transition for the tab button icon $tabs-md-tab-icon-transition: transform .3s ease-in-out !default; @@ -148,12 +192,15 @@ $tabs-md-tab-icon-size: 2.4rem !default; font-size: $tabs-md-tab-font-size; text-transform: $tabs-md-tab-text-capitalization; - transform-origin: $tabs-md-tab-text-transform-origin; transition: $tabs-md-tab-text-transition; @include deprecated-variable(margin, $tabs-md-tab-text-margin) { @include margin($tabs-md-tab-text-margin-top, $tabs-md-tab-text-margin-end, $tabs-md-tab-text-margin-bottom, $tabs-md-tab-text-margin-start); } + + @include deprecated-variable(transform-origin, $tabs-md-tab-text-transform-origin) { + @include transform-origin($tabs-md-tab-text-transform-origin-x, $tabs-md-tab-text-transform-origin-y); + } } .tabs-md .tab-button[aria-selected=true] .tab-button-text { @@ -182,32 +229,43 @@ $tabs-md-tab-icon-size: 2.4rem !default; color: $tabs-md-tab-icon-color; - transform-origin: $tabs-md-tab-icon-transform-origin; transition: $tabs-md-tab-icon-transition; + + @include deprecated-variable(transform-origin, $tabs-md-tab-icon-transform-origin) { + @include transform-origin($tabs-md-tab-icon-transform-origin-x, $tabs-md-tab-icon-transform-origin-y); + } } // Tab layout: icon-top, icon-only, title-only .tabs-md .tab-button[aria-selected=true] .tab-button-icon { color: $tabs-md-tab-icon-color-active; - transform: $tabs-md-tab-icon-transform-active; + @include deprecated-variable(transform, $tabs-md-tab-icon-transform-active) { + @include transform(translate3d($tabs-md-tab-icon-transform-x-active, $tabs-md-tab-icon-transform-y-active, $tabs-md-tab-icon-transform-z-active)); + } } // Tab layout: icon-end .tabs-md[tabsLayout=icon-right] .tab-button[aria-selected=true] .tab-button-icon, // deprecated .tabs-md[tabsLayout=icon-end] .tab-button[aria-selected=true] .tab-button-icon { - transform: $tabs-md-tab-icon-end-transform-active; + @include deprecated-variable(transform, $tabs-md-tab-icon-end-transform-active) { + @include transform(translate3d($tabs-md-tab-icon-right-transform-x-active, $tabs-md-tab-icon-right-transform-y-active, $tabs-md-tab-icon-right-transform-z-active)); + } } // Tab layout: icon-bottom .tabs-md[tabsLayout=icon-bottom] .tab-button[aria-selected=true] .tab-button-icon { - transform: $tabs-md-tab-icon-bottom-transform-active; + @include deprecated-variable(transform, $tabs-md-tab-icon-bottom-transform-active) { + @include transform(translate3d($tabs-md-tab-icon-bottom-transform-x-active, $tabs-md-tab-icon-bottom-transform-y-active, $tabs-md-tab-icon-bottom-transform-z-active)); + } } // Tab layout: icon-start .tabs-md[tabsLayout=icon-left] .tab-button[aria-selected=true] .tab-button-icon, // deprecated .tabs-md[tabsLayout=icon-start] .tab-button[aria-selected=true] .tab-button-icon { - transform: $tabs-md-tab-icon-start-transform-active; + @include deprecated-variable(transform, $tabs-md-tab-icon-start-transform-active) { + @include transform(translate3d($tabs-md-tab-icon-left-transform-x-active, $tabs-md-tab-icon-left-transform-y-active, $tabs-md-tab-icon-left-transform-z-active)); + } } @@ -227,6 +285,7 @@ $tabs-md-tab-icon-size: 2.4rem !default; .tabs-md[tabsHighlight=true] .tab-highlight { @include position(null, null, 0, 0); + @include transform-origin(0, 0); position: absolute; @@ -237,7 +296,6 @@ $tabs-md-tab-icon-size: 2.4rem !default; background: $tabs-md-tab-color-active; transform: translateZ(0); - transform-origin: 0 0; } .tabs-md[tabsHighlight=true] .tab-highlight.animate { diff --git a/src/components/toast/toast.ios.scss b/src/components/toast/toast.ios.scss index 73ebad6873..75cc1c6e5c 100644 --- a/src/components/toast/toast.ios.scss +++ b/src/components/toast/toast.ios.scss @@ -47,15 +47,15 @@ $toast-ios-title-padding-start: $toast-ios-title-padding-end ! } .toast-ios .toast-wrapper.toast-top { - top: 0; + @include transform(translate3d(0, -100%, 0)); - transform: translate3d(0, -100%, 0); + top: 0; } .toast-ios .toast-wrapper.toast-bottom { - bottom: 0; + @include transform(translate3d(0, 100%, 0)); - transform: translate3d(0, 100%, 0); + bottom: 0; } .toast-ios .toast-wrapper.toast-middle { diff --git a/src/components/toast/toast.md.scss b/src/components/toast/toast.md.scss index 34ebe45ea0..98de4edebf 100644 --- a/src/components/toast/toast.md.scss +++ b/src/components/toast/toast.md.scss @@ -44,15 +44,15 @@ $toast-md-title-padding-start: $toast-md-title-padding-end !de } .toast-md .toast-wrapper.toast-top { - top: 0; + @include transform(translate3d(0, -100%, 0)); - transform: translate3d(0, -100%, 0); + top: 0; } .toast-md .toast-wrapper.toast-bottom { - bottom: 0; + @include transform(translate3d(0, 100%, 0)); - transform: translate3d(0, 100%, 0); + bottom: 0; } .toast-md .toast-wrapper.toast-middle { diff --git a/src/components/toggle/toggle.ios.scss b/src/components/toggle/toggle.ios.scss index e798411bf7..424281bb5e 100644 --- a/src/components/toggle/toggle.ios.scss +++ b/src/components/toggle/toggle.ios.scss @@ -172,8 +172,7 @@ $toggle-ios-item-end-padding-start: $item-ios-padding-start !default; // ----------------------------------------- .toggle-ios.toggle-checked .toggle-inner { - transform: translate3d($toggle-ios-width - $toggle-ios-handle-width - ($toggle-ios-border-width * 2), 0, 0); - + @include transform(translate3d($toggle-ios-width - $toggle-ios-handle-width - ($toggle-ios-border-width * 2), 0, 0)); } diff --git a/src/components/toggle/toggle.md.scss b/src/components/toggle/toggle.md.scss index f070514eab..54a6327b00 100644 --- a/src/components/toggle/toggle.md.scss +++ b/src/components/toggle/toggle.md.scss @@ -178,8 +178,9 @@ $toggle-md-item-end-padding-start: $item-md-padding-start !default; // ----------------------------------------- .toggle-md.toggle-checked .toggle-inner { + @include transform(translate3d($toggle-md-track-width - $toggle-md-handle-width, 0, 0)); + background-color: $toggle-md-handle-background-color-on; - transform: translate3d($toggle-md-track-width - $toggle-md-handle-width, 0, 0); } diff --git a/src/components/toggle/toggle.wp.scss b/src/components/toggle/toggle.wp.scss index 155acc4a83..c44565cbe3 100644 --- a/src/components/toggle/toggle.wp.scss +++ b/src/components/toggle/toggle.wp.scss @@ -160,8 +160,9 @@ $toggle-wp-item-end-padding-start: $item-wp-padding-start !default; // ----------------------------------------- .toggle-wp.toggle-checked .toggle-inner { + @include transform(translate3d($toggle-wp-track-width - $toggle-wp-handle-width - ($toggle-wp-track-border-width * 2) - ($toggle-wp-handle-left * 2), 0, 0)); + background-color: $toggle-wp-handle-background-color-on; - transform: translate3d($toggle-wp-track-width - $toggle-wp-handle-width - ($toggle-wp-track-border-width * 2) - ($toggle-wp-handle-left * 2), 0, 0); } diff --git a/src/themes/ionic.functions.scss b/src/themes/ionic.functions.scss index 6a079fb737..347c2f67c5 100644 --- a/src/themes/ionic.functions.scss +++ b/src/themes/ionic.functions.scss @@ -133,6 +133,32 @@ } +// String Split Function +// -------------------------------------------------- + +@function str-split($string, $separator) { + // empty array/list + $split-arr: (); + // first index of separator in string + $index: str-index($string, $separator); + // loop through string + @while $index != null { + // get the substring from the first character to the separator + $item: str-slice($string, 1, $index - 1); + // push item to array + $split-arr: append($split-arr, $item); + // remove item and separator from string + $string: str-slice($string, $index + 1); + // find new index of separator + $index: str-index($string, $separator); + } + // add the remaining string to list (the last item) + $split-arr: append($split-arr, $string); + + @return $split-arr; +} + + // URL Encode Function // -------------------------------------------------- diff --git a/src/themes/ionic.mixins.scss b/src/themes/ionic.mixins.scss index 186de6aa71..1856981354 100644 --- a/src/themes/ionic.mixins.scss +++ b/src/themes/ionic.mixins.scss @@ -446,4 +446,79 @@ background-position: $horizontal $horizontal-amount $vertical $vertical-amount; } } -} \ No newline at end of file +} + +@mixin transform-origin($x-axis, $y-axis: null) { + @if $x-axis == start { + @include ltr() { + transform-origin: left $y-axis; + } + @include rtl() { + transform-origin: right $y-axis; + } + } @else if $x-axis == end { + @include ltr() { + transform-origin: right $y-axis; + } + @include rtl() { + transform-origin: left $y-axis; + } + } @else if $x-axis == left or $x-axis == right { + @include multi-dir() { + transform-origin: $x-axis $y-axis; + } + } @else { + @include ltr() { + transform-origin: $x-axis $y-axis; + } + @include rtl() { + transform-origin: calc(100% - #{$x-axis}) $y-axis; + } + } +} + +// Add transform for all directions +// @param {string} $transforms - comma separated list of transforms +@mixin transform($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($x, $y, $z); + $rtl-translate: translate3d(calc(-1 * #{$x}), $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; + } + } +} diff --git a/src/themes/util.scss b/src/themes/util.scss index c0a79391d9..dcd542b894 100755 --- a/src/themes/util.scss +++ b/src/themes/util.scss @@ -53,6 +53,7 @@ ion-input :focus { .click-block-enabled { @include position(0, 0, 0, 0); + @include transform(translate3d(0, -100%, 0), translateY(1px)); position: absolute; @@ -60,7 +61,6 @@ ion-input :focus { display: block; opacity: 0; - transform: translate3d(0, -100%, 0) translateY(1px); // background: red; // opacity: .3; @@ -68,5 +68,5 @@ ion-input :focus { } .click-block-active { - transform: translate3d(0, 0, 0); + @include transform(translate3d(0, 0, 0)); }