Fix drop shadow filters with multiple shadows (#17515)

It seems that I broke support for multiple drop-shadow filters when
`@theme inline` was used in v4.1. This PR fixes that by segmenting the
drop shadow value on top-level commas and wrapping each segment with
`drop-shadow(…)` like we did in v4.0.
This commit is contained in:
Jordan Pittman 2025-04-03 10:37:56 -04:00 • committed by GitHub
parent 3e41e9ffe6
commit e45302b910
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 67 additions and 4 deletions

View file

@ -11,6 +11,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Don't rely on `@layer base` for the `@property` polyfills ([#17506](https://github.com/tailwindlabs/tailwindcss/pull/17506))
- Fix multi-value inset shadow ([#17523](https://github.com/tailwindlabs/tailwindcss/pull/17523))
- Fix `drop-shadow` utility ([#17515](https://github.com/tailwindlabs/tailwindcss/pull/17515))
- Fix `drop-shadow-*` utilities that use multiple shadows in `@theme inline` ([#17515](https://github.com/tailwindlabs/tailwindcss/pull/17515))
## [4.1.1] - 2025-04-02

View file

@ -20366,6 +20366,9 @@ test('filter', async () => {
--drop-shadow: 0 1px 1px rgb(0 0 0 / 0.05);
--drop-shadow-xl: 0 9px 7px rgb(0 0 0 / 0.1);
}
@theme inline {
--drop-shadow-multi: 0 1px 1px rgb(0 0 0 / 0.05), 0 9px 7px rgb(0 0 0 / 0.1);
}
@tailwind utilities;
`,
[
@ -20392,6 +20395,7 @@ test('filter', async () => {
'drop-shadow',
'drop-shadow/25',
'drop-shadow-xl',
'drop-shadow-multi',
'drop-shadow-[0_0_red]',
'drop-shadow-red-500',
'drop-shadow-red-500/50',
@ -20486,6 +20490,12 @@ test('filter', async () => {
filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
}
.drop-shadow-multi {
--tw-drop-shadow-size: drop-shadow(0 1px 1px var(--tw-drop-shadow-color, #0000000d)) drop-shadow(0 9px 7px var(--tw-drop-shadow-color, #0000001a));
--tw-drop-shadow: drop-shadow(0 1px 1px #0000000d) drop-shadow(0 9px 7px #0000001a);
filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
}
.drop-shadow-xl {
--tw-drop-shadow-size: drop-shadow(0 9px 7px var(--tw-drop-shadow-color, #0000001a));
--tw-drop-shadow: drop-shadow(var(--drop-shadow-xl));

View file

@ -4298,7 +4298,8 @@ export function createUtilities(theme: Theme) {
if (!candidate.value) {
let value = theme.get(['--drop-shadow'])
if (value === null) return
let resolved = theme.resolve(null, ['--drop-shadow'])
if (value === null || resolved === null) return
return [
filterProperties(),
@ -4309,7 +4310,12 @@ export function createUtilities(theme: Theme) {
alpha,
(color) => `var(--tw-drop-shadow-color, ${color})`,
),
decl('--tw-drop-shadow', `drop-shadow(${theme.resolve(null, ['--drop-shadow'])})`),
decl(
'--tw-drop-shadow',
segment(resolved, ',')
.map((value) => `drop-shadow(${value})`)
.join(' '),
),
decl('filter', cssFilterValue),
]
}
@ -4350,7 +4356,8 @@ export function createUtilities(theme: Theme) {
// Shadow size
{
let value = theme.get([`--drop-shadow-${candidate.value.value}`])
if (value) {
let resolved = theme.resolve(candidate.value.value, ['--drop-shadow'])
if (value && resolved) {
if (candidate.modifier && !alpha) return
if (alpha) {
@ -4379,7 +4386,9 @@ export function createUtilities(theme: Theme) {
),
decl(
'--tw-drop-shadow',
`drop-shadow(${theme.resolve(candidate.value.value, ['--drop-shadow'])})`,
segment(resolved, ',')
.map((value) => `drop-shadow(${value})`)
.join(' '),
),
decl('filter', cssFilterValue),
]

View file

@ -1863,6 +1863,48 @@ test('drop shadow colors', async ({ page }) => {
])
})
test('multiple drop shadow filters with `@theme inline`', async ({ page }) => {
let { getPropertyList } = await render(
page,
html`
<div id="a" class="drop-shadow-inlined"></div>
<div id="b" class="drop-shadow-inlined drop-shadow-red"></div>
<div style="--drop-shadow-var: 0 20px 20px rgb(0 0 0 / 0.75)">
<div id="c" class="drop-shadow-var"></div>
</div>
<div style="--drop-shadow-var: 0 10px 10px rgb(0 0 0 / 0.75), 0 20px 20px rgb(0 0 0 / 0.75)">
<div id="d" class="drop-shadow-var"></div>
</div>
`,
css`
@theme {
--drop-shadow-var: 0 1px 1px rgb(0 0 0 / 0.5), 0 10px 10px rgb(0 0 0 / 0.25);
}
@theme inline {
--drop-shadow-inlined: 0 1px 1px rgb(0 0 0 / 0.5), 0 10px 10px rgb(0 0 0 / 0.25);
}
`,
)
expect(await getPropertyList('#a', 'filter')).toEqual([
'drop-shadow(rgba(0, 0, 0, 0.5) 0px 1px 1px) drop-shadow(rgba(0, 0, 0, 0.25) 0px 10px 10px)',
])
expect(await getPropertyList('#b', 'filter')).toEqual([
expect.stringMatching(
/drop-shadow\(oklab\(0\.627\d+ 0\.224\d+ 0\.125\d+\) 0px 1px 1px\) drop-shadow\(oklab\(0\.627\d+ 0\.224\d+ 0\.125\d+\) 0px 10px 10px\)/,
),
])
expect(await getPropertyList('#c', 'filter')).toEqual([
'drop-shadow(rgba(0, 0, 0, 0.75) 0px 20px 20px)',
])
// Multiple values are only supported with `@theme inline` because otherwise we use var(…)
// inside of drop-shadow(…) which can only ever be a single shadow
expect(await getPropertyList('#d', 'filter')).toEqual(['none'])
})
test('outline style is optional', async ({ page }) => {
let { getPropertyValue } = await render(
page,