UNPKG

@shopify/polaris

Version:

Shopify’s product component library

172 lines (171 loc) • 7.09 kB
import tokens from '@shopify/polaris-tokens'; import { colorToHsla, hslToString, hslToRgb } from '../color-transformers'; import { isLight } from '../color-validation'; import { constructColorName } from '../color-names'; import { createLightColor } from '../color-manipulation'; import { compose } from '../compose'; import { needsVariantList } from './config'; import colorAdjustmentsJson from './color-adjustments.json'; export function buildCustomProperties(themeConfig, globalTheming) { return globalTheming ? buildColors(themeConfig) : buildLegacyColors(themeConfig); } export function buildThemeContext(themeConfig, cssCustomProperties) { const { logo } = themeConfig; return { logo, // eslint-disable-next-line babel/camelcase UNSTABLE_cssCustomProperties: toString(cssCustomProperties), }; } function toString(obj) { if (obj) { return Object.entries(obj) .map((pair) => pair.join(':')) .join(';'); } else { return undefined; } } /* eslint-disable babel/camelcase */ // eslint-disable-next-line shopify/typescript/prefer-pascal-case-enums export var UNSTABLE_Color; (function (UNSTABLE_Color) { UNSTABLE_Color["Surface"] = "#FAFAFA"; UNSTABLE_Color["DarkSurface"] = "#111213"; UNSTABLE_Color["OnSurface"] = "#1F2225"; UNSTABLE_Color["Interactive"] = "#0870D9"; UNSTABLE_Color["Neutral"] = "#EAEAEB"; UNSTABLE_Color["Branded"] = "#008060"; UNSTABLE_Color["Critical"] = "#E32727"; UNSTABLE_Color["Warning"] = "#FFC453"; UNSTABLE_Color["Highlight"] = "#59D0C2"; UNSTABLE_Color["Success"] = "#008060"; })(UNSTABLE_Color || (UNSTABLE_Color = {})); export function buildColors(theme) { const colors = Object.assign({ surface: UNSTABLE_Color.Surface, onSurface: UNSTABLE_Color.OnSurface, interactive: UNSTABLE_Color.Interactive, neutral: UNSTABLE_Color.Neutral, branded: UNSTABLE_Color.Branded, critical: UNSTABLE_Color.Critical, warning: UNSTABLE_Color.Warning, highlight: UNSTABLE_Color.Highlight, success: UNSTABLE_Color.Success }, theme.UNSTABLE_colors); const surfaceColor = colorToHsla(colors.surface); const lightSurface = isLight(hslToRgb(surfaceColor)); const colorAdjustments = {}; Object.assign(colorAdjustments, colorAdjustmentsJson); const allColors = Object.entries(colorAdjustments).reduce((accumulator, [colorRole, colorAdjustment]) => { if (colorAdjustment == null) return accumulator; const baseColor = colorToHsla(colors[colorAdjustment.baseColor]); const { hue = baseColor.hue, saturation = baseColor.saturation, lightness = baseColor.lightness, alpha = baseColor.alpha, } = colorAdjustment[lightSurface ? 'light' : 'dark']; return Object.assign({}, accumulator, { [colorRole]: hslToString({ hue, saturation, lightness, alpha, }) }); }, {}); return customPropertyTransformer(Object.assign({}, allColors, overrides())); } /* eslint-enable babel/camelcase */ function overrides() { return { overrideNone: 'none', overrideTransparent: 'transparent', overrideOne: '1', overrideVisible: 'visible', buttonFontWeight: '500', nonNullContent: "''", borderRadiusBase: rem('4px'), borderRadiusWide: rem('8px'), bannerDefaultBorder: buildBannerBorder('--p-divider-on-surface'), bannerSuccessBorder: buildBannerBorder('--p-success-divider'), bannerHighlightBorder: buildBannerBorder('--p-highlight-divider'), bannerWarningBorder: buildBannerBorder('--p-warning-divider'), bannerCriticalBorder: buildBannerBorder('--p-critical-divider'), badgeMixBlendMode: 'luminosity', borderSubdued: `${rem('1px')} solid var(--p-divider-subdued-on-surface)`, textFieldSpinnerOffset: rem('2px'), textFieldFocusRingOffset: rem('-4px'), textFieldFocusRingBorderRadius: rem('7px'), }; } function customPropertyTransformer(properties) { return Object.entries(properties).reduce((transformed, [key, value]) => (Object.assign({}, transformed, { [toCssCustomPropertySyntax(key)]: value })), {}); } function toCssCustomPropertySyntax(camelCase) { return `--p-${camelCase.replace(/([A-Z0-9])/g, '-$1').toLowerCase()}`; } function rem(px) { const baseFontSize = 10; return `${parseInt(px, 10) / baseFontSize}rem`; } function buildBannerBorder(cssVar) { return `inset 0 ${rem('2px')} 0 0 var(${cssVar}), inset 0 0 0 ${rem('2px')} var(${cssVar})`; } function buildLegacyColors(theme) { let colorPairs; const colors = theme && theme.colors && theme.colors.topBar ? theme.colors.topBar : { background: '#00848e', backgroundLighter: '#1d9ba4', color: '#f9fafb' }; const colorKey = 'topBar'; const colorKeys = Object.keys(colors); if (colorKeys.length > 1) { colorPairs = colorKeys.map((key) => { return [constructColorName(colorKey, key), colors[key]]; }); } else { colorPairs = parseColors([colorKey, colors]); } return colorPairs.reduce((state, [key, value]) => (Object.assign({}, state, { [key]: value })), {}); } export function needsVariant(name) { return needsVariantList.indexOf(name) !== -1; } const lightenToString = compose(hslToString, createLightColor); export function setTextColor(name, variant = 'dark') { if (variant === 'light') { return [name, tokens.colorInk]; } return [name, tokens.colorWhite]; } export function setTheme(color, baseName, key, variant) { const colorPairs = []; switch (variant) { case 'light': colorPairs.push(setTextColor(constructColorName(baseName, null, 'color'), 'light')); colorPairs.push([ constructColorName(baseName, key, 'lighter'), lightenToString(color, 7, -10), ]); break; case 'dark': colorPairs.push(setTextColor(constructColorName(baseName, null, 'color'), 'dark')); colorPairs.push([ constructColorName(baseName, key, 'lighter'), lightenToString(color, 15, 15), ]); break; default: } return colorPairs; } function parseColors([baseName, colors]) { const keys = Object.keys(colors); const colorPairs = []; for (let i = 0; i < keys.length; i++) { colorPairs.push([constructColorName(baseName, keys[i]), colors[keys[i]]]); if (needsVariant(baseName)) { const hslColor = colorToHsla(colors[keys[i]]); if (typeof hslColor === 'string') { return colorPairs; } const rgbColor = hslToRgb(hslColor); if (isLight(rgbColor)) { colorPairs.push(...setTheme(hslColor, baseName, keys[i], 'light')); } else { colorPairs.push(...setTheme(hslColor, baseName, keys[i], 'dark')); } } } return colorPairs; }