diff --git a/tailwind.config.js b/tailwind.config.js index 08fb9819d..83c44d43e 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -1,4 +1,4 @@ -const { parseColorMatrix, withOpacityValue } = require('./tailwind/colors'); +const { parseColorMatrix } = require('./tailwind/colors'); module.exports = { content: ['./app/**/*.{html,js,ts,tsx}'], @@ -33,7 +33,7 @@ module.exports = { 'Noto Color Emoji', ], }, - colors: Object.assign(parseColorMatrix({ + colors: parseColorMatrix({ // Define color matrix (of available colors) // Colors are configured at runtime with CSS variables in soapbox.json gray: [50, 100, 200, 300, 400, 500, 600, 700, 800, 900], @@ -41,10 +41,9 @@ module.exports = { success: [50, 100, 200, 300, 400, 500, 600, 700, 800, 900], danger: [50, 100, 200, 300, 400, 500, 600, 700, 800, 900], accent: [300, 500], - }), { - 'gradient-purple': withOpacityValue('--color-gradient-purple'), - 'gradient-blue': withOpacityValue('--color-gradient-blue'), - 'sea-blue': withOpacityValue('--color-sea-blue'), + 'gradient-purple': true, + 'gradient-blue': true, + 'sea-blue': true, }), }, }, diff --git a/tailwind/__tests__/colors-test.js b/tailwind/__tests__/colors-test.js index 6bf314bf0..cf11f1461 100644 --- a/tailwind/__tests__/colors-test.js +++ b/tailwind/__tests__/colors-test.js @@ -30,6 +30,24 @@ describe('parseColorMatrix()', () => { // Colors are mapped to functions which return CSS values expect(result.primary[500]({})).toEqual('rgb(var(--color-primary-500))'); - expect(result.accent[300]({ opacityValue: .5 })).toEqual('rgb(var(--color-accent-300) / 0.5)'); + expect(result.accent[300]({ opacityValue: .3 })).toEqual('rgb(var(--color-accent-300) / 0.3)'); + }); + + it('parses single-tint values', () => { + const colorMatrix = { + gray: [50, 100, 200, 300, 400, 500, 600, 700, 800, 900], + primary: [50, 100, 200, 300, 400, 500, 600, 700, 800, 900], + success: [50, 100, 200, 300, 400, 500, 600, 700, 800, 900], + danger: [50, 100, 200, 300, 400, 500, 600, 700, 800, 900], + accent: [300, 500], + 'gradient-purple': true, + 'gradient-blue': true, + 'sea-blue': true, + }; + + const result = parseColorMatrix(colorMatrix); + + expect(result['sea-blue']({})).toEqual('rgb(var(--color-sea-blue))'); + expect(result['gradient-purple']({ opacityValue: .7 })).toEqual('rgb(var(--color-gradient-purple) / 0.7)'); }); }); diff --git a/tailwind/colors.js b/tailwind/colors.js index 9fd87e6ec..412de7d3f 100644 --- a/tailwind/colors.js +++ b/tailwind/colors.js @@ -8,19 +8,35 @@ function withOpacityValue(variable) { }; } -// Parse list of shades into Tailwind function with CSS variables -const parseShades = (color, shades) => { - return shades.reduce((obj, shade) => { - obj[shade] = withOpacityValue(`--color-${color}-${shade}`); - return obj; +// Parse a single color as a CSS variable +const toColorVariable = (colorName, tint = null) => { + const suffix = tint ? `-${tint}` : ''; + const variable = `--color-${colorName}${suffix}`; + + return withOpacityValue(variable); +}; + +// Parse list of tints into Tailwind function with CSS variables +const parseTints = (colorName, tints) => { + return tints.reduce((colorObj, tint) => { + colorObj[tint] = toColorVariable(colorName, tint); + return colorObj; }, {}); }; -// Parse color matrix into Tailwind colors object -const parseColorMatrix = colors => { - return Object.keys(colors).reduce((obj, color) => { - obj[color] = parseShades(color, colors[color]); - return obj; +// Parse color matrix into Tailwind color palette +const parseColorMatrix = colorMatrix => { + return Object.entries(colorMatrix).reduce((palette, colorData) => { + const [colorName, tints] = colorData; + + // Conditionally parse array or single-tint colors + if (Array.isArray(tints)) { + palette[colorName] = parseTints(colorName, tints); + } else if (tints === true) { + palette[colorName] = toColorVariable(colorName); + } + + return palette; }, {}); };