From 3a291ac6f6ae52093375f4c3dab5f15c4cf476b8 Mon Sep 17 00:00:00 2001 From: Michael Prentice Date: Wed, 1 Jul 2020 01:34:37 -0400 Subject: [PATCH] fix(theming, toolbar, subheader, input): align color palettes and contrasts with AA standards - properly theme `md-icon`s in toolbars with `md-warn` - all colors and their contrasts meet 4.5 contrast ratio requirements - except a few edge cases which have comments to explain them - add `aria-labels` to demoInputsInToolbar - increase opacity of subheader text to meet AA contrast ratio requirements - increase opacity of input placeholders and labels to meet AA contrast ratio requirements - minor regexp adjustments for `md-colors` - fix colors/demoThemePicker and colors/demoBasicUsage to pass Lighthouse a11y audit - update button/demoBasicUsage to pass Lighthouse a11y audit - add missing alt tag in demoInCardActions and demoCardActionButtons - adjust docs app theme to define valid contrast colors for `docs-blue` - fix inaccurate JSDoc Fixes #8992. Fixes #10164. Closes #8993. BREAKING CHANGE: The contrast colors (the text or icon color, for example on a raised button) of many of our default palettes have been updated to meet the [AA level of the contrast guidelines](https://www.w3.org/TR/WCAG21/#contrast-minimum) for web accessibility. If you are using our default palettes directly, the accessibility of your application should be improved. However, we recommend that you evaluate this after updating to `1.2.0`. There may be edge cases in your app or custom styles that need to be updated to meet accessibility guidelines. If you find significant accessibility issues after updating, please report them to us. In `1.2.x`, we have a lot more control over our component theming in regards to hues and opacities. If your app is using a custom palette, whether based on a copy of default palette or not, we encourage you to evaluate that your contrast configuration meets the WebAIM guidelines. Please review our guide on [Defining Custom Palettes](https://material.angularjs.org/latest/Theming/03_configuring_a_theme#defining-custom-palettes) for details. --- docs/app/js/app.js | 10 ++- .../button/demoBasicUsage/index.html | 14 ++-- .../button/demoBasicUsage/script.js | 2 - .../button/demoBasicUsage/style.css | 2 +- .../card/demoCardActionButtons/index.html | 2 +- .../card/demoInCardActions/index.html | 2 +- src/components/colors/colors.js | 2 +- .../colors/demoBasicUsage/index.html | 4 +- .../colors/demoThemePicker/index.html | 4 +- src/components/input/input-theme.scss | 4 +- src/components/subheader/subheader-theme.scss | 2 +- .../toolbar/demoInputsInToolbar/index.html | 24 +++--- src/components/toolbar/toolbar-theme.scss | 5 ++ src/core/core.js | 2 +- src/core/services/theming/theme.palette.js | 84 ++++++++++++------- 15 files changed, 94 insertions(+), 69 deletions(-) diff --git a/docs/app/js/app.js b/docs/app/js/app.js index b633f095187..ef79c4c0a3e 100644 --- a/docs/app/js/app.js +++ b/docs/app/js/app.js @@ -51,8 +51,8 @@ function(SERVICES, COMPONENTS, DEMOS, PAGES, '800': '#014AB6', '900': '#013583', 'contrastDefaultColor': 'light', - 'contrastDarkColors': '50 100 200 A100', - 'contrastStrongLightColors': '300 400 A200 A400' + 'contrastDarkColors': '50 100 200 300 400 A100 A200', + 'contrastStrongLightColors': '500 600 700 800 900 A400 A700' })); $mdThemingProvider.definePalette('docs-red', $mdThemingProvider.extendPalette('red', { 'A100': '#DE3641' @@ -76,8 +76,10 @@ function(SERVICES, COMPONENTS, DEMOS, PAGES, .defaultIconSet('img/icons/sets/core-icons.svg', 24); $mdThemingProvider.theme('default') - .primaryPalette('docs-blue') - .accentPalette('docs-red'); + .primaryPalette('docs-blue') + .accentPalette('docs-red', { + 'default': 'A700' + }); $mdThemingProvider.enableBrowserColor(); diff --git a/src/components/button/demoBasicUsage/index.html b/src/components/button/demoBasicUsage/index.html index 05a305d6c43..30a3ba196e5 100644 --- a/src/components/button/demoBasicUsage/index.html +++ b/src/components/button/demoBasicUsage/index.html @@ -2,10 +2,10 @@
- {{title1}} + Button Primary (md-noink) Disabled - {{title4}} + Warn
Flat
@@ -14,7 +14,7 @@ Button Primary Disabled - Warn + Accent
Raised
@@ -58,10 +58,10 @@
- Primary Hue 1 - Warn Hue 2 - Accent - Accent Hue 1 + Primary Hue 2 + Warn Hue 1 + Accent Hue 2 + Accent Hue 3
Themed
diff --git a/src/components/button/demoBasicUsage/script.js b/src/components/button/demoBasicUsage/script.js index 4201838b251..7153f0d1e36 100644 --- a/src/components/button/demoBasicUsage/script.js +++ b/src/components/button/demoBasicUsage/script.js @@ -1,7 +1,5 @@ angular.module('buttonsDemoBasic', ['ngMaterial']) .controller('AppCtrl', function($scope) { - $scope.title1 = 'Button'; - $scope.title4 = 'Warn'; $scope.isDisabled = true; $scope.googleUrl = 'http://google.com'; }); diff --git a/src/components/button/demoBasicUsage/style.css b/src/components/button/demoBasicUsage/style.css index 65e021f6d55..ac3c84a6324 100644 --- a/src/components/button/demoBasicUsage/style.css +++ b/src/components/button/demoBasicUsage/style.css @@ -13,5 +13,5 @@ section .md-button { bottom: 5px; left: 7px; font-size: 14px; - opacity: 0.54; + color: rgba(0, 0, 0, 0.54); } diff --git a/src/components/card/demoCardActionButtons/index.html b/src/components/card/demoCardActionButtons/index.html index 1dbe3a7e376..b1b7caaa023 100644 --- a/src/components/card/demoCardActionButtons/index.html +++ b/src/components/card/demoCardActionButtons/index.html @@ -90,7 +90,7 @@ - + Washed Out AngularJS diff --git a/src/components/card/demoInCardActions/index.html b/src/components/card/demoInCardActions/index.html index 90c87a7bc54..dbfb9272330 100644 --- a/src/components/card/demoInCardActions/index.html +++ b/src/components/card/demoInCardActions/index.html @@ -30,7 +30,7 @@ - + Washed Out User diff --git a/src/components/colors/colors.js b/src/components/colors/colors.js index 5007e812b6f..c285639cccc 100644 --- a/src/components/colors/colors.js +++ b/src/components/colors/colors.js @@ -5,7 +5,7 @@ * Use a RegExp to check if the `md-colors=""` is static string * or one that should be observed and dynamically interpolated. */ - var STATIC_COLOR_EXPRESSION = /^{((\s|,)*?["'a-zA-Z-]+?\s*?:\s*?('|")[a-zA-Z0-9-.]*('|"))+\s*}$/; + var STATIC_COLOR_EXPRESSION = /^{((\s|,)*?["'a-zA-Z-]+?\s*?:\s*?(['"])[a-zA-Z0-9-.]*(['"]))+\s*}$/; var colorPalettes = null; /** diff --git a/src/components/colors/demoBasicUsage/index.html b/src/components/colors/demoBasicUsage/index.html index 20011e0e3ac..2dd2a833467 100644 --- a/src/components/colors/demoBasicUsage/index.html +++ b/src/components/colors/demoBasicUsage/index.html @@ -1,6 +1,6 @@

- Custom component implementations using Material elements often want to easily apply theme colors + Custom component implementations using Material elements often want to apply theme colors to their custom components. Consider the custom <user-card> component below where the md-colors attribute is used to color the background and text colors using either the current or specified theme palette colors. @@ -18,7 +18,7 @@

<user-card> coloring using the 'fores

Note: The md-colors directive allows pre-defined theme colors to be applied as CSS style properties. md-colors uses the palettes defined in the - + Material Design Colors and the themes defined using $mdThemingProvider. This directive is an extension of the $mdTheming features.

diff --git a/src/components/colors/demoThemePicker/index.html b/src/components/colors/demoThemePicker/index.html index a61b006fcb5..aec84e63cd2 100644 --- a/src/components/colors/demoThemePicker/index.html +++ b/src/components/colors/demoThemePicker/index.html @@ -1,12 +1,12 @@

- Select two of the Material Palettes + Select two of the Material Palettes below:

{{color}} diff --git a/src/components/input/input-theme.scss b/src/components/input/input-theme.scss index 14e47ba2d2d..5dd1de01511 100644 --- a/src/components/input/input-theme.scss +++ b/src/components/input/input-theme.scss @@ -1,6 +1,6 @@ md-input-container.md-THEME_NAME-theme { .md-input { - @include input-placeholder-color('\'{{background-default-contrast-hint}}\''); + @include input-placeholder-color('\'{{background-default-contrast-secondary}}\''); color: '{{background-default-contrast}}'; border-color: '{{background-default-contrast-divider}}'; } @@ -11,7 +11,7 @@ md-input-container.md-THEME_NAME-theme { label, .md-placeholder { - color: '{{background-default-contrast-hint}}'; + color: '{{background-default-contrast-secondary}}'; } label.md-required:after { diff --git a/src/components/subheader/subheader-theme.scss b/src/components/subheader/subheader-theme.scss index 60fd59123cb..a9a2991970e 100644 --- a/src/components/subheader/subheader-theme.scss +++ b/src/components/subheader/subheader-theme.scss @@ -1,5 +1,5 @@ .md-subheader.md-THEME_NAME-theme { - color: '{{ foreground-2-0.23 }}'; + color: '{{ foreground-2-0.54 }}'; background-color: '{{background-default}}'; &.md-primary { diff --git a/src/components/toolbar/demoInputsInToolbar/index.html b/src/components/toolbar/demoInputsInToolbar/index.html index e77c3cbf899..1685f8540c7 100644 --- a/src/components/toolbar/demoInputsInToolbar/index.html +++ b/src/components/toolbar/demoInputsInToolbar/index.html @@ -9,15 +9,15 @@ - + - + - + @@ -31,15 +31,15 @@ - + - + - + @@ -53,27 +53,27 @@ - + - + - + - + - + - +
diff --git a/src/components/toolbar/toolbar-theme.scss b/src/components/toolbar/toolbar-theme.scss index 56185eae494..a8b3b4f3488 100644 --- a/src/components/toolbar/toolbar-theme.scss +++ b/src/components/toolbar/toolbar-theme.scss @@ -107,6 +107,11 @@ md-toolbar.md-THEME_NAME-theme:not(.md-menu-toolbar) { background-color: '{{warn-color}}'; color: '{{warn-contrast}}'; + md-icon { + color: '{{accent-contrast}}'; + fill: '{{accent-contrast}}'; + } + md-input-container[md-no-float] { .md-input { @include input-placeholder-color('\'{{warn-default-contrast-hint}}\''); diff --git a/src/core/core.js b/src/core/core.js index 7e36957493d..4246fd7745c 100644 --- a/src/core/core.js +++ b/src/core/core.js @@ -59,7 +59,7 @@ function rAFDecorator($delegate) { * our callback will only be fired once per frame, with the last resize * event that happened before that frame. * - * @param {function} callback function to debounce + * @param {function} cb function to debounce */ $delegate.throttle = function(cb) { var queuedArgs, alreadyQueued, queueCb, context; diff --git a/src/core/services/theming/theme.palette.js b/src/core/services/theming/theme.palette.js index 77915005982..21b381c1885 100644 --- a/src/core/services/theming/theme.palette.js +++ b/src/core/services/theming/theme.palette.js @@ -16,8 +16,8 @@ angular.module('material.core.theming.palette', []) 'A400': '#ff1744', 'A700': '#d50000', 'contrastDefaultColor': 'light', - 'contrastDarkColors': '50 100 200 300 A100', - 'contrastStrongLightColors': '400 500 600 700 800 900 A200 A400 A700' + 'contrastDarkColors': '50 100 200 300 400 500 600 A100 A200 A400', + 'contrastStrongLightColors': '700 800 900 A700' }, 'pink': { '50': '#fce4ec', @@ -35,8 +35,10 @@ angular.module('material.core.theming.palette', []) 'A400': '#f50057', 'A700': '#c51162', 'contrastDefaultColor': 'light', - 'contrastDarkColors': '50 100 200 A100', - 'contrastStrongLightColors': '300 400 500 600 700 800 900 A200 A400 A700' + 'contrastDarkColors': '50 100 200 300 400 A100 A200 A400', + // White on 500 does not meet the minimum 4.5 contrast ratio (at 4.34), + // but it's worse with a dark foreground (3.61). + 'contrastStrongLightColors': '500 600 700 800 900 A700' }, 'purple': { '50': '#f3e5f5', @@ -54,8 +56,8 @@ angular.module('material.core.theming.palette', []) 'A400': '#d500f9', 'A700': '#aa00ff', 'contrastDefaultColor': 'light', - 'contrastDarkColors': '50 100 200 A100', - 'contrastStrongLightColors': '300 400 500 600 700 800 900 A200 A400 A700' + 'contrastDarkColors': '50 100 200 300 A100 A200 A400', + 'contrastStrongLightColors': '400 500 600 700 800 900 A700' }, 'deep-purple': { '50': '#ede7f6', @@ -73,8 +75,8 @@ angular.module('material.core.theming.palette', []) 'A400': '#651fff', 'A700': '#6200ea', 'contrastDefaultColor': 'light', - 'contrastDarkColors': '50 100 200 A100', - 'contrastStrongLightColors': '300 400 500 600 700 800 900 A200 A400 A700' + 'contrastDarkColors': '50 100 200 300 A100', + 'contrastStrongLightColors': '400 500 600 700 800 900 A200 A400 A700' }, 'indigo': { '50': '#e8eaf6', @@ -92,8 +94,8 @@ angular.module('material.core.theming.palette', []) 'A400': '#3d5afe', 'A700': '#304ffe', 'contrastDefaultColor': 'light', - 'contrastDarkColors': '50 100 200 A100', - 'contrastStrongLightColors': '300 400 500 600 700 800 900 A200 A400 A700' + 'contrastDarkColors': '50 100 200 300 A100 A200', + 'contrastStrongLightColors': '400 500 600 700 800 900 A400 A700' }, 'blue': { '50': '#e3f2fd', @@ -111,8 +113,10 @@ angular.module('material.core.theming.palette', []) 'A400': '#2979ff', 'A700': '#2962ff', 'contrastDefaultColor': 'light', - 'contrastDarkColors': '50 100 200 300 400 A100', - 'contrastStrongLightColors': '500 600 700 800 900 A200 A400 A700' + // White on A400 does not meet the minimum 4.5 contrast ratio (at 3.98), + // but it's worse with a dark foreground (3.94). + 'contrastDarkColors': '50 100 200 300 400 500 600 A100 A200', + 'contrastStrongLightColors': '700 800 900 A400 A700' }, 'light-blue': { '50': '#e1f5fe', @@ -130,8 +134,10 @@ angular.module('material.core.theming.palette', []) 'A400': '#00b0ff', 'A700': '#0091ea', 'contrastDefaultColor': 'dark', - 'contrastLightColors': '600 700 800 900 A700', - 'contrastStrongLightColors': '600 700 800 900 A700' + // Dark on 700 does not meet the minimum 4.5 contrast ratio (at 4.07), + // but it's worse with a white foreground (3.85). + 'contrastLightColors': '800 900 A700', + 'contrastStrongLightColors': '800 900 A700' }, 'cyan': { '50': '#e0f7fa', @@ -149,8 +155,10 @@ angular.module('material.core.theming.palette', []) 'A400': '#00e5ff', 'A700': '#00b8d4', 'contrastDefaultColor': 'dark', - 'contrastLightColors': '700 800 900', - 'contrastStrongLightColors': '700 800 900' + // Dark on 700 does not meet the minimum 4.5 contrast ratio (at 4.47), + // but it's worse with a white foreground (3.5). + 'contrastLightColors': '800 900', + 'contrastStrongLightColors': '800 900' }, 'teal': { '50': '#e0f2f1', @@ -168,8 +176,12 @@ angular.module('material.core.theming.palette', []) 'A400': '#1de9b6', 'A700': '#00bfa5', 'contrastDefaultColor': 'dark', - 'contrastLightColors': '500 600 700 800 900', - 'contrastStrongLightColors': '500 600 700 800 900' + // Dark on 500 does not meet the minimum 4.5 contrast ratio (at 4.27), + // but it's worse with a white foreground (3.67). + // White on 600 does not meet the minimum 4.5 contrast ratio (at 4.31), + // but it's worse with a dark foreground (3.64). + 'contrastLightColors': '600 700 800 900', + 'contrastStrongLightColors': '600 700 800 900' }, 'green': { '50': '#e8f5e9', @@ -187,8 +199,10 @@ angular.module('material.core.theming.palette', []) 'A400': '#00e676', 'A700': '#00c853', 'contrastDefaultColor': 'dark', - 'contrastLightColors': '600 700 800 900', - 'contrastStrongLightColors': '600 700 800 900' + // White on 700 does not meet the minimum 4.5 contrast ratio (at 4.11), + // but it's worse with a dark foreground (3.81). + 'contrastLightColors': '700 800 900', + 'contrastStrongLightColors': '700 800 900' }, 'light-green': { '50': '#f1f8e9', @@ -206,8 +220,8 @@ angular.module('material.core.theming.palette', []) 'A400': '#76ff03', 'A700': '#64dd17', 'contrastDefaultColor': 'dark', - 'contrastLightColors': '700 800 900', - 'contrastStrongLightColors': '700 800 900' + 'contrastLightColors': '800 900', + 'contrastStrongLightColors': '800 900' }, 'lime': { '50': '#f9fbe7', @@ -278,8 +292,8 @@ angular.module('material.core.theming.palette', []) 'A400': '#ff9100', 'A700': '#ff6d00', 'contrastDefaultColor': 'dark', - 'contrastLightColors': '800 900', - 'contrastStrongLightColors': '800 900' + 'contrastLightColors': '900', + 'contrastStrongLightColors': '900' }, 'deep-orange': { '50': '#fbe9e7', @@ -296,9 +310,12 @@ angular.module('material.core.theming.palette', []) 'A200': '#ff6e40', 'A400': '#ff3d00', 'A700': '#dd2c00', - 'contrastDefaultColor': 'light', - 'contrastDarkColors': '50 100 200 300 400 A100 A200', - 'contrastStrongLightColors': '500 600 700 800 900 A400 A700' + 'contrastDefaultColor': 'dark', + // Dark on 700 does not meet the minimum 4.5 contrast ratio (at 4.01), + // but it's worse with a white foreground (3.91). + // White on 800 does not meet the minimum 4.5 contrast ratio (at 4.43), + // but it's worse with a dark foreground (3.54). + 'contrastLightColors': '800 900 A400 A700', }, 'brown': { '50': '#efebe9', @@ -316,8 +333,8 @@ angular.module('material.core.theming.palette', []) 'A400': '#8d6e63', 'A700': '#5d4037', 'contrastDefaultColor': 'light', - 'contrastDarkColors': '50 100 200 A100 A200', - 'contrastStrongLightColors': '300 400 500 600 700 800 900 A400 A700' + 'contrastDarkColors': '50 100 200 300 A100 A200', + 'contrastStrongLightColors': '400 500 600 700 800 900 A400 A700' }, 'grey': { '50': '#fafafa', @@ -335,7 +352,8 @@ angular.module('material.core.theming.palette', []) 'A400': '#303030', 'A700': '#616161', 'contrastDefaultColor': 'dark', - 'contrastLightColors': '600 700 800 900 A200 A400 A700' + 'contrastLightColors': '600 700 800 900 A200 A400 A700', + 'contrastStrongLightColors': '600' }, 'blue-grey': { '50': '#eceff1', @@ -353,7 +371,9 @@ angular.module('material.core.theming.palette', []) 'A400': '#78909c', 'A700': '#455a64', 'contrastDefaultColor': 'light', - 'contrastDarkColors': '50 100 200 300 A100 A200', - 'contrastStrongLightColors': '400 500 600 700 800 900 A400 A700' + 'contrastDarkColors': '50 100 200 300 400 A100 A200 A400', + // White on 500 does not meet the minimum 4.5 contrast ratio (at 4.37), + // but it's worse with a dark foreground. + 'contrastStrongLightColors': '500 600 700 800 900 A700' } });