Created
February 14, 2019 22:59
-
-
Save Falieson/ef445fd5574b1cd8404418405a322bf4 to your computer and use it in GitHub Desktop.
material-ui getContrastText()
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// tslint:disable | |
// MUI getContrastText | |
// REF: https://github.com/mui-org/material-ui/blob/ec37e2bb3c904d9552fa819425ee1eef72914996/packages/material-ui/src/styles/createPalette.js#L104 | |
import * as warning from './node_modules/warning/warning.js'; | |
export default function getContrastText({ | |
background, | |
contrastThreshold, | |
dark, | |
light, | |
}) { | |
warning( | |
background, | |
`Material-UI: missing background argument in getContrastText(${background}).`, | |
); | |
const contrastText = | |
getContrastRatio(background, dark.text.primary) >= contrastThreshold | |
? dark.text.primary | |
: light.text.primary; | |
if (process.env.NODE_ENV !== 'production') { | |
const contrast = getContrastRatio(background, contrastText); | |
warning( | |
contrast >= 3, | |
[ | |
`Material-UI: the contrast ratio of ${contrast}:1 for ${contrastText} on ${background}`, | |
'falls below the WACG recommended absolute minimum contrast ratio of 3:1.', | |
'https://www.w3.org/TR/2008/REC-WCAG20-20081211/#visual-audio-contrast-contrast', | |
].join('\n'), | |
); | |
} | |
return contrastText; | |
} | |
function getContrastRatio(foreground, background) { | |
warning( | |
foreground, | |
`Material-UI: missing foreground argument in getContrastRatio(${foreground}, ${background}).`, | |
); | |
warning( | |
background, | |
`Material-UI: missing background argument in getContrastRatio(${foreground}, ${background}).`, | |
); | |
const lumA = getLuminance(foreground); | |
const lumB = getLuminance(background); | |
return (Math.max(lumA, lumB) + 0.05) / (Math.min(lumA, lumB) + 0.05); | |
} | |
function getLuminance(color) { | |
warning(color, `Material-UI: missing color argument in getLuminance(${color}).`); | |
const decomposedColor = decomposeColor(color); | |
if (decomposedColor.type.indexOf('rgb') !== -1) { | |
const rgb = decomposedColor.values.map(val => { | |
val /= 255; // normalized | |
return val <= 0.03928 ? val / 12.92 : ((val + 0.055) / 1.055) ** 2.4; | |
}); | |
// Truncate at 3 digits | |
return Number((0.2126 * rgb[0] + 0.7152 * rgb[1] + 0.0722 * rgb[2]).toFixed(3)); | |
} | |
// else if (decomposedColor.type.indexOf('hsl') !== -1) | |
return decomposedColor.values[2] / 100; | |
} | |
function decomposeColor(color) { | |
if (color.charAt(0) === '#') { | |
return decomposeColor(convertHexToRGB(color)); | |
} | |
const marker = color.indexOf('('); | |
const type = color.substring(0, marker); | |
let values = color.substring(marker + 1, color.length - 1).split(','); | |
values = values.map(value => parseFloat(value)); | |
if (process.env.NODE_ENV !== 'production') { | |
if (['rgb', 'rgba', 'hsl', 'hsla'].indexOf(type) === -1) { | |
throw new Error( | |
[ | |
`Material-UI: unsupported \`${color}\` color.`, | |
'We support the following formats: #nnn, #nnnnnn, rgb(), rgba(), hsl(), hsla().', | |
].join('\n'), | |
); | |
} | |
} | |
return { type, values }; | |
} | |
function convertHexToRGB(color) { | |
color = color.substr(1); | |
const re = new RegExp(`.{1,${color.length / 3}}`, 'g'); | |
let colors = color.match(re); | |
if (colors && colors[0].length === 1) { | |
colors = colors.map(n => n + n); | |
} | |
return colors ? `rgb(${colors.map(n => parseInt(n, 16)).join(', ')})` : ''; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import indigo from '@material-ui/core/colors/indigo' | |
import red from '@material-ui/core/colors/red' | |
import teal from '@material-ui/core/colors/teal' | |
import { getContrastText } from '../mui/' | |
const contrastThreshold = 3 | |
// tslint:disable object-literal-sort-keys | |
const palette = { | |
primary: indigo, | |
secondary: teal, | |
error: red, | |
} | |
export default { | |
palette: { | |
type: 'dark', | |
primary: { | |
light: palette.primary[300], | |
main: palette.primary[500], | |
dark: palette.primary[700], | |
contrastText: getContrastText({ | |
background: palette.primary[500], | |
light: {text: {primary: palette.primary[300]}}, | |
dark: {text: {primary: palette.primary[700]}}, | |
contrastThreshold, | |
}), | |
}, | |
secondary: { | |
light: palette.secondary.A200, | |
main: palette.secondary.A400, | |
dark: palette.secondary.A700, | |
contrastText: getContrastText({ | |
background: palette.secondary[500], | |
light: {text: {primary: palette.secondary[300]}}, | |
dark: {text: {primary: palette.secondary[700]}}, | |
contrastThreshold, | |
}), | |
}, | |
error: { | |
light: palette.error[300], | |
main: palette.error[500], | |
dark: palette.error[700], | |
contrastText: getContrastText({ | |
background: palette.error[500], | |
light: {text: {primary: palette.error[300]}}, | |
dark: {text: {primary: palette.error[700]}}, | |
contrastThreshold, | |
}), | |
}, | |
// Used by `getContrastText()` to maximize the contrast between the background and | |
// the text. | |
contrastThreshold, | |
// Used to shift a color's luminance by approximately | |
// two indexes within its tonal palette. | |
// E.g., shift from Red 500 to Red 300 or Red 700. | |
tonalOffset: 0.2, | |
}, | |
spacing: 4, | |
typography: { | |
useNextVariants: true, | |
}, | |
} | |
// tslint:enable object-literal-sort-keys |
Author
Falieson
commented
Feb 14, 2019
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment