From 27c812e4f6029e60db6532d0fbd118f884e053e1 Mon Sep 17 00:00:00 2001 From: Robin Malfait Date: Wed, 1 Jun 2022 18:47:59 +0200 Subject: [PATCH 1/9] implement --- src/util/pluginUtils.js | 11 ++++++++++- src/util/withAlphaVariable.js | 4 ++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/util/pluginUtils.js b/src/util/pluginUtils.js index f3214df467a0..82d6bf630523 100644 --- a/src/util/pluginUtils.js +++ b/src/util/pluginUtils.js @@ -97,7 +97,11 @@ function splitAlpha(modifier) { export function asColor(modifier, options = {}, { tailwindConfig = {} } = {}) { if (options.values?.[modifier] !== undefined) { - return options.values?.[modifier] + let value = options.values?.[modifier] + if (typeof value === 'string' && value.includes('')) { + return ({ opacityValue = 1 }) => value.replace('', opacityValue) + } + return value } let [color, alpha] = splitAlpha(modifier) @@ -110,6 +114,11 @@ export function asColor(modifier, options = {}, { tailwindConfig = {} } = {}) { return undefined } + if (typeof normalizedColor === 'string' && normalizedColor.includes('')) { + let value = normalizedColor + normalizedColor = ({ opacityValue = 1 }) => value.replace('', opacityValue) + } + if (isArbitraryValue(alpha)) { return withAlphaValue(normalizedColor, alpha.slice(1, -1)) } diff --git a/src/util/withAlphaVariable.js b/src/util/withAlphaVariable.js index 00ed2be9740e..91b310f6edfe 100644 --- a/src/util/withAlphaVariable.js +++ b/src/util/withAlphaVariable.js @@ -5,6 +5,10 @@ export function withAlphaValue(color, alphaValue, defaultValue) { return color({ opacityValue: alphaValue }) } + if (typeof color === 'string' && color.includes('')) { + return color.replace('', alphaValue) + } + let parsed = parseColor(color) if (parsed === null) { From 7d890bd6ca27adfa08fe1c2e6726760461d264d5 Mon Sep 17 00:00:00 2001 From: Robin Malfait Date: Wed, 1 Jun 2022 18:48:46 +0200 Subject: [PATCH 2/9] remove `rgb`/`hsl` helpers, use `` instead --- src/util/resolveConfig.js | 30 ----- tests/evaluateTailwindFunctions.test.js | 12 +- tests/opacity.test.js | 157 +++++++++++++++++------- 3 files changed, 119 insertions(+), 80 deletions(-) diff --git a/src/util/resolveConfig.js b/src/util/resolveConfig.js index f4808cf687f5..783fc9261bf6 100644 --- a/src/util/resolveConfig.js +++ b/src/util/resolveConfig.js @@ -67,36 +67,6 @@ const configUtils = { {} ) }, - rgb(property) { - if (!property.startsWith('--')) { - throw new Error( - 'The rgb() helper requires a custom property name to be passed as the first argument.' - ) - } - - return ({ opacityValue }) => { - if (opacityValue === undefined || opacityValue === 1) { - return `rgb(var(${property}) / 1.0)` - } - - return `rgb(var(${property}) / ${opacityValue})` - } - }, - hsl(property) { - if (!property.startsWith('--')) { - throw new Error( - 'The hsl() helper requires a custom property name to be passed as the first argument.' - ) - } - - return ({ opacityValue }) => { - if (opacityValue === undefined || opacityValue === 1) { - return `hsl(var(${property}) / 1)` - } - - return `hsl(var(${property}) / ${opacityValue})` - } - }, } function value(valueToResolve, ...args) { diff --git a/tests/evaluateTailwindFunctions.test.js b/tests/evaluateTailwindFunctions.test.js index ecadb6edcb51..d14e95e85ce3 100644 --- a/tests/evaluateTailwindFunctions.test.js +++ b/tests/evaluateTailwindFunctions.test.js @@ -982,11 +982,11 @@ test('Theme function can extract alpha values for colors (7)', () => { return runFull(input, { theme: { - colors: ({ rgb }) => ({ + colors: { blue: { - 500: rgb('--foo'), + 500: 'rgb(var(--foo) / )', }, - }), + }, }, }).then((result) => { expect(result.css).toMatchCss(output) @@ -1009,11 +1009,11 @@ test('Theme function can extract alpha values for colors (8)', () => { return runFull(input, { theme: { - colors: ({ rgb }) => ({ + colors: { blue: { - 500: rgb('--foo'), + 500: 'rgb(var(--foo) / )', }, - }), + }, opacity: { myalpha: '50%', diff --git a/tests/opacity.test.js b/tests/opacity.test.js index 18b43ec01a00..38ea4ab44142 100644 --- a/tests/opacity.test.js +++ b/tests/opacity.test.js @@ -96,7 +96,7 @@ test('colors defined as functions work when opacity plugins are disabled', () => }) }) -it('can use rgb helper when defining custom properties for colors (opacity plugins enabled)', () => { +it('can use defining custom properties for colors (opacity plugins enabled)', () => { let config = { content: [ { @@ -117,9 +117,9 @@ it('can use rgb helper when defining custom properties for colors (opacity plugi }, ], theme: { - colors: ({ rgb }) => ({ - primary: rgb('--color-primary'), - }), + colors: { + primary: 'rgb(var(--color-primary) / )', + }, }, } @@ -192,9 +192,9 @@ it('can use rgb helper when defining custom properties for colors (opacity plugi }, ], theme: { - colors: ({ rgb }) => ({ - primary: rgb('--color-primary'), - }), + colors: { + primary: 'rgb(var(--color-primary) / )', + }, }, corePlugins: { backgroundOpacity: false, @@ -269,9 +269,9 @@ it('can use hsl helper when defining custom properties for colors (opacity plugi }, ], theme: { - colors: ({ hsl }) => ({ - primary: hsl('--color-primary'), - }), + colors: { + primary: 'hsl(var(--color-primary) / )', + }, }, } @@ -344,9 +344,9 @@ it('can use hsl helper when defining custom properties for colors (opacity plugi }, ], theme: { - colors: ({ hsl }) => ({ - primary: hsl('--color-primary'), - }), + colors: { + primary: 'hsl(var(--color-primary) / )', + }, }, corePlugins: { backgroundOpacity: false, @@ -400,34 +400,6 @@ it('can use hsl helper when defining custom properties for colors (opacity plugi }) }) -it('the rgb helper throws when not passing custom properties', () => { - let config = { - theme: { - colors: ({ rgb }) => ({ - primary: rgb('anything else'), - }), - }, - } - - return expect(run('@tailwind utilities', config)).rejects.toThrow( - 'The rgb() helper requires a custom property name to be passed as the first argument.' - ) -}) - -it('the hsl helper throws when not passing custom properties', () => { - let config = { - theme: { - colors: ({ hsl }) => ({ - primary: hsl('anything else'), - }), - }, - } - - return expect(run('@tailwind utilities', config)).rejects.toThrow( - 'The hsl() helper requires a custom property name to be passed as the first argument.' - ) -}) - test('Theme function in JS can apply alpha values to colors (1)', () => { let input = css` @tailwind utilities; @@ -611,11 +583,11 @@ test('Theme function in JS can apply alpha values to colors (7)', () => { content: [{ raw: html`text-foo` }], corePlugins: { textOpacity: false }, theme: { - colors: ({ rgb }) => ({ + colors: { blue: { - 500: rgb('--foo'), + 500: 'rgb(var(--foo) / )', }, - }), + }, extend: { textColor: ({ theme }) => ({ foo: theme('colors.blue.500 / var(--my-alpha)'), @@ -659,3 +631,100 @@ test('Theme function prefers existing values in config', () => { expect(result.warnings().length).toBe(0) }) }) + +it('should be possible to use an as part of the color definition', () => { + let config = { + content: [ + { + raw: html`
`, + }, + ], + corePlugins: ['backgroundColor', 'backgroundOpacity'], + theme: { + colors: { + primary: 'rgb(var(--color-primary) / )', + }, + }, + } + + return run('@tailwind utilities', config).then((result) => { + expect(result.css).toMatchCss(css` + .bg-primary { + --tw-bg-opacity: 1; + background-color: rgb(var(--color-primary) / var(--tw-bg-opacity)); + } + `) + }) +}) + +it('should be possible to use an as part of the color definition with an opacity modifiers', () => { + let config = { + content: [ + { + raw: html`
`, + }, + ], + corePlugins: ['backgroundColor', 'backgroundOpacity'], + theme: { + colors: { + primary: 'rgb(var(--color-primary) / )', + }, + }, + } + + return run('@tailwind utilities', config).then((result) => { + expect(result.css).toMatchCss(css` + .bg-primary\/50 { + background-color: rgb(var(--color-primary) / 0.5); + } + `) + }) +}) + +it('should be possible to use an as part of the color definition with an opacity modifiers', () => { + let config = { + content: [ + { + raw: html`
`, + }, + ], + corePlugins: ['backgroundColor'], + theme: { + colors: { + primary: 'rgb(var(--color-primary) / )', + }, + }, + } + + return run('@tailwind utilities', config).then((result) => { + expect(result.css).toMatchCss(css` + .bg-primary { + background-color: rgb(var(--color-primary) / 1); + } + `) + }) +}) + +it('should be possible to use inside arbitrary values', () => { + let config = { + content: [ + { + raw: html`
`, + }, + ], + corePlugins: ['backgroundColor', 'backgroundOpacity'], + theme: { + colors: { + primary: 'rgb(var(--color-primary) / )', + }, + }, + } + + return run('@tailwind utilities', config).then((result) => { + expect(result.css).toMatchCss(css` + .bg-\[rgb\(var\(--color-primary\)\/\\)\]\/50 { + background-color: rgb(var(--color-primary) / 0.5); + } + `) + }) +}) From 2bb7fdd6244e062c89073a1bb5cb26565d6b7c8e Mon Sep 17 00:00:00 2001 From: Robin Malfait Date: Wed, 1 Jun 2022 18:56:19 +0200 Subject: [PATCH 3/9] never pass undefined to `withAlphaValue` --- src/corePlugins.js | 4 ++++ src/util/withAlphaVariable.js | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/corePlugins.js b/src/corePlugins.js index aaf6fcdb45b1..0f8680df3bb8 100644 --- a/src/corePlugins.js +++ b/src/corePlugins.js @@ -1986,6 +1986,10 @@ export let corePlugins = { let ringOpacityDefault = theme('ringOpacity.DEFAULT', '0.5') + if (!theme('ringColor')?.DEFAULT) { + return `rgb(147 197 253 / ${ringOpacityDefault})` + } + return withAlphaValue( theme('ringColor')?.DEFAULT, ringOpacityDefault, diff --git a/src/util/withAlphaVariable.js b/src/util/withAlphaVariable.js index 91b310f6edfe..252669d26091 100644 --- a/src/util/withAlphaVariable.js +++ b/src/util/withAlphaVariable.js @@ -5,7 +5,7 @@ export function withAlphaValue(color, alphaValue, defaultValue) { return color({ opacityValue: alphaValue }) } - if (typeof color === 'string' && color.includes('')) { + if (color.includes('')) { return color.replace('', alphaValue) } From 13a336b9719a413b6ab6c3987037462cd834fb5e Mon Sep 17 00:00:00 2001 From: Robin Malfait Date: Wed, 1 Jun 2022 19:10:09 +0200 Subject: [PATCH 4/9] WIP --- src/util/resolveConfig.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/util/resolveConfig.js b/src/util/resolveConfig.js index 783fc9261bf6..effe32338452 100644 --- a/src/util/resolveConfig.js +++ b/src/util/resolveConfig.js @@ -8,6 +8,7 @@ import { toPath } from './toPath' import { normalizeConfig } from './normalizeConfig' import isPlainObject from './isPlainObject' import { cloneDeep } from './cloneDeep' +import { asColor } from './pluginUtils' import { withAlphaValue } from './withAlphaVariable' function isFunction(input) { @@ -185,7 +186,8 @@ function resolveFunctionKeys(object) { if (val !== undefined) { if (path.alpha !== undefined) { - return withAlphaValue(val, path.alpha) + let x = 'x' + return asColor(x, { values: { [x]: val } }, {})?.({ opacityValue: path.alpha }) } if (isPlainObject(val)) { From 79b27c1adebb64b54b4fcf0c14e760a870560493 Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Thu, 2 Jun 2022 09:57:20 -0400 Subject: [PATCH 5/9] WIP --- src/lib/evaluateTailwindFunctions.js | 2 ++ src/util/pluginUtils.js | 22 ++++++++++++++-------- src/util/resolveConfig.js | 10 +++++----- src/util/withAlphaVariable.js | 6 +----- 4 files changed, 22 insertions(+), 18 deletions(-) diff --git a/src/lib/evaluateTailwindFunctions.js b/src/lib/evaluateTailwindFunctions.js index bfeea5a52009..e525b89c3a1f 100644 --- a/src/lib/evaluateTailwindFunctions.js +++ b/src/lib/evaluateTailwindFunctions.js @@ -6,6 +6,7 @@ import { normalizeScreens } from '../util/normalizeScreens' import buildMediaQuery from '../util/buildMediaQuery' import { toPath } from '../util/toPath' import { withAlphaValue } from '../util/withAlphaVariable' +import { parseColorFormat } from '../util/pluginUtils.js' function isObject(input) { return typeof input === 'object' && input !== null @@ -181,6 +182,7 @@ export default function ({ tailwindConfig: config }) { } if (alpha !== undefined) { + value = parseColorFormat(value) value = withAlphaValue(value, alpha, value) } diff --git a/src/util/pluginUtils.js b/src/util/pluginUtils.js index 82d6bf630523..6dc3ed1fa939 100644 --- a/src/util/pluginUtils.js +++ b/src/util/pluginUtils.js @@ -18,6 +18,7 @@ import { shadow, } from './dataTypes' import negateValue from './negateValue' +import toColorValue from './toColorValue.js' export function updateAllClasses(selectors, updateClass) { let parser = selectorParser((selectors) => { @@ -95,13 +96,21 @@ function splitAlpha(modifier) { return [modifier.slice(0, slashIdx), modifier.slice(slashIdx + 1)] } +export function parseColorFormat(value) { + if (typeof value === 'string' && value.includes('')) { + let oldValue = value + + return ({ opacityValue = 1 }) => oldValue.replace('', opacityValue) + } + + return value +} + export function asColor(modifier, options = {}, { tailwindConfig = {} } = {}) { if (options.values?.[modifier] !== undefined) { let value = options.values?.[modifier] - if (typeof value === 'string' && value.includes('')) { - return ({ opacityValue = 1 }) => value.replace('', opacityValue) - } - return value + + return parseColorFormat(value) } let [color, alpha] = splitAlpha(modifier) @@ -114,10 +123,7 @@ export function asColor(modifier, options = {}, { tailwindConfig = {} } = {}) { return undefined } - if (typeof normalizedColor === 'string' && normalizedColor.includes('')) { - let value = normalizedColor - normalizedColor = ({ opacityValue = 1 }) => value.replace('', opacityValue) - } + normalizedColor = parseColorFormat(normalizedColor) if (isArbitraryValue(alpha)) { return withAlphaValue(normalizedColor, alpha.slice(1, -1)) diff --git a/src/util/resolveConfig.js b/src/util/resolveConfig.js index effe32338452..ffee66806f65 100644 --- a/src/util/resolveConfig.js +++ b/src/util/resolveConfig.js @@ -8,8 +8,9 @@ import { toPath } from './toPath' import { normalizeConfig } from './normalizeConfig' import isPlainObject from './isPlainObject' import { cloneDeep } from './cloneDeep' -import { asColor } from './pluginUtils' +import { asColor, normalizeColorAlpha, parseColorFormat, resolveColorAlpha } from './pluginUtils' import { withAlphaValue } from './withAlphaVariable' +import toColorValue from './toColorValue.js' function isFunction(input) { return typeof input === 'function' @@ -186,8 +187,9 @@ function resolveFunctionKeys(object) { if (val !== undefined) { if (path.alpha !== undefined) { - let x = 'x' - return asColor(x, { values: { [x]: val } }, {})?.({ opacityValue: path.alpha }) + let normalized = parseColorFormat(val) + + return withAlphaValue(normalized, path.alpha, toColorValue(normalized)) } if (isPlainObject(val)) { @@ -201,8 +203,6 @@ function resolveFunctionKeys(object) { return defaultValue } - // colors.red.500/50 - Object.assign(resolvePath, { theme: resolvePath, ...configUtils, diff --git a/src/util/withAlphaVariable.js b/src/util/withAlphaVariable.js index 252669d26091..15aedb73b66d 100644 --- a/src/util/withAlphaVariable.js +++ b/src/util/withAlphaVariable.js @@ -5,11 +5,7 @@ export function withAlphaValue(color, alphaValue, defaultValue) { return color({ opacityValue: alphaValue }) } - if (color.includes('')) { - return color.replace('', alphaValue) - } - - let parsed = parseColor(color) + let parsed = parseColor(color, { loose: true }) if (parsed === null) { return defaultValue From b4f898fbdbf004216c060b596807fc0ee69a904b Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Thu, 2 Jun 2022 10:00:32 -0400 Subject: [PATCH 6/9] WIP --- src/util/pluginUtils.js | 1 - src/util/resolveConfig.js | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/util/pluginUtils.js b/src/util/pluginUtils.js index 6dc3ed1fa939..7cd70bfec992 100644 --- a/src/util/pluginUtils.js +++ b/src/util/pluginUtils.js @@ -18,7 +18,6 @@ import { shadow, } from './dataTypes' import negateValue from './negateValue' -import toColorValue from './toColorValue.js' export function updateAllClasses(selectors, updateClass) { let parser = selectorParser((selectors) => { diff --git a/src/util/resolveConfig.js b/src/util/resolveConfig.js index ffee66806f65..aac15fefa713 100644 --- a/src/util/resolveConfig.js +++ b/src/util/resolveConfig.js @@ -8,7 +8,7 @@ import { toPath } from './toPath' import { normalizeConfig } from './normalizeConfig' import isPlainObject from './isPlainObject' import { cloneDeep } from './cloneDeep' -import { asColor, normalizeColorAlpha, parseColorFormat, resolveColorAlpha } from './pluginUtils' +import { parseColorFormat } from './pluginUtils' import { withAlphaValue } from './withAlphaVariable' import toColorValue from './toColorValue.js' From cef458b4db9358494a6407d32e35562a7e08849f Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Thu, 2 Jun 2022 10:01:47 -0400 Subject: [PATCH 7/9] WIP --- src/lib/evaluateTailwindFunctions.js | 2 +- src/util/resolveConfig.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/evaluateTailwindFunctions.js b/src/lib/evaluateTailwindFunctions.js index e525b89c3a1f..2b755394cbd0 100644 --- a/src/lib/evaluateTailwindFunctions.js +++ b/src/lib/evaluateTailwindFunctions.js @@ -6,7 +6,7 @@ import { normalizeScreens } from '../util/normalizeScreens' import buildMediaQuery from '../util/buildMediaQuery' import { toPath } from '../util/toPath' import { withAlphaValue } from '../util/withAlphaVariable' -import { parseColorFormat } from '../util/pluginUtils.js' +import { parseColorFormat } from '../util/pluginUtils' function isObject(input) { return typeof input === 'object' && input !== null diff --git a/src/util/resolveConfig.js b/src/util/resolveConfig.js index aac15fefa713..5472da08876f 100644 --- a/src/util/resolveConfig.js +++ b/src/util/resolveConfig.js @@ -10,7 +10,7 @@ import isPlainObject from './isPlainObject' import { cloneDeep } from './cloneDeep' import { parseColorFormat } from './pluginUtils' import { withAlphaValue } from './withAlphaVariable' -import toColorValue from './toColorValue.js' +import toColorValue from './toColorValue' function isFunction(input) { return typeof input === 'function' From 82635d63ae510c08e801f5bab09549e279893984 Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Thu, 2 Jun 2022 10:10:25 -0400 Subject: [PATCH 8/9] Update changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 60a0c664f4ee..19d9bfe7e448 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,7 +36,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added -- Add `rgb` and `hsl` color helpers for CSS variables ([#7665](https://github.com/tailwindlabs/tailwindcss/pull/7665)) - Support PostCSS `Document` nodes ([#7291](https://github.com/tailwindlabs/tailwindcss/pull/7291)) - Add `text-start` and `text-end` utilities ([#6656](https://github.com/tailwindlabs/tailwindcss/pull/6656)) - Support customizing class name when using `darkMode: 'class'` ([#5800](https://github.com/tailwindlabs/tailwindcss/pull/5800)) @@ -53,6 +52,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add opacity support when referencing colors with `theme` function ([#8416](https://github.com/tailwindlabs/tailwindcss/pull/8416)) - Add `postcss-import` support to the CLI ([#8437](https://github.com/tailwindlabs/tailwindcss/pull/8437)) - Add `optional` variant ([#8486](https://github.com/tailwindlabs/tailwindcss/pull/8486)) +- Add `` placeholder support for custom colors ([#8501](https://github.com/tailwindlabs/tailwindcss/pull/8501)) ## [3.0.24] - 2022-04-12 From cb6fdaeb00480b6ee1e4b3b94f8a476f28db3a2d Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Thu, 2 Jun 2022 10:17:58 -0400 Subject: [PATCH 9/9] Cleanup --- src/util/pluginUtils.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/util/pluginUtils.js b/src/util/pluginUtils.js index 7cd70bfec992..61a401822bf1 100644 --- a/src/util/pluginUtils.js +++ b/src/util/pluginUtils.js @@ -107,9 +107,7 @@ export function parseColorFormat(value) { export function asColor(modifier, options = {}, { tailwindConfig = {} } = {}) { if (options.values?.[modifier] !== undefined) { - let value = options.values?.[modifier] - - return parseColorFormat(value) + return parseColorFormat(options.values?.[modifier]) } let [color, alpha] = splitAlpha(modifier)