mirror of
https://github.com/tailwindlabs/tailwindcss.git
synced 2025-12-08 21:36:08 +00:00
Fix var(…) as the opacity value inside the theme(…) function (#14653)
Inside the `theme(…)` function, we can use the `/` character for
applying an opacity. For example `theme(colors.red.500 / 50%)` will
apply a 50% opacity to the `colors.red.500` value.
However, if you used a variable instead of the hardcoded `50%` value,
then this was not parsed correctly. E.g.: `theme(colors.red.500 /
var(--opacity))`
_If_ we have this exact syntax (with the spaces), then it parses, but
some information is lost:
```html
<div class="bg-[theme(colors.red.500_/_var(--opacity))]"></div>
```
Results in:
```css
.bg-\[theme\(colors\.red\.500_\/_var\(--opacity\)\)\] {
background-color: color-mix(in srgb, #ef4444 calc(var * 100%), transparent);
}
```
Notice that the `var(--opacity)` is just parsed as `var`, and the
`--opacity` is lost.
Additionally, if we drop the spaces, then it doesn't parse at all:
```html
<div class="bg-[theme(colors.red.500/var(--opacity))]"></div>
```
Results in:
```css
```
This means that we have to handle 2 issues to make this work:
1. We have to properly handle the `/` character as a proper separator.
2. If we have sub-functions, we have to make sure to print them in full
(instead of only the very first node (`var` in this case)).
This commit is contained in:
parent
a64e209888
commit
f2ebb8eb82
@ -33,6 +33,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- Pass options when using `addComponents` and `matchComponents` ([#14590](https://github.com/tailwindlabs/tailwindcss/pull/14590))
|
||||
- Ensure `boxShadow` and `animation` theme keys in JS config files are accessible under `--shadow-*` and `--animate-*` using the `theme()` function ([#14642](https://github.com/tailwindlabs/tailwindcss/pull/14642))
|
||||
- Ensure all theme keys with new names are also accessible under their old names when using the `theme()` function with the legacy dot notation syntax ([#14642](https://github.com/tailwindlabs/tailwindcss/pull/14642))
|
||||
- Ensure `var(…)` can be used as the opacity value inside the `theme([path] / [modifier])` function ([#14653](https://github.com/tailwindlabs/tailwindcss/pull/14653))
|
||||
- _Upgrade (experimental)_: Ensure CSS before a layer stays unlayered when running codemods ([#14596](https://github.com/tailwindlabs/tailwindcss/pull/14596))
|
||||
- _Upgrade (experimental)_: Resolve issues where some prefixed candidates were not properly migrated ([#14600](https://github.com/tailwindlabs/tailwindcss/pull/14600))
|
||||
|
||||
|
||||
@ -136,6 +136,27 @@ describe('theme function', () => {
|
||||
`)
|
||||
})
|
||||
|
||||
test('theme(colors.red.500/75%)', async () => {
|
||||
expect(
|
||||
await compileCss(css`
|
||||
@theme {
|
||||
--color-red-500: #f00;
|
||||
}
|
||||
.red {
|
||||
color: theme(colors.red.500/75%);
|
||||
}
|
||||
`),
|
||||
).toMatchInlineSnapshot(`
|
||||
":root {
|
||||
--color-red-500: red;
|
||||
}
|
||||
|
||||
.red {
|
||||
color: #ff0000bf;
|
||||
}"
|
||||
`)
|
||||
})
|
||||
|
||||
test('theme(colors.red.500 / 75%)', async () => {
|
||||
expect(
|
||||
await compileCss(css`
|
||||
@ -178,6 +199,49 @@ describe('theme function', () => {
|
||||
`)
|
||||
})
|
||||
|
||||
test('theme(colors.red.500/var(--opacity))', async () => {
|
||||
expect(
|
||||
await compileCss(css`
|
||||
@theme {
|
||||
--color-red-500: #f00;
|
||||
}
|
||||
.red {
|
||||
color: theme(colors.red.500/var(--opacity));
|
||||
}
|
||||
`),
|
||||
).toMatchInlineSnapshot(`
|
||||
":root {
|
||||
--color-red-500: red;
|
||||
}
|
||||
|
||||
.red {
|
||||
color: color-mix(in srgb, red calc(var(--opacity) * 100%), transparent);
|
||||
}"
|
||||
`)
|
||||
})
|
||||
|
||||
test('theme(colors.red.500/var(--opacity,50%))', async () => {
|
||||
expect(
|
||||
await compileCss(css`
|
||||
@theme {
|
||||
--color-red-500: #f00;
|
||||
}
|
||||
.red {
|
||||
/* prettier-ignore */
|
||||
color: theme(colors.red.500/var(--opacity,50%));
|
||||
}
|
||||
`),
|
||||
).toMatchInlineSnapshot(`
|
||||
":root {
|
||||
--color-red-500: red;
|
||||
}
|
||||
|
||||
.red {
|
||||
color: color-mix(in srgb, red calc(var(--opacity, 50%) * 100%), transparent);
|
||||
}"
|
||||
`)
|
||||
})
|
||||
|
||||
test('theme(spacing.12)', async () => {
|
||||
expect(
|
||||
await compileCss(css`
|
||||
|
||||
@ -68,7 +68,7 @@ export function substituteFunctionsInValue(
|
||||
if (node.nodes[i].value.includes(',')) {
|
||||
break
|
||||
}
|
||||
path += node.nodes[i].value
|
||||
path += ValueParser.toCss([node.nodes[i]])
|
||||
skipUntilIndex = i + 1
|
||||
}
|
||||
|
||||
|
||||
@ -66,6 +66,20 @@ describe('parse', () => {
|
||||
])
|
||||
})
|
||||
|
||||
it('should parse a function with nested arguments separated by `/`', () => {
|
||||
expect(parse('theme(colors.red.500/var(--opacity))')).toEqual([
|
||||
{
|
||||
kind: 'function',
|
||||
value: 'theme',
|
||||
nodes: [
|
||||
{ kind: 'word', value: 'colors.red.500' },
|
||||
{ kind: 'separator', value: '/' },
|
||||
{ kind: 'function', value: 'var', nodes: [{ kind: 'word', value: '--opacity' }] },
|
||||
],
|
||||
},
|
||||
])
|
||||
})
|
||||
|
||||
it('should handle calculations', () => {
|
||||
expect(parse('calc((1 + 2) * 3)')).toEqual([
|
||||
{
|
||||
|
||||
@ -114,6 +114,7 @@ const SPACE = 0x20
|
||||
const LESS_THAN = 0x3c
|
||||
const GREATER_THAN = 0x3e
|
||||
const EQUALS = 0x3d
|
||||
const SLASH = 0x2f
|
||||
|
||||
export function parse(input: string) {
|
||||
input = input.replaceAll('\r\n', '\n')
|
||||
@ -143,6 +144,7 @@ export function parse(input: string) {
|
||||
case COLON:
|
||||
case COMMA:
|
||||
case SPACE:
|
||||
case SLASH:
|
||||
case LESS_THAN:
|
||||
case GREATER_THAN:
|
||||
case EQUALS: {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user