Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
fix(cdk/a11y): make cdk-high-contrast work w/ emulated view encapsula…
…tion (#18152)

* 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.

(cherry picked from commit ea17135)
  • Loading branch information
jelbourn committed Jan 29, 2020
1 parent 2b83a0a commit aff21e8
Showing 1 changed file with 41 additions and 12 deletions.
53 changes: 41 additions & 12 deletions src/cdk/a11y/_a11y.scss
Expand Up @@ -18,29 +18,58 @@
}
}

// 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`
/// * `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"';
}

@if ($encapsulation != 'on' and $encapsulation != 'off' and $encapsulation != 'any') {
@error 'Unknown cdk-high-contrast encapsulation "#{$encapsulation}" provided. ' +
'Allowed values are "on", "off", and "any"';
}

// 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;
}
}
Expand Down

0 comments on commit aff21e8

Please sign in to comment.