fix(utilities): check staticValues before fallback theme keys
When `--spacing-none: 0` is defined in `@theme`, `theme.resolve('none',
['--leading', '--spacing'])` finds `--spacing-none` before the staticValues
fallback, causing `leading-none` to produce `line-height: 0` instead of
`line-height: 1`.
Fix by resolving against the primary theme key first, then checking
staticValues before falling back to secondary theme keys. This ensures
explicit static values like `leading-none` are not shadowed by unrelated
theme namespaces while still allowing `--leading-none` theme overrides.
Fixes #19722
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
c586bd6a94
commit
d04174ff12
2 changed files with 50 additions and 9 deletions
|
|
@ -24618,6 +24618,38 @@ test('leading', async () => {
|
|||
`)
|
||||
})
|
||||
|
||||
test('leading-none is not shadowed by --spacing-none', async () => {
|
||||
expect(
|
||||
await compileCss(
|
||||
css`
|
||||
@theme {
|
||||
--spacing-none: 0;
|
||||
}
|
||||
@tailwind utilities;
|
||||
`,
|
||||
['leading-none'],
|
||||
),
|
||||
).toMatchInlineSnapshot(`
|
||||
"@layer properties {
|
||||
@supports (((-webkit-hyphens: none)) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color: rgb(from red r g b)))) {
|
||||
*, :before, :after, ::backdrop {
|
||||
--tw-leading: initial;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.leading-none {
|
||||
--tw-leading: 1;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
@property --tw-leading {
|
||||
syntax: "*";
|
||||
inherits: false
|
||||
}"
|
||||
`)
|
||||
})
|
||||
|
||||
test('tracking', async () => {
|
||||
expect(
|
||||
await compileCss(
|
||||
|
|
|
|||
|
|
@ -414,10 +414,24 @@ export function createUtilities(theme: Theme) {
|
|||
value = candidate.value.value
|
||||
dataType = candidate.value.dataType
|
||||
} else {
|
||||
value = theme.resolve(
|
||||
candidate.value.fraction ?? candidate.value.value,
|
||||
desc.themeKeys ?? [],
|
||||
)
|
||||
let resolvedValue = candidate.value.fraction ?? candidate.value.value
|
||||
|
||||
// First try resolving against just the primary theme key.
|
||||
value = theme.resolve(resolvedValue, desc.themeKeys?.slice(0, 1) ?? [])
|
||||
|
||||
// If the primary theme key didn't match, check static values before
|
||||
// falling back to secondary theme keys (like `--spacing`). This
|
||||
// ensures e.g. `leading-none` produces `line-height: 1` even when
|
||||
// `--spacing-none` is defined in the theme.
|
||||
if (value === null && !negative && desc.staticValues && !candidate.modifier) {
|
||||
let fallback = desc.staticValues[candidate.value.value]
|
||||
if (fallback) return fallback.map(cloneAstNode)
|
||||
}
|
||||
|
||||
// Fall back to the full set of theme keys.
|
||||
if (value === null) {
|
||||
value = theme.resolve(resolvedValue, desc.themeKeys ?? [])
|
||||
}
|
||||
|
||||
// Automatically handle things like `w-1/2` without requiring `1/2` to
|
||||
// exist as a theme value.
|
||||
|
|
@ -439,11 +453,6 @@ export function createUtilities(theme: Theme) {
|
|||
value = desc.handleBareValue(candidate.value)
|
||||
if (!value?.includes('/') && candidate.modifier) return
|
||||
}
|
||||
|
||||
if (value === null && !negative && desc.staticValues && !candidate.modifier) {
|
||||
let fallback = desc.staticValues[candidate.value.value]
|
||||
if (fallback) return fallback.map(cloneAstNode)
|
||||
}
|
||||
}
|
||||
|
||||
// If there is no value, don't generate any rules.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue