From 2a6cd94b38659c80d4a349c5ebd7cc73386d9c0b Mon Sep 17 00:00:00 2001 From: Philipp Spiess Date: Fri, 15 Nov 2024 15:43:12 +0100 Subject: [PATCH] Bring back named opacity support for color opacity modifiers (#15009) This PR reverts https://github.com/tailwindlabs/tailwindcss/pull/14278 to bring back support for using named opacity values in color opacity modifiers: ```css @theme { --opacity-myOpacity: 50%; } ``` ```html
``` We briefly discuss to restructure the code so that we avoid adding a `theme` argument to the call sites but I do still prefer the current approach for the following reasons: The way to avoid this is to a) put something in either the `Theme` class scope, where it feels grossly out of place, or b) put it into the shared closure in the utilities file which is already very large and hard to reason. Furthermore, there's a second call site in the compile function where we would need to duplicate the namespace lookup. Every caller of the current `asColor` value already has access to the `Theme` so passing that as an argument seems like the least intrusive way. ## Test Plan Brought back the unit tests but I also tested it with the Vite extension: Screenshot 2024-11-15 at 11 15 05 --------- Co-authored-by: Adam Wathan --- CHANGELOG.md | 4 +- packages/tailwindcss/src/compile.ts | 2 +- packages/tailwindcss/src/utilities.test.ts | 14 ++++++- packages/tailwindcss/src/utilities.ts | 43 ++++++++++++++-------- 4 files changed, 44 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 356005dec..1dafd6313 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -- Nothing yet! +### Changed + +- Bring back support for color opacity modifiers to read from `--opacity-*` theme values ([#14278](https://github.com/tailwindlabs/tailwindcss/pull/14278)) ## [4.0.0-alpha.34] - 2024-11-14 diff --git a/packages/tailwindcss/src/compile.ts b/packages/tailwindcss/src/compile.ts index 4d3ee5dd2..81419ce77 100644 --- a/packages/tailwindcss/src/compile.ts +++ b/packages/tailwindcss/src/compile.ts @@ -263,7 +263,7 @@ function compileBaseUtility(candidate: Candidate, designSystem: DesignSystem) { // Assumption: If an arbitrary property has a modifier, then we assume it // is an opacity modifier. if (candidate.modifier) { - value = asColor(value, candidate.modifier) + value = asColor(value, candidate.modifier, designSystem.theme) } if (value === null) return [] diff --git a/packages/tailwindcss/src/utilities.test.ts b/packages/tailwindcss/src/utilities.test.ts index 167f7feb9..6c6808e97 100644 --- a/packages/tailwindcss/src/utilities.test.ts +++ b/packages/tailwindcss/src/utilities.test.ts @@ -10998,7 +10998,19 @@ test('bg', async () => { `, ['bg-current/half', 'bg-current/custom', '[color:red]/half'], ), - ).toEqual('') + ).toMatchInlineSnapshot(` + ".bg-current\\/custom { + background-color: color-mix(in oklch, currentColor var(--opacity-custom), transparent); + } + + .bg-current\\/half { + background-color: color-mix(in oklch, currentColor var(--opacity-half), transparent); + } + + .\\[color\\:red\\]\\/half { + color: color-mix(in oklch, red var(--opacity-half), transparent); + }" + `) }) test('from', async () => { diff --git a/packages/tailwindcss/src/utilities.ts b/packages/tailwindcss/src/utilities.ts index 0b93a10f7..2e2397cae 100644 --- a/packages/tailwindcss/src/utilities.ts +++ b/packages/tailwindcss/src/utilities.ts @@ -124,13 +124,24 @@ export function withAlpha(value: string, alpha: string): string { /** * Resolve a color value + optional opacity modifier to a final color. */ -export function asColor(value: string, modifier: CandidateModifier | null): string | null { +export function asColor( + value: string, + modifier: CandidateModifier | null, + theme: Theme, +): string | null { if (!modifier) return value if (modifier.kind === 'arbitrary') { return withAlpha(value, modifier.value) } + // Check if the modifier exists in the `opacity` theme configuration and use + // that value if so. + let alpha = theme.resolve(modifier.value, ['--opacity']) + if (alpha) { + return withAlpha(value, alpha) + } + if (!isValidOpacityValue(modifier.value)) { return null } @@ -182,7 +193,7 @@ function resolveThemeColor( } } - return value ? asColor(value, candidate.modifier) : null + return value ? asColor(value, candidate.modifier, theme) : null } export function createUtilities(theme: Theme) { @@ -340,7 +351,7 @@ export function createUtilities(theme: Theme) { value = candidate.value.value // Apply an opacity modifier to the value if appropriate. - value = asColor(value, candidate.modifier) + value = asColor(value, candidate.modifier, theme) } else { value = resolveThemeColor(candidate, theme, desc.themeKeys) } @@ -2048,7 +2059,7 @@ export function createUtilities(theme: Theme) { return [borderProperties(), ...decls] } default: { - value = asColor(value, candidate.modifier) + value = asColor(value, candidate.modifier, theme) if (value === null) return return desc.color(value) @@ -2510,7 +2521,7 @@ export function createUtilities(theme: Theme) { return [decl('background-image', value)] } default: { - value = asColor(value, candidate.modifier) + value = asColor(value, candidate.modifier, theme) if (value === null) return return [decl('background-color', value)] @@ -2584,7 +2595,7 @@ export function createUtilities(theme: Theme) { return desc.position(value) } default: { - value = asColor(value, candidate.modifier) + value = asColor(value, candidate.modifier, theme) if (value === null) return return desc.color(value) @@ -2721,7 +2732,7 @@ export function createUtilities(theme: Theme) { if (!candidate.value) return if (candidate.value.kind === 'arbitrary') { - let value = asColor(candidate.value.value, candidate.modifier) + let value = asColor(candidate.value.value, candidate.modifier, theme) if (value === null) return return [decl('fill', value)] } @@ -2758,7 +2769,7 @@ export function createUtilities(theme: Theme) { return [decl('stroke-width', value)] } default: { - value = asColor(candidate.value.value, candidate.modifier) + value = asColor(candidate.value.value, candidate.modifier, theme) if (value === null) return return [decl('stroke', value)] @@ -3002,7 +3013,7 @@ export function createUtilities(theme: Theme) { return [decl('text-decoration-thickness', value)] } default: { - value = asColor(value, candidate.modifier) + value = asColor(value, candidate.modifier, theme) if (value === null) return return [decl('text-decoration-color', value)] @@ -3880,7 +3891,7 @@ export function createUtilities(theme: Theme) { ] } default: { - value = asColor(value, candidate.modifier) + value = asColor(value, candidate.modifier, theme) if (value === null) return return [decl('outline-color', value)] @@ -4017,7 +4028,7 @@ export function createUtilities(theme: Theme) { return [decl('font-size', value)] } default: { - value = asColor(value, candidate.modifier) + value = asColor(value, candidate.modifier, theme) if (value === null) return return [decl('color', value)] @@ -4151,7 +4162,7 @@ export function createUtilities(theme: Theme) { switch (type) { case 'color': { - value = asColor(value, candidate.modifier) + value = asColor(value, candidate.modifier, theme) if (value === null) return return [boxShadowProperties(), decl('--tw-shadow-color', value)] @@ -4243,7 +4254,7 @@ export function createUtilities(theme: Theme) { switch (type) { case 'color': { - value = asColor(value, candidate.modifier) + value = asColor(value, candidate.modifier, theme) if (value === null) return return [boxShadowProperties(), decl('--tw-inset-shadow-color', value)] @@ -4341,7 +4352,7 @@ export function createUtilities(theme: Theme) { ] } default: { - value = asColor(value, candidate.modifier) + value = asColor(value, candidate.modifier, theme) if (value === null) return return [decl('--tw-ring-color', value)] @@ -4414,7 +4425,7 @@ export function createUtilities(theme: Theme) { ] } default: { - value = asColor(value, candidate.modifier) + value = asColor(value, candidate.modifier, theme) if (value === null) return return [decl('--tw-inset-ring-color', value)] @@ -4478,7 +4489,7 @@ export function createUtilities(theme: Theme) { ] } default: { - value = asColor(value, candidate.modifier) + value = asColor(value, candidate.modifier, theme) if (value === null) return return [decl('--tw-ring-offset-color', value)]