Skip to content

Commit

Permalink
fix: avoid infinite while loop with colorYiq (#2349)
Browse files Browse the repository at this point in the history
* fix: avoid never ending while loop with colorYiq
* fix: replace scss variable with css variable
  • Loading branch information
adamstankiewicz authored and PKulkoRaccoonGang committed Aug 1, 2024
1 parent 4cbad9a commit 95a682a
Show file tree
Hide file tree
Showing 7 changed files with 53 additions and 18 deletions.
2 changes: 1 addition & 1 deletion styles/css/core/custom-media-breakpoints.css
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* IMPORTANT: This file is the result of assembling design tokens
* Do not edit directly
* Generated on Thu, 01 Jun 2023 14:00:29 GMT
* Generated on Sat, 03 Jun 2023 13:27:55 GMT
*/

@custom-media --min-pgn-size-breakpoint-xs (min-width: 0);
Expand Down
2 changes: 1 addition & 1 deletion styles/css/core/variables.css
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* IMPORTANT: This file is the result of assembling design tokens
* Do not edit directly
* Generated on Thu, 01 Jun 2023 14:00:29 GMT
* Generated on Sat, 03 Jun 2023 13:27:55 GMT
*/

:root {
Expand Down
2 changes: 1 addition & 1 deletion styles/css/themes/light/utility-classes.css
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* IMPORTANT: This file is the result of assembling design tokens
* Do not edit directly
* Generated on Thu, 01 Jun 2023 14:00:29 GMT
* Generated on Sat, 03 Jun 2023 13:27:55 GMT
*/

.bg-accent-a {
Expand Down
2 changes: 1 addition & 1 deletion styles/css/themes/light/variables.css
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* IMPORTANT: This file is the result of assembling design tokens
* Do not edit directly
* Generated on Thu, 01 Jun 2023 14:00:29 GMT
* Generated on Sat, 03 Jun 2023 13:27:55 GMT
*/

:root {
Expand Down
45 changes: 34 additions & 11 deletions tokens/sass-helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,24 @@ const chroma = require('chroma-js');
* Javascript version of bootstrap's color-yiq function. Decides whether to return light color variant or dark one
* based on contrast value of the input color
*
* @param color - chroma-js color instance
* @param {String} [themeVariant] - theme variant name that will be used to find default contrast colors
* @param {String} [light] - light color variant from ./src/themes/{themeVariant}/global/other.json
* @param {String} [dark] - dark color variant from ./src/themes/{themeVariant}/global/other.json
* @param {Number} [threshold] - contrast threshold from ./src/core/global/other.json
* @param {Object} args
* @param {Object} args.tokenName - Name of design token, used to log warnings
* @param {Object} args.color - chroma-js color instance
* @param {String} args.light - light color variant from ./src/themes/{themeVariant}/global/other.json
* @param {String} args.dark - dark color variant from ./src/themes/{themeVariant}/global/other.json
* @param {Number} args.threshold - contrast threshold from ./src/core/global/other.json
* @param {String} [args.themeVariant] - theme variant name that will be used to find default contrast colors
*
* @return chroma-js color instance (one of dark or light variants)
*/
function colorYiq(color, light, dark, threshold, themeVariant = 'light') {
function colorYiq({
tokenName,
originalColor,
light,
dark,
threshold,
themeVariant = 'light',
}) {
const defaultThresholdFile = fs.readFileSync(path.resolve(__dirname, 'src/core/global', 'other.json'), 'utf8');
const defaultThreshold = JSON.parse(defaultThresholdFile)['yiq-contrasted-threshold'];

Expand All @@ -27,24 +37,37 @@ function colorYiq(color, light, dark, threshold, themeVariant = 'light') {
const lightColor = light || defaultLight;
const darkColor = dark || defaultDark;

const [r, g, b] = color.rgb();
const [r, g, b] = originalColor.rgb();
const yiq = ((r * 299) + (g * 587) + (b * 114)) * 0.001;

let result = yiq >= contrastThreshold ? chroma(darkColor) : chroma(lightColor);

const maxAttempts = 10; // maximum number of attempts to darken/brighten color to pass contrast ratio
if (yiq >= contrastThreshold) {
// check whether the resulting combination of colors passes a11y contrast ratio of 4:5:1
// if not - darken resulting color until it does
while (chroma.contrast(color, result) < 4.5) {
// if not - darken resulting color until it does until maxAttempts is reached.
let numDarkenAttempts = 1;
while (chroma.contrast(originalColor, result) < 4.5 && numDarkenAttempts <= maxAttempts) {
result = result.darken(0.1);
numDarkenAttempts += 1;
if (numDarkenAttempts === maxAttempts) {
// eslint-disable-next-line no-console
console.warn(`WARNING: Failed to darken ${tokenName} to pass contrast ratio of 4.5:1 (Original: ${originalColor.hex()}; Attempted: ${result.hex()}).`);
}
}
return result;
}

// check whether the resulting combination of colors passes a11y contrast ratio of 4:5:1
// if not - brighten resulting color until it does
while (chroma.contrast(color, result) < 4.5) {
// if not - brighten resulting color until it does until maxAttempts is reached.
let numBrightenAttempts = 1;
while (chroma.contrast(originalColor, result) < 4.5 && numBrightenAttempts <= maxAttempts) {
result = result.brighten(0.1);
numBrightenAttempts += 1;
if (numBrightenAttempts === maxAttempts) {
// eslint-disable-next-line no-console
console.warn(`WARNING: Failed to brighten ${tokenName} () to pass contrast ratio of 4.5:1 (Original: ${originalColor.hex()}; Attempted: ${result.hex()}).`);
}
}
return result;
}
Expand Down
16 changes: 14 additions & 2 deletions tokens/style-dictionary.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,12 @@ const cssUtilities = require('./css-utilities');
const { fileHeader, sortByReference } = StyleDictionary.formatHelpers;

const colorTransform = (token, theme) => {
const { value, modify = [], original } = token;
const {
name: tokenName,
value,
original,
modify = [],
} = token;
const reservedColorValues = ['inherit', 'initial', 'revert', 'unset', 'currentColor'];

if (reservedColorValues.includes(original.value)) {
Expand All @@ -27,7 +32,14 @@ const colorTransform = (token, theme) => {
break;
case 'color-yiq': {
const { light, dark, threshold } = modifier;
color = colorYiq(color, light, dark, threshold, theme);
color = colorYiq({
tokenName,
originalColor: color,
light,
dark,
threshold,
theme,
});
break;
}
case 'darken':
Expand Down
2 changes: 1 addition & 1 deletion www/src/components/Menu.scss
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
}

&-items {
margin-bottom: $spacer;
margin-bottom: var(--pgn-spacing-spacer-base);

.pgn_collapsible {
font-size: var(--pgn-typography-font-size-xs);
Expand Down

0 comments on commit 95a682a

Please sign in to comment.