From e226409606836e7c8c20b299b414abb83fc566cd Mon Sep 17 00:00:00 2001 From: Jeremy Elbourn Date: Fri, 10 Jan 2020 15:32:28 -0800 Subject: [PATCH 1/3] fix(cdk/a11y): make cdk-high-contrast work w/ emulated view encapsulation Say you have this in your component: ```scss .some-element { @include cdk-high-contrast() { border: 1px solid white; } } ``` With this change, this will output: ```scss .cdk-high-contrast-active .some-element, .cdk-high-contrast-active :host .some-element { border: 1px solid white; } ``` Here, `.cdk-high-contrast-active .some-element` will apply in places where encapsulation is turned off, and `.cdk-high-contrast-active :host .some-element` will apply in cases where encapsulation is emulated. Neither will work in Shadow DOM (which we don't officially support). AFAIK, Shadow DOM would need to use `:host-content()`, which we could consider adding if we get an additional request. This adds a few more bytes, but high-contrast styles tend to be pretty limited. --- src/cdk/a11y/_a11y.scss | 52 +++++++++++++++++++++++++++++++---------- 1 file changed, 40 insertions(+), 12 deletions(-) diff --git a/src/cdk/a11y/_a11y.scss b/src/cdk/a11y/_a11y.scss index c2d5638923a4..5d5d55a958ba 100644 --- a/src/cdk/a11y/_a11y.scss +++ b/src/cdk/a11y/_a11y.scss @@ -18,29 +18,57 @@ } } -// Applies styles for users in high contrast mode. Note that this only applies -// to Microsoft browsers. Chrome can be included by checking for the `html[hc]` -// attribute, however Chrome handles high contrast differently. -// -// @param target Which kind of high contrast setting to target. Defaults to `active`, can be -// `white-on-black` or `black-on-white`. -@mixin cdk-high-contrast($target: active) { +/// Emits the mixin's content nested under `$selector-context` if `$selector-context` +/// is non-empty. +/// @param selector-context The selector under which to nest the mixin's content. +@mixin _cdk-optionally-nest-content($selector-context) { + @if ($selector-context == '') { + @content; + } @else { + #{$selector-context} { + @content; + } + } +} + +/// Applies styles for users in high contrast mode. Note that this only applies +/// to Microsoft browsers. Chrome can be included by checking for the `html[hc]` +/// attribute, however Chrome handles high contrast differently. +/// +/// @param target Which kind of high contrast setting to target. Defaults to `active`, can be +/// `white-on-black` or `black-on-white`. +/// @param encapsulation Whether to emit styles for view encapsulation. Values are: +/// * `on` - works for `Emulated`, `Native`, and `ShadowDom` +/// * `off` - works for `None` +/// * `both` - works for all encapsulation modes by emitting the CSS twice (default). +@mixin cdk-high-contrast($target: active, $encapsulation: 'both') { @if ($target != 'active' and $target != 'black-on-white' and $target != 'white-on-black') { @error 'Unknown cdk-high-contrast value "#{$target}" provided. ' + 'Allowed values are "active", "black-on-white", and "white-on-black"'; } + @if ($encapsulation != 'on' and $encapsulation != 'off' and $encapsulation != 'both') { + @error 'Unknown cdk-high-contrast encapsulation "#{$encapsulation}" provided. ' + + 'Allowed values are "on", "off", and "both"'; + } + // If the selector context has multiple parts, such as `.section, .region`, just doing // `.cdk-high-contrast-xxx #{&}` will only apply the parent selector to the first part of the // context. We address this by nesting the selector context under .cdk-high-contrast. @at-root { $selector-context: #{&}; - .cdk-high-contrast-#{$target} { - @if ($selector-context == '') { - @content; + + @if ($encapsulation != 'on') { + .cdk-high-contrast-#{$target} { + @include _cdk-optionally-nest-content($selector-context) { + @content; + } } - @else { - #{$selector-context} { + } + + @if ($encapsulation != 'off') { + .cdk-high-contrast-#{$target} :host { + @include _cdk-optionally-nest-content($selector-context) { @content; } } From 5d540028c297bad7a6242131fafdb6909e281163 Mon Sep 17 00:00:00 2001 From: Jeremy Elbourn Date: Thu, 16 Jan 2020 14:31:22 -0800 Subject: [PATCH 2/3] address comments --- src/cdk/a11y/_a11y.scss | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/cdk/a11y/_a11y.scss b/src/cdk/a11y/_a11y.scss index 5d5d55a958ba..f32fe5d61b57 100644 --- a/src/cdk/a11y/_a11y.scss +++ b/src/cdk/a11y/_a11y.scss @@ -24,7 +24,8 @@ @mixin _cdk-optionally-nest-content($selector-context) { @if ($selector-context == '') { @content; - } @else { + } + @else { #{$selector-context} { @content; } @@ -40,8 +41,8 @@ /// @param encapsulation Whether to emit styles for view encapsulation. Values are: /// * `on` - works for `Emulated`, `Native`, and `ShadowDom` /// * `off` - works for `None` -/// * `both` - works for all encapsulation modes by emitting the CSS twice (default). -@mixin cdk-high-contrast($target: active, $encapsulation: 'both') { +/// * `any` - works for all encapsulation modes by emitting the CSS twice (default). +@mixin cdk-high-contrast($target: active, $encapsulation: 'any') { @if ($target != 'active' and $target != 'black-on-white' and $target != 'white-on-black') { @error 'Unknown cdk-high-contrast value "#{$target}" provided. ' + 'Allowed values are "active", "black-on-white", and "white-on-black"'; From 3768db6fad607a9025eb444c982cc501e0d796a3 Mon Sep 17 00:00:00 2001 From: Jeremy Elbourn Date: Thu, 16 Jan 2020 15:24:49 -0800 Subject: [PATCH 3/3] Change "both" to "any" --- src/cdk/a11y/_a11y.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cdk/a11y/_a11y.scss b/src/cdk/a11y/_a11y.scss index f32fe5d61b57..0b2d77c17b0d 100644 --- a/src/cdk/a11y/_a11y.scss +++ b/src/cdk/a11y/_a11y.scss @@ -48,9 +48,9 @@ 'Allowed values are "active", "black-on-white", and "white-on-black"'; } - @if ($encapsulation != 'on' and $encapsulation != 'off' and $encapsulation != 'both') { + @if ($encapsulation != 'on' and $encapsulation != 'off' and $encapsulation != 'any') { @error 'Unknown cdk-high-contrast encapsulation "#{$encapsulation}" provided. ' + - 'Allowed values are "on", "off", and "both"'; + 'Allowed values are "on", "off", and "any"'; } // If the selector context has multiple parts, such as `.section, .region`, just doing