Skip to content

Commit f6643c9

Browse files
committed
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.
1 parent 149669e commit f6643c9

File tree

1 file changed

+40
-12
lines changed

1 file changed

+40
-12
lines changed

src/cdk/a11y/_a11y.scss

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,29 +18,57 @@
1818
}
1919
}
2020

21-
// Applies styles for users in high contrast mode. Note that this only applies
22-
// to Microsoft browsers. Chrome can be included by checking for the `html[hc]`
23-
// attribute, however Chrome handles high contrast differently.
24-
//
25-
// @param target Which kind of high contrast setting to target. Defaults to `active`, can be
26-
// `white-on-black` or `black-on-white`.
27-
@mixin cdk-high-contrast($target: active) {
21+
/// Emits the mixin's content nested under `$selector-context` if `$selector-context`
22+
/// is non-empty.
23+
/// @param selector-context The selector under which to nest the mixin's content.
24+
@mixin _cdk-optionally-nest-content($selector-context) {
25+
@if ($selector-context == '') {
26+
@content;
27+
} @else {
28+
#{$selector-context} {
29+
@content;
30+
}
31+
}
32+
}
33+
34+
/// Applies styles for users in high contrast mode. Note that this only applies
35+
/// to Microsoft browsers. Chrome can be included by checking for the `html[hc]`
36+
/// attribute, however Chrome handles high contrast differently.
37+
///
38+
/// @param target Which kind of high contrast setting to target. Defaults to `active`, can be
39+
/// `white-on-black` or `black-on-white`.
40+
/// @param encapsulation Whether to emit styles for view encapsulation. Values are:
41+
/// * `on` - works for `Emulated`, `Native`, and `ShadowDom`
42+
/// * `off` - works for `None`
43+
/// * `both` - works for all encapsulation modes by emitting the CSS twice (default).
44+
@mixin cdk-high-contrast($target: active, $encapsulation: 'both') {
2845
@if ($target != 'active' and $target != 'black-on-white' and $target != 'white-on-black') {
2946
@error 'Unknown cdk-high-contrast value "#{$target}" provided. ' +
3047
'Allowed values are "active", "black-on-white", and "white-on-black"';
3148
}
3249

50+
@if ($encapsulation != 'on' and $encapsulation != 'off' and $encapsulation != 'both') {
51+
@error 'Unknown cdk-high-contrast encapsulation "#{$encapsulation}" provided. ' +
52+
'Allowed values are "on", "off", and "both"';
53+
}
54+
3355
// If the selector context has multiple parts, such as `.section, .region`, just doing
3456
// `.cdk-high-contrast-xxx #{&}` will only apply the parent selector to the first part of the
3557
// context. We address this by nesting the selector context under .cdk-high-contrast.
3658
@at-root {
3759
$selector-context: #{&};
38-
.cdk-high-contrast-#{$target} {
39-
@if ($selector-context == '') {
40-
@content;
60+
61+
@if ($encapsulation != 'on') {
62+
.cdk-high-contrast-#{$target} {
63+
@include _cdk-optionally-nest-content($selector-context) {
64+
@content;
65+
}
4166
}
42-
@else {
43-
#{$selector-context} {
67+
}
68+
69+
@if ($encapsulation != 'off') {
70+
.cdk-high-contrast-#{$target} :host {
71+
@include _cdk-optionally-nest-content($selector-context) {
4472
@content;
4573
}
4674
}

0 commit comments

Comments
 (0)