author | Maliha Islam <mislam@mozilla.com> |
Fri, 16 Aug 2019 00:55:27 +0000 | |
changeset 488409 | c009e486b4c2e82a516e95cfb635523ea215e275 |
parent 488408 | d9a83f0385d54763aabbadaea607a7451381beba |
child 488410 | 1cca4f1af964c1214bc04bd9d5b34fee4023ed87 |
push id | 92739 |
push user | yura.zenevich@gmail.com |
push date | Fri, 16 Aug 2019 00:59:10 +0000 |
treeherder | autoland@c009e486b4c2 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | yzen, gl |
bugs | 1568053 |
milestone | 70.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/devtools/client/accessibility/accessibility.css +++ b/devtools/client/accessibility/accessibility.css @@ -658,17 +658,17 @@ body { .accessible .tree .objectBox-accessible .accessible-name, .accessible .tree .objectBox-node .attrName { overflow: hidden; text-overflow: ellipsis; } .accessible .tree .objectBox-accessible .open-accessibility-inspector, -.accessible .tree .objectBox-node .open-inspector{ +.accessible .tree .objectBox-node .open-inspector { width: 17px; cursor: pointer; flex-shrink: 0; } .accessible .tree .objectBox-object, .accessible .tree .objectBox-string, .accessible .tree .objectBox-text, @@ -800,13 +800,8 @@ body { .accessibility-color-contrast .accessibility-color-contrast-label:after { content: ":"; } .accessibility-color-contrast .accessibility-color-contrast-label, .accessibility-color-contrast .accessibility-color-contrast-separator:before { margin-inline-end: 3px; } - -.accessibility-color-contrast .accessibility-color-contrast-separator:before { - content: "-"; - margin-inline-start: 4px; -}
--- a/devtools/client/locales/en-US/inspector.properties +++ b/devtools/client/locales/en-US/inspector.properties @@ -533,8 +533,14 @@ colorPickerTooltip.colorNameTitle=Closes # LOCALIZATION NOTE (colorPickerTooltip.hueSliderTitle): A title text for the # hue slider in the color picker tooltip. colorPickerTooltip.hueSliderTitle=Hue # LOCALIZATION NOTE (colorPickerTooltip.alphaSliderTitle): A title text for the # alpha slider in the color picker tooltip. colorPickerTooltip.alphaSliderTitle=Opacity + +# LOCALIZATION NOTE (colorPickerTooltip.contrast.large.title): A title text for the color +# contrast ratio description in the color picker tooltip, used together with the specification +# that the color contrast criteria used is for large text. %S in the content will be replaced by a +# large text indicator span at run time. +colorPickerTooltip.contrast.large.title=Contrast %S:
--- a/devtools/client/shared/test/browser_spectrum.js +++ b/devtools/client/shared/test/browser_spectrum.js @@ -4,31 +4,35 @@ "use strict"; // Tests that the spectrum color picker works correctly const { Spectrum } = require("devtools/client/shared/widgets/Spectrum"); const { accessibility: { - SCORES: { FAIL, AAA }, + SCORES: { FAIL, AAA, AA }, }, } = require("devtools/shared/constants"); loader.lazyRequireGetter( this, "cssColors", "devtools/shared/css/color-db", true ); const TEST_URI = CHROME_URL_ROOT + "doc_spectrum.html"; const REGULAR_TEXT_PROPS = { "font-size": { value: "11px" }, "font-weight": { value: "bold" }, + opacity: { value: "1" }, +}; +const SINGLE_BG_COLOR = { + value: cssColors.white, }; const ZERO_ALPHA_COLOR = [0, 255, 255, 0]; add_task(async function() { const [host, , doc] = await createHost("bottom", TEST_URI); const container = doc.getElementById("spectrum-container"); @@ -38,16 +42,17 @@ add_task(async function() { await testChangingColorShouldEmitEvents(container, doc); await testSettingColorShoudUpdateTheUI(container); await testChangingColorShouldUpdateColorPreview(container); await testNotSettingTextPropsShouldNotShowContrastSection(container); await testSettingTextPropsAndColorShouldUpdateContrastValue(container); await testOnlySelectingLargeTextWithNonZeroAlphaShouldShowIndicator( container ); + await testSettingMultiColoredBackgroundShouldShowContrastRange(container); host.destroy(); }); /** * Helper method for extracting the rgba overlay value of the color preview's background * image style. * @@ -343,37 +348,38 @@ function testNotSettingTextPropsShouldNo "Contrast section is not shown." ); s.destroy(); } function testSpectrumContrast( spectrum, + contrastValueEl, rgb, expectedValue, expectedBadgeClass = "", expectLargeTextIndicator = false ) { setSpectrumProps(spectrum, { rgb }); is( - spectrum.contrastValue.textContent, + contrastValueEl.textContent, expectedValue, "Contrast value has the correct text." ); is( - spectrum.contrastValue.className, + contrastValueEl.className, `accessibility-contrast-value${ expectedBadgeClass ? " " + expectedBadgeClass : "" }`, `Contrast value contains ${expectedBadgeClass || "base"} class.` ); is( - spectrum.spectrumContrast.classList.contains("large-text"), + spectrum.contrastLabel.childNodes.length === 3, expectLargeTextIndicator, `Large text indicator is ${expectLargeTextIndicator ? "" : "not"} shown.` ); } function testSettingTextPropsAndColorShouldUpdateContrastValue(container) { const s = new Spectrum(container, cssColors.white); s.show(); @@ -381,62 +387,119 @@ function testSettingTextPropsAndColorSho ok( !s.spectrumContrast.classList.contains("visible"), "Contrast value is not available yet." ); info( "Test that contrast ratio is calculated on setting 'textProps' and 'rgb'." ); - setSpectrumProps(s, { textProps: REGULAR_TEXT_PROPS }, false); - testSpectrumContrast(s, [50, 240, 234, 0.8], "1.35", FAIL); + setSpectrumProps( + s, + { textProps: REGULAR_TEXT_PROPS, backgroundColorData: SINGLE_BG_COLOR }, + false + ); + testSpectrumContrast(s, s.contrastValue, [50, 240, 234, 0.8], "1.35", FAIL); info("Test that contrast ratio is updated when color is changed."); - testSpectrumContrast(s, cssColors.black, "21.00", AAA); + testSpectrumContrast(s, s.contrastValue, cssColors.black, "21.00", AAA); info("Test that contrast ratio cannot be calculated with zero alpha."); - testSpectrumContrast(s, ZERO_ALPHA_COLOR, "Unable to calculate"); + testSpectrumContrast( + s, + s.contrastValue, + ZERO_ALPHA_COLOR, + "Unable to calculate" + ); s.destroy(); } function testOnlySelectingLargeTextWithNonZeroAlphaShouldShowIndicator( container ) { let s = new Spectrum(container, cssColors.white); s.show(); ok( - !s.spectrumContrast.classList.contains("large-text"), + s.contrastLabel.childNodes.length !== 3, "Large text indicator is initially hidden." ); info( "Test that selecting large text with non-zero alpha shows large text indicator." ); setSpectrumProps( s, { textProps: { "font-size": { value: "24px" }, "font-weight": { value: "normal" }, + opacity: { value: "1" }, }, + backgroundColorData: SINGLE_BG_COLOR, }, false ); - testSpectrumContrast(s, cssColors.black, "21.00", AAA, true); + testSpectrumContrast(s, s.contrastValue, cssColors.black, "21.00", AAA, true); info( "Test that selecting large text with zero alpha hides large text indicator." ); - testSpectrumContrast(s, ZERO_ALPHA_COLOR, "Unable to calculate"); + testSpectrumContrast( + s, + s.contrastValue, + ZERO_ALPHA_COLOR, + "Unable to calculate" + ); // Spectrum should be closed and opened again to reflect changes in text size s.destroy(); s = new Spectrum(container, cssColors.white); s.show(); info("Test that selecting regular text does not show large text indicator."); - setSpectrumProps(s, { textProps: REGULAR_TEXT_PROPS }, false); - testSpectrumContrast(s, cssColors.black, "21.00", AAA); + setSpectrumProps( + s, + { textProps: REGULAR_TEXT_PROPS, backgroundColorData: SINGLE_BG_COLOR }, + false + ); + testSpectrumContrast(s, s.contrastValue, cssColors.black, "21.00", AAA); s.destroy(); } + +function testSettingMultiColoredBackgroundShouldShowContrastRange(container) { + const s = new Spectrum(container, cssColors.white); + s.show(); + + info( + "Test setting text with non-zero alpha and multi-colored bg shows contrast range and empty single contrast." + ); + setSpectrumProps( + s, + { + textProps: REGULAR_TEXT_PROPS, + backgroundColorData: { + min: cssColors.yellow, + max: cssColors.green, + }, + }, + false + ); + testSpectrumContrast(s, s.contrastValueMin, cssColors.white, "1.07", FAIL); + testSpectrumContrast(s, s.contrastValueMax, cssColors.white, "5.14", AA); + testSpectrumContrast(s, s.contrastValue, cssColors.white, ""); + ok( + s.spectrumContrast.classList.contains("range"), + "Contrast section contains range class." + ); + + info("Test setting text with zero alpha shows error in contrast min span."); + testSpectrumContrast( + s, + s.contrastValueMin, + ZERO_ALPHA_COLOR, + "Unable to calculate" + ); + + s.destroy(); +}
--- a/devtools/client/shared/widgets/Spectrum.js +++ b/devtools/client/shared/widgets/Spectrum.js @@ -9,52 +9,45 @@ const { MultiLocalizationHelper } = requ const L10N = new MultiLocalizationHelper( "devtools/shared/locales/en-US/accessibility.properties", "devtools/client/locales/en-US/accessibility.properties", "devtools/client/locales/en-US/inspector.properties" ); const ARROW_KEYS = ["ArrowUp", "ArrowRight", "ArrowDown", "ArrowLeft"]; const [ArrowUp, ArrowRight, ArrowDown, ArrowLeft] = ARROW_KEYS; const XHTML_NS = "http://www.w3.org/1999/xhtml"; -const COLOR_HEX_WHITE = "#ffffff"; const SLIDER = { hue: { MIN: "0", MAX: "128", STEP: "1", }, alpha: { MIN: "0", MAX: "1", STEP: "0.01", }, }; loader.lazyRequireGetter(this, "colorUtils", "devtools/shared/css/color", true); loader.lazyRequireGetter( this, - "cssColors", - "devtools/shared/css/color-db", - true -); -loader.lazyRequireGetter( - this, "labColors", "devtools/shared/css/color-db", true ); loader.lazyRequireGetter( this, - "getContrastRatioScore", + "getTextProperties", "devtools/shared/accessibility", true ); loader.lazyRequireGetter( this, - "getTextProperties", + "getContrastRatioAgainstBackground", "devtools/shared/accessibility", true ); /** * Spectrum creates a color picker widget in any container you give it. * * Simple usage example: @@ -105,26 +98,31 @@ function Spectrum(parentEl, rgb) { <section class="spectrum-controls"> <div class="spectrum-color-preview"></div> <div class="spectrum-slider-container"> <div class="spectrum-hue spectrum-box"></div> <div class="spectrum-alpha spectrum-checker spectrum-box"></div> </div> </section> <section class="spectrum-color-contrast accessibility-color-contrast"> - <span class="contrast-ratio-label" role="presentation"> - ${L10N.getStr("accessibility.contrast.ratio.label")} - </span> - <span class="accessibility-contrast-value"></span> - <span - class="accessibility-color-contrast-large-text" - title="${L10N.getStr("accessibility.contrast.large.title")}" - > - ${L10N.getStr("accessibility.contrast.large.text")} - </span> + <div class="contrast-ratio-header-and-single-ratio"> + <span class="contrast-ratio-label" role="presentation"></span> + <span class="contrast-value-and-swatch contrast-ratio-single" role="presentation"> + <span class="accessibility-contrast-value"></span> + </span> + </div> + <div class="contrast-ratio-range"> + <span class="contrast-value-and-swatch contrast-ratio-min" role="presentation"> + <span class="accessibility-contrast-value"></span> + </span> + <span class="accessibility-color-contrast-separator"></span> + <span class="contrast-value-and-swatch contrast-ratio-max" role="presentation"> + <span class="accessibility-contrast-value"></span> + </span> + </div> </section> `; this.onElementClick = this.onElementClick.bind(this); this.element.addEventListener("click", this.onElementClick); this.parentEl.appendChild(this.element); @@ -159,26 +157,31 @@ function Spectrum(parentEl, rgb) { "alpha", this.onAlphaSliderMove.bind(this) ); // Color contrast this.spectrumContrast = this.element.querySelector( ".spectrum-color-contrast" ); - this.contrastValue = this.element.querySelector( - ".accessibility-contrast-value" - ); + this.contrastLabel = this.element.querySelector(".contrast-ratio-label"); + [ + this.contrastValue, + this.contrastValueMin, + this.contrastValueMax, + ] = this.element.querySelectorAll(".accessibility-contrast-value"); // Create the learn more info button const learnMore = this.document.createElementNS(XHTML_NS, "button"); learnMore.id = "learn-more-button"; learnMore.className = "learn-more"; learnMore.title = L10N.getStr("accessibility.learnMore"); - this.spectrumContrast.appendChild(learnMore); + this.element + .querySelector(".contrast-ratio-header-and-single-ratio") + .appendChild(learnMore); if (rgb) { this.rgb = rgb; this.updateUI(); } } module.exports.Spectrum = Spectrum; @@ -356,57 +359,57 @@ Spectrum.draggable = function(element, d }; /** * Calculates the contrast ratio for a DOM node's computed style against * a given background. * * @param {Object} computedStyle * The computed style for which we want to calculate the contrast ratio. - * @param {Array} background - * The rgba value array for background color (i.e. [255, 255, 255, 1]). + * @param {Object} backgroundColor + * Object with one or more of the following properties: value, min, max * @return {Object} * An object that may contain one or more of the following fields: error, * isLargeText, value, score for contrast. */ -function getContrastRatioAgainstSolidBg( - computedStyle, - background = cssColors.white -) { +function getContrastRatio(computedStyle, backgroundColor) { const props = getTextProperties(computedStyle); + if (!props) { return { error: true, }; } - const { color, isLargeText } = props; - const value = colorUtils.calculateContrastRatio(background, color); - return { - value, - color, - isLargeText, - score: getContrastRatioScore(value, isLargeText), - }; + return getContrastRatioAgainstBackground(backgroundColor, props); } Spectrum.prototype = { set textProps(style) { this._textProps = style ? { fontSize: style["font-size"].value, fontWeight: style["font-weight"].value, + opacity: style.opacity.value, } : null; }, set rgb(color) { this.hsv = Spectrum.rgbToHsv(color[0], color[1], color[2], color[3]); }, + set backgroundColorData(colorData) { + this._backgroundColorData = colorData; + }, + + get backgroundColorData() { + return this._backgroundColorData; + }, + get textProps() { return this._textProps; }, get rgb() { const rgb = Spectrum.hsvToRgb( this.hsv[0], this.hsv[1], @@ -512,16 +515,92 @@ Spectrum.prototype = { slider.step = SLIDER[sliderType].STEP; slider.title = L10N.getStr(`colorPickerTooltip.${sliderType}SliderTitle`); slider.addEventListener("input", onSliderMove); container.appendChild(slider); return slider; }, + /** + * Updates the contrast label with appropriate content (i.e. large text indicator + * if the contrast is calculated for large text, or a base label otherwise) + * + * @param {Boolean} isLargeText + * True if contrast is calculated for large text. + */ + updateContrastLabel: function(isLargeText) { + if (!isLargeText) { + this.contrastLabel.textContent = L10N.getStr( + "accessibility.contrast.ratio.label" + ); + return; + } + + // Clear previously appended children before appending any new children + while (this.contrastLabel.firstChild) { + this.contrastLabel.firstChild.remove(); + } + + const largeTextStr = L10N.getStr("accessibility.contrast.large.text"); + const contrastLabelStr = L10N.getFormatStr( + "colorPickerTooltip.contrast.large.title", + largeTextStr + ); + + // Build an array of children nodes for the contrast label element + const contents = contrastLabelStr + .split(new RegExp(largeTextStr), 2) + .map(content => this.document.createTextNode(content)); + const largeTextIndicator = this.document.createElementNS(XHTML_NS, "span"); + largeTextIndicator.className = "accessibility-color-contrast-large-text"; + largeTextIndicator.textContent = largeTextStr; + largeTextIndicator.title = L10N.getStr( + "accessibility.contrast.large.title" + ); + contents.splice(1, 0, largeTextIndicator); + + // Append children to contrast label + for (const content of contents) { + this.contrastLabel.appendChild(content); + } + }, + + /** + * Updates a contrast value element with the given score, value and swatches. + * + * @param {DOMNode} el + * Contrast value element to update. + * @param {String} score + * Contrast ratio score. + * @param {Number} value + * Contrast ratio value. + * @param {Array} backgroundColor + * RGBA color array for the background color to show in the swatch. + */ + updateContrastValueEl: function(el, score, value, backgroundColor) { + el.classList.toggle(score, true); + el.textContent = value.toFixed(2); + el.title = L10N.getFormatStr( + `accessibility.contrast.annotation.${score}`, + L10N.getFormatStr( + "colorPickerTooltip.contrastAgainstBgTitle", + `rgba(${backgroundColor})` + ) + ); + el.parentElement.style.setProperty( + "--accessibility-contrast-color", + this.rgbCssString + ); + el.parentElement.style.setProperty( + "--accessibility-contrast-bg", + `rgba(${backgroundColor})` + ); + }, + updateAlphaSlider: function() { // Set alpha slider background const rgb = this.rgb; const rgbNoAlpha = "rgb(" + rgb[0] + "," + rgb[1] + "," + rgb[2] + ")"; const rgbAlpha0 = "rgba(" + rgb[0] + "," + rgb[1] + "," + rgb[2] + ", 0)"; const alphaGradient = "linear-gradient(to right, " + rgbAlpha0 + ", " + rgbNoAlpha + ")"; @@ -588,65 +667,106 @@ Spectrum.prototype = { // Placing the hue slider this.hueSlider.value = h * this.hueSlider.max; // Placing the alpha slider this.alphaSlider.value = this.hsv[3] * this.alphaSlider.max; }, /* Calculates the contrast ratio for the currently selected - * color against white background and displays/hides contrast ratio span + * color against a single or range of background colors and displays contrast ratio section * components depending on the contrast ratio calculated. * * Contrast ratio components include: * - contrastLargeTextIndicator: Hidden by default, shown when text has large font * size if there is no error in calculation. - * - contrastValue: Set to calculated value and score. Set to error text + * - contrastValue(s): Set to calculated value(s), score(s) and text color on + * background swatches. Set to error text * if there is an error in calculation. */ updateContrast: function() { // Remove additional classes on spectrum contrast, leaving behind only base classes - this.spectrumContrast.classList.toggle("large-text", false); this.spectrumContrast.classList.toggle("visible", false); - // Assign only base class to contrastValue, removing any score class - this.contrastValue.className = "accessibility-contrast-value"; + this.spectrumContrast.classList.toggle("range", false); + this.spectrumContrast.classList.toggle("error", false); + // Assign only base class to all contrastValues, removing any score class + this.contrastValue.className = this.contrastValueMin.className = this.contrastValueMax.className = + "accessibility-contrast-value"; if (!this.contrastEnabled) { return; } + const isRange = this.backgroundColorData.min !== undefined; this.spectrumContrast.classList.toggle("visible", true); + this.spectrumContrast.classList.toggle("range", isRange); + + const colorContrast = getContrastRatio( + { + ...this.textProps, + color: this.rgbCssString, + }, + this.backgroundColorData + ); - const contrastRatio = getContrastRatioAgainstSolidBg({ - ...this.textProps, - color: this.rgbCssString, - }); - const { value, score, isLargeText, error } = contrastRatio; + const { + value, + min, + max, + score, + scoreMin, + scoreMax, + backgroundColor, + backgroundColorMin, + backgroundColorMax, + isLargeText, + error, + } = colorContrast; if (error) { - this.contrastValue.textContent = L10N.getStr( - "accessibility.contrast.error" - ); - this.contrastValue.title = L10N.getStr( + this.updateContrastLabel(false); + this.spectrumContrast.classList.toggle("error", true); + + // If current background color is a range, show the error text in the contrast range + // span. Otherwise, show it in the single contrast span. + const contrastValEl = isRange + ? this.contrastValueMin + : this.contrastValue; + contrastValEl.textContent = L10N.getStr("accessibility.contrast.error"); + contrastValEl.title = L10N.getStr( "accessibility.contrast.annotation.transparent.error" ); - this.spectrumContrast.classList.remove("large-text"); + return; } - this.contrastValue.classList.toggle(score, true); - this.contrastValue.textContent = value.toFixed(2); - this.contrastValue.title = L10N.getFormatStr( - `accessibility.contrast.annotation.${score}`, - L10N.getFormatStr( - "colorPickerTooltip.contrastAgainstBgTitle", - COLOR_HEX_WHITE - ) + this.updateContrastLabel(isLargeText); + if (!isRange) { + this.updateContrastValueEl( + this.contrastValue, + score, + value, + backgroundColor + ); + + return; + } + + this.updateContrastValueEl( + this.contrastValueMin, + scoreMin, + min, + backgroundColorMin ); - this.spectrumContrast.classList.toggle("large-text", isLargeText); + this.updateContrastValueEl( + this.contrastValueMax, + scoreMax, + max, + backgroundColorMax + ); }, updateUI: function() { this.updateHelperLocations(); this.updateColorPreview(); this.updateDragger(); this.updateHueSlider(); @@ -663,11 +783,12 @@ Spectrum.prototype = { this.dragger = this.dragHelper = null; this.alphaSlider = null; this.hueSlider = null; this.colorPreview = null; this.element = null; this.parentEl = null; this.spectrumContrast = null; - this.contrastValue = null; + this.contrastValue = this.contrastValueMin = this.contrastValueMax = null; + this.contrastLabel = null; }, };
--- a/devtools/client/shared/widgets/spectrum.css +++ b/devtools/client/shared/widgets/spectrum.css @@ -203,65 +203,123 @@ http://www.briangrinstead.com/blog/keep- height: 8px; width: 8px; border: 1px solid white; box-shadow: 0 0 2px rgba(0, 0, 0, 0.6); } .spectrum-color-contrast { padding-block-start: 8px; - padding-inline-start: 3px; - align-items: stretch; + padding-inline-start: 4px; + padding-inline-end: 4px; line-height: 1.2em; } -.spectrum-color-contrast.visible.large-text .accessibility-color-contrast-large-text { +.contrast-ratio-header-and-single-ratio, +.contrast-ratio-range { + display: flex; + align-items: stretch; +} + +.contrast-ratio-range { + margin-block-start: 4px; + margin-inline-start: 1px; + margin-block-end: 2px; +} + +.spectrum-color-contrast.visible { display: block; } -.spectrum-color-contrast.visible { +.spectrum-color-contrast.visible:not(.range) .contrast-ratio-single, +.spectrum-color-contrast.visible.range .contrast-ratio-range { display: flex; } .spectrum-color-contrast, -.spectrum-color-contrast .accessibility-color-contrast-large-text { +.spectrum-color-contrast .contrast-ratio-range, +.spectrum-color-contrast.range .contrast-ratio-single, +.spectrum-color-contrast.error .accessibility-color-contrast-separator, +.spectrum-color-contrast.error .contrast-ratio-max { display: none; } .contrast-ratio-label { + font-size: 10px; padding-inline-end: 4px; - padding-inline-start: 2px; color: var(--theme-toolbar-color); } -.spectrum-color-contrast .accessibility-color-contrast { - align-items: stretch; +.spectrum-color-contrast .accessibility-contrast-value { + font-size: 10px; + color: var(--theme-body-color); + border-bottom: 1px solid var(--learn-more-underline); } -.spectrum-color-contrast .accessibility-contrast-value { - color: var(--theme-body-color); - border-bottom: 1px solid var(--learn-more-underline); +.spectrum-color-contrast.visible:not(.error) .contrast-ratio-single .accessibility-contrast-value { + margin-inline-start: 10px; +} + +.spectrum-color-contrast.visible:not(.error) .contrast-ratio-min .accessibility-contrast-value, +.spectrum-color-contrast.visible:not(.error) .contrast-ratio-max .accessibility-contrast-value{ + margin-inline-start: 7px; } .spectrum-color-contrast .accessibility-contrast-value:not(:empty)::before { width: auto; content: none; padding-inline-start: 2px; } +.spectrum-color-contrast.visible:not(.error) .contrast-value-and-swatch:before { + display: inline-flex; + content: ""; + height: 9px; + width: 9px; + background-color: var(--accessibility-contrast-color); +} + +.spectrum-color-contrast.visible:not(.error):-moz-locale-dir(ltr) .contrast-value-and-swatch:before { + box-shadow: 0 0 0 1px var(--grey-40), 6px 5px var(--accessibility-contrast-bg), + 6px 5px 0 1px var(--grey-40); +} + +.spectrum-color-contrast.visible:not(.error):-moz-locale-dir(rtl) .contrast-value-and-swatch:before { + box-shadow: 0 0 0 1px var(--grey-40), -6px 5px var(--accessibility-contrast-bg), + -6px 5px 0 1px var(--grey-40); +} + +.spectrum-color-contrast .accessibility-color-contrast-separator:before { + margin-inline-end: 4px; + color: var(--theme-body-color); +} + +.spectrum-color-contrast .accessibility-color-contrast-large-text { + margin-inline-start: 1px; + margin-inline-end: 1px; + unicode-bidi: isolate; +} + .learn-more { - background-size: 12px 12px; background-repeat: no-repeat; -moz-context-properties: fill; background-image: url(chrome://devtools/skin/images/info-small.svg); background-color: transparent; fill: var(--theme-icon-dimmed-color); border: none; margin-inline-start: auto; - margin-block-start: 2px; + margin-block-start: 1px; +} + +.learn-more:-moz-locale-dir(ltr) { + margin-inline-end: -5px; +} + +.learn-more:-moz-locale-dir(rtl) { + margin-inline-end: -2px; } .learn-more:hover, .learn-more:focus { fill: var(--theme-icon-color); cursor: pointer; outline: none; }
--- a/devtools/client/shared/widgets/tooltip/SwatchColorPickerTooltip.js +++ b/devtools/client/shared/widgets/tooltip/SwatchColorPickerTooltip.js @@ -105,30 +105,31 @@ class SwatchColorPickerTooltip extends S async show() { // set contrast enabled for the spectrum const name = this.activeSwatch.dataset.propertyName; if (this.isContrastCompatible === undefined) { const target = this.inspector.target; this.isContrastCompatible = await target.actorHasMethod( "domnode", - "getClosestBackgroundColor" + "getBackgroundColor" ); } - // Only enable contrast and set spectrum text props if selected node is + // Only enable contrast and set text props and bg color if selected node is // contrast compatible and if the type of property is color. this.spectrum.contrastEnabled = name === "color" && this.isContrastCompatible; - this.spectrum.textProps = this.spectrum.contrastEnabled - ? await this.inspector.pageStyle.getComputed( - this.inspector.selection.nodeFront, - { filterProperties: ["font-size", "font-weight"] } - ) - : null; + if (this.spectrum.contrastEnabled) { + this.spectrum.textProps = await this.inspector.pageStyle.getComputed( + this.inspector.selection.nodeFront, + { filterProperties: ["font-size", "font-weight", "opacity"] } + ); + this.spectrum.backgroundColorData = await this.inspector.selection.nodeFront.getBackgroundColor(); + } // Then set spectrum's color and listen to color changes to preview them if (this.activeSwatch) { this.currentSwatchColor = this.activeSwatch.nextSibling; this._originalColor = this.currentSwatchColor.textContent; const color = this.activeSwatch.style.backgroundColor; this.spectrum.off("changed", this._onSpectrumColorChange);
--- a/devtools/client/themes/accessibility-color-contrast.css +++ b/devtools/client/themes/accessibility-color-contrast.css @@ -43,16 +43,21 @@ } .accessibility-color-contrast .accessibility-contrast-value:not(:empty).AAA:after { content: "AAA\2713"; unicode-bidi: isolate; } +.accessibility-color-contrast .accessibility-color-contrast-separator:before { + content: "–"; + margin-inline-start: 4px; +} + .accessibility-color-contrast-large-text { background-color: var(--badge-background-color); color: var(--badge-color); outline: 1px solid var(--badge-border-color); -moz-outline-radius: 3px; padding: 0px 2px; margin-inline-start: 6px; line-height: initial;