From 3d34cb3594e148817d3a098575349e136deda76b Mon Sep 17 00:00:00 2001 From: crisbeto Date: Thu, 4 Jul 2019 22:44:52 +0200 Subject: [PATCH] feat(snackbar): add feature targeting for styles Adds support for feature targeting to the `mdc-snackbar` styles. Relates to #4227. --- packages/mdc-snackbar/_mixins.scss | 250 +++++++++++++++++++++--- packages/mdc-snackbar/mdc-snackbar.scss | 130 +----------- test/scss/_feature-targeting-test.scss | 15 ++ 3 files changed, 239 insertions(+), 156 deletions(-) diff --git a/packages/mdc-snackbar/_mixins.scss b/packages/mdc-snackbar/_mixins.scss index 55c8f91ffbc..a0bf74cf03d 100644 --- a/packages/mdc-snackbar/_mixins.scss +++ b/packages/mdc-snackbar/_mixins.scss @@ -20,73 +20,269 @@ // THE SOFTWARE. // +@import "@material/feature-targeting/functions"; +@import "@material/feature-targeting/mixins"; +@import "@material/animation/functions"; +@import "@material/button/mixins"; +@import "@material/icon-button/mixins"; +@import "@material/ripple/mixins"; +@import "@material/rtl/mixins"; +@import "@material/typography/mixins"; @import "@material/elevation/mixins"; @import "@material/shape/mixins"; @import "@material/theme/mixins"; @import "./variables"; -@mixin mdc-snackbar-fill-color($color) { +@mixin mdc-snackbar-core-styles($query: mdc-feature-all()) { + $feat-structure: mdc-feature-create-target($query, structure); + $feat-animation: mdc-feature-create-target($query, animation); + + // postcss-bem-linter: define snackbar + .mdc-snackbar { + @include mdc-snackbar-z-index($mdc-snackbar-z-index, $query); + @include mdc-snackbar-viewport-margin($mdc-snackbar-viewport-margin-narrow, $query); + + @include mdc-feature-targets($feat-structure) { + display: none; + position: fixed; + right: 0; + bottom: 0; + left: 0; + align-items: center; + justify-content: center; + box-sizing: border-box; + + // Ignore mouse events on the root layout element. + pointer-events: none; + + // For some reason, iOS Safari displays a tap highlight on the entire snackbar element. + // Mobile Safari only supports `rgba` values for this property; named values like + // `transparent` are ignored. From Apple's docs: + // > This property obeys the alpha value, if specified. + // > If you don’t specify an alpha value, Safari on iOS applies a default alpha value to the color. + // > To disable tap highlighting, set the alpha value to 0 (invisible). + // > If you set the alpha value to 1.0 (opaque), the element is not visible when tapped. + // See https://github.com/ben-eb/postcss-colormin/issues/1 + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); + } + } + + @at-root { + @include mdc-snackbar-fill-color($mdc-snackbar-fill-color, $query); + @include mdc-snackbar-label-ink-color($mdc-snackbar-label-ink-color, $query); + @include mdc-snackbar-min-width($mdc-snackbar-min-width, $query: $query); + @include mdc-snackbar-max-width($mdc-snackbar-max-width, $query: $query); + @include mdc-snackbar-elevation($mdc-snackbar-elevation, $query: $query); + @include mdc-snackbar-shape-radius($mdc-snackbar-shape-radius, $query: $query); + } + + .mdc-snackbar--opening, + .mdc-snackbar--open, + .mdc-snackbar--closing { + @include mdc-feature-targets($feat-structure) { + display: flex; + } + } + + .mdc-snackbar--leading { + @include mdc-snackbar-position-leading($query); + } + + .mdc-snackbar--stacked { + @include mdc-snackbar-layout-stacked($query); + } + + .mdc-snackbar__surface { + @include mdc-feature-targets($feat-structure) { + display: flex; + align-items: center; + justify-content: flex-start; + box-sizing: border-box; + transform: scale(.8); + opacity: 0; + } + + .mdc-snackbar--open & { + @include mdc-feature-targets($feat-structure) { + transform: scale(1); + opacity: 1; + pointer-events: auto; // Allow mouse events on surface element while snackbar is open + } + + @include mdc-feature-targets($feat-animation) { + transition: + mdc-animation-enter(opacity, $mdc-snackbar-enter-duration), + mdc-animation-enter(transform, $mdc-snackbar-enter-duration); + } + } + + .mdc-snackbar--closing & { + @include mdc-feature-targets($feat-structure) { + transform: scale(1); + } + + @include mdc-feature-targets($feat-animation) { + transition: mdc-animation-exit-permanent(opacity, $mdc-snackbar-exit-duration); + } + } + } + + .mdc-snackbar__label { + @include mdc-typography($mdc-snackbar-label-type-scale, $query: $query); + + @include mdc-feature-targets($feat-structure) { + flex-grow: 1; + box-sizing: border-box; + margin: 0; + + // 14px top/bottom padding needed to make the height 48px. + padding: 14px 16px; + } + } + + // Used to prevent visual jank when announcing label text to screen readers. + // See the `announce()` function in util.js for details. + .mdc-snackbar__label::before { + @include mdc-feature-targets($feat-structure) { + display: inline; + content: attr(data-mdc-snackbar-label-text); + } + } + + .mdc-snackbar__actions { + @include mdc-feature-targets($feat-structure) { + @include mdc-rtl-reflexive-property(margin, 0, $mdc-snackbar-padding); + + display: flex; + flex-shrink: 0; + align-items: center; + box-sizing: border-box; + } + } + + .mdc-snackbar__action { + @include mdc-button-ink-color($mdc-snackbar-action-ink-color, $query: $query); + @include mdc-states($mdc-snackbar-action-ink-color, $query: $query); + } + + .mdc-snackbar__dismiss { + @include mdc-icon-button-ink-color($mdc-snackbar-dismiss-ink-color, $query: $query); + } + + // Two selectors are needed to increase specificity above `.material-icons`. + // stylelint-disable-next-line selector-class-pattern + .mdc-snackbar__dismiss.mdc-snackbar__dismiss { + @include mdc-icon-button-size($mdc-snackbar-dismiss-icon-size, $query: $query); + } + + .mdc-snackbar__action + .mdc-snackbar__dismiss { + @include mdc-feature-targets($feat-structure) { + @include mdc-rtl-reflexive-property(margin, $mdc-snackbar-padding, 0); + } + } + // postcss-bem-linter: end +} + +@mixin mdc-snackbar-fill-color($color, $query: mdc-feature-all()) { + $feat-color: mdc-feature-create-target($query, color); + .mdc-snackbar__surface { - @include mdc-theme-prop(background-color, $color); + @include mdc-feature-targets($feat-color) { + @include mdc-theme-prop(background-color, $color); + } } } -@mixin mdc-snackbar-label-ink-color($color) { +@mixin mdc-snackbar-label-ink-color($color, $query: mdc-feature-all()) { + $feat-color: mdc-feature-create-target($query, color); + .mdc-snackbar__label { - @include mdc-theme-prop(color, $color); + @include mdc-feature-targets($feat-color) { + @include mdc-theme-prop(color, $color); + } } } -@mixin mdc-snackbar-shape-radius($radius, $rtl-reflexive: false) { +@mixin mdc-snackbar-shape-radius($radius, $rtl-reflexive: false, $query: mdc-feature-all()) { .mdc-snackbar__surface { - @include mdc-shape-radius($radius, $rtl-reflexive); + @include mdc-shape-radius($radius, $rtl-reflexive, $query: $query); } } -@mixin mdc-snackbar-min-width($min-width, $mobile-breakpoint: $mdc-snackbar-mobile-breakpoint) { +@mixin mdc-snackbar-min-width( + $min-width, + $mobile-breakpoint: $mdc-snackbar-mobile-breakpoint, + $query: mdc-feature-all() +) { + $feat-structure: mdc-feature-create-target($query, structure); + .mdc-snackbar__surface { - min-width: $min-width; + @include mdc-feature-targets($feat-structure) { + min-width: $min-width; - // The first media query ensures that snackbars are always 100% width on mobile devices, as required by the spec. - // The second media query prevents snackbars from being wider than the viewport for large min-width values. - @media (max-width: $mobile-breakpoint), (max-width: $min-width) { - min-width: 100%; + // The first media query ensures that snackbars are always 100% width on mobile devices, as required by the spec. + // The second media query prevents snackbars from being wider than the viewport for large min-width values. + @media (max-width: $mobile-breakpoint), (max-width: $min-width) { + min-width: 100%; + } } } } -@mixin mdc-snackbar-max-width($max-width) { +@mixin mdc-snackbar-max-width($max-width, $query: mdc-feature-all()) { + $feat-structure: mdc-feature-create-target($query, structure); + .mdc-snackbar__surface { - max-width: $max-width; + @include mdc-feature-targets($feat-structure) { + max-width: $max-width; + } } } -@mixin mdc-snackbar-elevation($z-index) { +@mixin mdc-snackbar-elevation($z-index, $query: mdc-feature-all()) { .mdc-snackbar__surface { - @include mdc-elevation($z-index); + @include mdc-elevation($z-index, $query: $query); } } -@mixin mdc-snackbar-viewport-margin($margin) { - margin: $margin; +@mixin mdc-snackbar-viewport-margin($margin, $query: mdc-feature-all()) { + $feat-structure: mdc-feature-create-target($query, structure); + + @include mdc-feature-targets($feat-structure) { + margin: $margin; + } } -@mixin mdc-snackbar-z-index($z-index) { - z-index: $z-index; +@mixin mdc-snackbar-z-index($z-index, $query: mdc-feature-all()) { + $feat-structure: mdc-feature-create-target($query, structure); + + @include mdc-feature-targets($feat-structure) { + z-index: $z-index; + } } -@mixin mdc-snackbar-position-leading { - justify-content: flex-start; +@mixin mdc-snackbar-position-leading($query: mdc-feature-all()) { + $feat-structure: mdc-feature-create-target($query, structure); + + @include mdc-feature-targets($feat-structure) { + justify-content: flex-start; + } } -@mixin mdc-snackbar-layout-stacked { +@mixin mdc-snackbar-layout-stacked($query: mdc-feature-all()) { + $feat-structure: mdc-feature-create-target($query, structure); + .mdc-snackbar__surface { - flex-direction: column; - align-items: flex-start; + @include mdc-feature-targets($feat-structure) { + flex-direction: column; + align-items: flex-start; + } } .mdc-snackbar__actions { - align-self: flex-end; - margin-bottom: $mdc-snackbar-padding; + @include mdc-feature-targets($feat-structure) { + align-self: flex-end; + margin-bottom: $mdc-snackbar-padding; + } } } diff --git a/packages/mdc-snackbar/mdc-snackbar.scss b/packages/mdc-snackbar/mdc-snackbar.scss index 8c86996da3c..c04f2505475 100644 --- a/packages/mdc-snackbar/mdc-snackbar.scss +++ b/packages/mdc-snackbar/mdc-snackbar.scss @@ -20,133 +20,5 @@ // THE SOFTWARE. // -@import "@material/animation/functions"; -@import "@material/button/mixins"; -@import "@material/icon-button/mixins"; -@import "@material/ripple/mixins"; -@import "@material/rtl/mixins"; -@import "@material/typography/mixins"; @import "./mixins"; -@import "./variables"; - -// postcss-bem-linter: define snackbar -.mdc-snackbar { - @include mdc-snackbar-z-index($mdc-snackbar-z-index); - @include mdc-snackbar-viewport-margin($mdc-snackbar-viewport-margin-narrow); - - display: none; - position: fixed; - right: 0; - bottom: 0; - left: 0; - align-items: center; - justify-content: center; - box-sizing: border-box; - - // Ignore mouse events on the root layout element. - pointer-events: none; - - // For some reason, iOS Safari displays a tap highlight on the entire snackbar element. - // Mobile Safari only supports `rgba` values for this property; named values like `transparent` are ignored. - // From Apple's docs: - // > This property obeys the alpha value, if specified. - // > If you don’t specify an alpha value, Safari on iOS applies a default alpha value to the color. - // > To disable tap highlighting, set the alpha value to 0 (invisible). - // > If you set the alpha value to 1.0 (opaque), the element is not visible when tapped. - // See https://github.com/ben-eb/postcss-colormin/issues/1 - -webkit-tap-highlight-color: rgba(0, 0, 0, 0); -} - -@at-root { - @include mdc-snackbar-fill-color($mdc-snackbar-fill-color); - @include mdc-snackbar-label-ink-color($mdc-snackbar-label-ink-color); - @include mdc-snackbar-min-width($mdc-snackbar-min-width); - @include mdc-snackbar-max-width($mdc-snackbar-max-width); - @include mdc-snackbar-elevation($mdc-snackbar-elevation); - @include mdc-snackbar-shape-radius($mdc-snackbar-shape-radius); -} - -.mdc-snackbar--opening, -.mdc-snackbar--open, -.mdc-snackbar--closing { - display: flex; -} - -.mdc-snackbar--leading { - @include mdc-snackbar-position-leading; -} - -.mdc-snackbar--stacked { - @include mdc-snackbar-layout-stacked; -} - -.mdc-snackbar__surface { - display: flex; - align-items: center; - justify-content: flex-start; - box-sizing: border-box; - transform: scale(.8); - opacity: 0; - - .mdc-snackbar--open & { - transform: scale(1); - transition: - mdc-animation-enter(opacity, $mdc-snackbar-enter-duration), - mdc-animation-enter(transform, $mdc-snackbar-enter-duration); - opacity: 1; - pointer-events: auto; // Allow mouse events on surface element while snackbar is open - } - - .mdc-snackbar--closing & { - transform: scale(1); - transition: mdc-animation-exit-permanent(opacity, $mdc-snackbar-exit-duration); - } -} - -.mdc-snackbar__label { - @include mdc-typography($mdc-snackbar-label-type-scale); - - flex-grow: 1; - box-sizing: border-box; - margin: 0; - - // 14px top/bottom padding needed to make the height 48px. - padding: 14px 16px; -} - -// Used to prevent visual jank when announcing label text to screen readers. -// See the `announce()` function in util.js for details. -.mdc-snackbar__label::before { - display: inline; - content: attr(data-mdc-snackbar-label-text); -} - -.mdc-snackbar__actions { - @include mdc-rtl-reflexive-property(margin, 0, $mdc-snackbar-padding); - - display: flex; - flex-shrink: 0; - align-items: center; - box-sizing: border-box; -} - -.mdc-snackbar__action { - @include mdc-button-ink-color($mdc-snackbar-action-ink-color); - @include mdc-states($mdc-snackbar-action-ink-color); -} - -.mdc-snackbar__dismiss { - @include mdc-icon-button-ink-color($mdc-snackbar-dismiss-ink-color); -} - -// Two selectors are needed to increase specificity above `.material-icons`. -// stylelint-disable-next-line selector-class-pattern -.mdc-snackbar__dismiss.mdc-snackbar__dismiss { - @include mdc-icon-button-size($mdc-snackbar-dismiss-icon-size); -} - -.mdc-snackbar__action + .mdc-snackbar__dismiss { - @include mdc-rtl-reflexive-property(margin, $mdc-snackbar-padding, 0); -} - -// postcss-bem-linter: end +@include mdc-snackbar-core-styles; diff --git a/test/scss/_feature-targeting-test.scss b/test/scss/_feature-targeting-test.scss index 3642a2b0d4b..a695a238eee 100644 --- a/test/scss/_feature-targeting-test.scss +++ b/test/scss/_feature-targeting-test.scss @@ -15,6 +15,7 @@ @import "@material/radio/mixins"; @import "@material/ripple/mixins"; @import "@material/shape/mixins"; +@import "@material/snackbar/mixins"; @import "@material/switch/mixins"; @import "@material/tab-bar/mixins"; @import "@material/tab-scroller/mixins"; @@ -180,6 +181,20 @@ // Shape @include mdc-shape-radius(1px 2px, true, $query: $query); + + // Snackbar + @include mdc-snackbar-core-styles($query: $query); + @include mdc-snackbar-fill-color(red, $query: $query); + @include mdc-snackbar-label-ink-color(red, $query: $query); + @include mdc-snackbar-shape-radius(1337, $query: $query); + @include mdc-snackbar-min-width(1337, $query: $query); + @include mdc-snackbar-max-width(1337, $query: $query); + @include mdc-snackbar-elevation(13, $query: $query); + @include mdc-snackbar-viewport-margin(1337, $query: $query); + @include mdc-snackbar-z-index(1337, $query: $query); + @include mdc-snackbar-position-leading($query: $query); + @include mdc-snackbar-layout-stacked($query: $query); + // Switch @include mdc-switch-core-styles($query: $query); @include mdc-switch-toggled-on-color(on-surface, $query: $query);