|
2 | 2 | @use 'sass:map'; |
3 | 3 | @use 'sass:meta'; |
4 | 4 | @use 'sass:string'; |
| 5 | +@use 'sass:color'; |
| 6 | +@use 'sass:math'; |
5 | 7 | @use '@material/tokens/v0_161' as mdc-tokens; |
6 | 8 | @use '../style/elevation'; |
7 | 9 | @use '../style/sass-utils'; |
@@ -367,6 +369,66 @@ $_component-prefix: null; |
367 | 369 | @return $result; |
368 | 370 | } |
369 | 371 |
|
| 372 | +/// Inherited function from MDC that computes which contrast tone to use on top of a color. |
| 373 | +/// This is used only in a narrow set of use cases when generating M2 button tokens to maintain |
| 374 | +/// backwards compatibility. |
| 375 | +/// @param {Color} $value Color for which we're calculating the contrast tone. |
| 376 | +/// @param {Boolean} $is-dark Whether the current theme is dark. |
| 377 | +/// @return {Map} Either `dark` or `light`. |
| 378 | +@function contrast-tone($value, $is-dark) { |
| 379 | + @if ($value == 'dark') { |
| 380 | + @return 'light'; |
| 381 | + } |
| 382 | + |
| 383 | + @if ($value == 'light') { |
| 384 | + @return 'dark'; |
| 385 | + } |
| 386 | + |
| 387 | + // Fallback if the app is using a non-color palette (e.g. CSS variable based). |
| 388 | + @if (meta.type-of($value) != 'color') { |
| 389 | + @return if($is-dark, 'light', 'dark'); |
| 390 | + } |
| 391 | + |
| 392 | + $minimum-contrast: 3.1; |
| 393 | + $light-contrast: _contrast($value, #fff); |
| 394 | + $dark-contrast: _contrast($value, rgba(0, 0, 0, 0.87)); |
| 395 | + |
| 396 | + @if ($light-contrast < $minimum-contrast) and ($dark-contrast > $light-contrast) { |
| 397 | + @return 'dark'; |
| 398 | + } |
| 399 | + |
| 400 | + @return 'light'; |
| 401 | +} |
| 402 | + |
| 403 | +@function _linear-channel-value($channel-value) { |
| 404 | + $normalized-channel-value: math.div($channel-value, 255); |
| 405 | + |
| 406 | + @if ($normalized-channel-value < 0.03928) { |
| 407 | + @return math.div($normalized-channel-value, 12.92); |
| 408 | + } |
| 409 | + |
| 410 | + @return math.pow(math.div($normalized-channel-value + 0.055, 1.055), 2.4); |
| 411 | +} |
| 412 | + |
| 413 | +// Calculate the luminance for a color. |
| 414 | +// See https://www.w3.org/TR/WCAG20-TECHS/G17.html#G17-tests |
| 415 | +@function _luminance($color) { |
| 416 | + $red: _linear-channel-value(color.red($color)); |
| 417 | + $green: _linear-channel-value(color.green($color)); |
| 418 | + $blue: _linear-channel-value(color.blue($color)); |
| 419 | + |
| 420 | + @return 0.2126 * $red + 0.7152 * $green + 0.0722 * $blue; |
| 421 | +} |
| 422 | + |
| 423 | +// Calculate the contrast ratio between two colors. |
| 424 | +// See https://www.w3.org/TR/WCAG20-TECHS/G17.html#G17-tests |
| 425 | +@function _contrast($back, $front) { |
| 426 | + $back-lum: _luminance($back) + 0.05; |
| 427 | + $fore-lum: _luminance($front) + 0.05; |
| 428 | + |
| 429 | + @return math.div(math.max($back-lum, $fore-lum), math.min($back-lum, $fore-lum)); |
| 430 | +} |
| 431 | + |
370 | 432 | /// Verifies that the token overrides exist and are used in one of the given token maps. |
371 | 433 | @mixin _validate-token-overrides($overrides: (), $token-maps) { |
372 | 434 | $valid-token-names: (); |
|
0 commit comments