Skip to content

Commit cf77420

Browse files
authored
Ensure --inset-ring=* and --inset-shadow-* variables are ignored by inset-* utilities (#14855)
This PR fixes a issue where utilities like `inset-x-*`, `left-*`, `top-*`, etc. mistakenly pull values from the `--inset-ring-*` and `--inset-shadow-*` theme namespaces. For example, the class `left-shadow-sm` currently generates this CSS: ```css .left-shadow-sm { left: var( --inset-shadow-sm, inset 0 1px 1px rgb(0 0 0 / 0.05) ); } ``` This happens because the `--inset-ring-*` and `--inset-shadow-*` namespaces collide with the `--inset-*` namespace. We were already handling this manually for just the `inset-*` utilities but didn't realize we needed to handle it for every related utility, so this PR fixes that. This also fixes an issue where IntelliSense would suggest classes like `inset-x-shadow-sm` when they shouldn't actually exist. To do this we've created this new concept of `ignoredThemeKeys` in the relevant APIs to make sure these are filtered out at the source. --------- Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
1 parent 63b321b commit cf77420

File tree

5 files changed

+461
-177
lines changed

5 files changed

+461
-177
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1212
- Detect classes in new files when using `@tailwindcss/postcss` ([#14829](https://github.com/tailwindlabs/tailwindcss/pull/14829))
1313
- Fix crash when using `@source` containing `..` ([#14831](https://github.com/tailwindlabs/tailwindcss/pull/14831))
1414
- Ensure instances of the same variant with different values are always sorted deterministically (e.g. `data-focus:flex` and `data-active:flex`) ([#14835](https://github.com/tailwindlabs/tailwindcss/pull/14835))
15+
- Ensure `--inset-ring=*` and `--inset-shadow-*` variables are ignored by `inset-*` utilities ([#14855](https://github.com/tailwindlabs/tailwindcss/pull/14855))
1516
- _Upgrade (experimental)_: Install `@tailwindcss/postcss` next to `tailwindcss` ([#14830](https://github.com/tailwindlabs/tailwindcss/pull/14830))
1617
- _Upgrade (experimental)_: Remove whitespace around `,` separator when print arbitrary values ([#14838](https://github.com/tailwindlabs/tailwindcss/pull/14838))
1718

packages/tailwindcss/src/intellisense.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ function loadDesignSystem() {
2222
theme.add('--perspective-normal', '500px')
2323
theme.add('--opacity-background', '0.3')
2424
theme.add('--drop-shadow-sm', '0 1px 1px rgb(0 0 0 / 0.05)')
25+
theme.add('--inset-shadow-sm', 'inset 0 1px 1px rgb(0 0 0 / 0.05)')
26+
theme.add('--inset-ring-big', '100px')
2527
return buildDesignSystem(theme)
2628
}
2729

packages/tailwindcss/src/theme.ts

Lines changed: 40 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@ export const enum ThemeOptions {
88
DEFAULT = 1 << 2,
99
}
1010

11+
function isIgnoredThemeKey(themeKey: ThemeKey, ignoredThemeKeys: ThemeKey[]) {
12+
return ignoredThemeKeys.some(
13+
(ignoredThemeKey) => themeKey === ignoredThemeKey || themeKey.startsWith(`${ignoredThemeKey}-`),
14+
)
15+
}
16+
1117
export class Theme {
1218
public prefix: string | null = null
1319

@@ -44,20 +50,22 @@ export class Theme {
4450
}
4551
}
4652

47-
keysInNamespaces(themeKeys: ThemeKey[]): string[] {
53+
keysInNamespaces(themeKeys: ThemeKey[], ignoredThemeKeys: ThemeKey[] = []): string[] {
4854
let keys: string[] = []
4955

5056
for (let prefix of themeKeys) {
5157
let namespace = `${prefix}-`
5258

5359
for (let key of this.values.keys()) {
54-
if (key.startsWith(namespace)) {
55-
if (key.indexOf('--', 2) !== -1) {
56-
continue
57-
}
60+
if (!key.startsWith(namespace)) continue
61+
62+
if (key.indexOf('--', 2) !== -1) continue
5863

59-
keys.push(key.slice(namespace.length))
64+
if (isIgnoredThemeKey(key as ThemeKey, ignoredThemeKeys)) {
65+
continue
6066
}
67+
68+
keys.push(key.slice(namespace.length))
6169
}
6270
}
6371

@@ -111,14 +119,21 @@ export class Theme {
111119
}
112120
}
113121

114-
#resolveKey(candidateValue: string | null, themeKeys: ThemeKey[]): string | null {
122+
#resolveKey(
123+
candidateValue: string | null,
124+
themeKeys: ThemeKey[],
125+
ignoredThemeKeys: ThemeKey[] = [],
126+
): string | null {
115127
for (let key of themeKeys) {
116128
let themeKey =
117-
candidateValue !== null ? escape(`${key}-${candidateValue.replaceAll('.', '_')}`) : key
129+
candidateValue !== null
130+
? (escape(`${key}-${candidateValue.replaceAll('.', '_')}`) as ThemeKey)
131+
: key
118132

119-
if (this.values.has(themeKey)) {
120-
return themeKey
121-
}
133+
if (!this.values.has(themeKey)) continue
134+
if (isIgnoredThemeKey(themeKey, ignoredThemeKeys)) continue
135+
136+
return themeKey
122137
}
123138

124139
return null
@@ -132,8 +147,12 @@ export class Theme {
132147
return `var(${this.#prefixKey(themeKey)}, ${this.values.get(themeKey)?.value})`
133148
}
134149

135-
resolve(candidateValue: string | null, themeKeys: ThemeKey[]): string | null {
136-
let themeKey = this.#resolveKey(candidateValue, themeKeys)
150+
resolve(
151+
candidateValue: string | null,
152+
themeKeys: ThemeKey[],
153+
ignoredThemeKeys: ThemeKey[] = [],
154+
): string | null {
155+
let themeKey = this.#resolveKey(candidateValue, themeKeys, ignoredThemeKeys)
137156

138157
if (!themeKey) return null
139158

@@ -146,8 +165,12 @@ export class Theme {
146165
return this.#var(themeKey)
147166
}
148167

149-
resolveValue(candidateValue: string | null, themeKeys: ThemeKey[]): string | null {
150-
let themeKey = this.#resolveKey(candidateValue, themeKeys)
168+
resolveValue(
169+
candidateValue: string | null,
170+
themeKeys: ThemeKey[],
171+
ignoredThemeKeys: ThemeKey[] = [],
172+
): string | null {
173+
let themeKey = this.#resolveKey(candidateValue, themeKeys, ignoredThemeKeys)
151174

152175
if (!themeKey) return null
153176

@@ -158,8 +181,9 @@ export class Theme {
158181
candidateValue: string,
159182
themeKeys: ThemeKey[],
160183
nestedKeys: `--${string}`[] = [],
184+
ignoredThemeKeys: ThemeKey[] = [],
161185
): [string, Record<string, string>] | null {
162-
let themeKey = this.#resolveKey(candidateValue, themeKeys)
186+
let themeKey = this.#resolveKey(candidateValue, themeKeys, ignoredThemeKeys)
163187

164188
if (!themeKey) return null
165189

0 commit comments

Comments
 (0)