diff --git a/CHANGELOG.md b/CHANGELOG.md index cfdcb3345375..37578fd727c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Don't scan `.geojson` files for classes by default ([#17700](https://github.com/tailwindlabs/tailwindcss/pull/17700)) - Hide default shadow suggestions when missing theme keys ([#17743](https://github.com/tailwindlabs/tailwindcss/pull/17743)) +- Replace `_` with `.` in theme suggestions for `@utility` if surrounded by digits ([#17743](https://github.com/tailwindlabs/tailwindcss/pull/17743)) ## [4.1.4] - 2025-04-14 diff --git a/packages/tailwindcss/src/intellisense.test.ts b/packages/tailwindcss/src/intellisense.test.ts index a135c40dd9b1..95d5d954d2ce 100644 --- a/packages/tailwindcss/src/intellisense.test.ts +++ b/packages/tailwindcss/src/intellisense.test.ts @@ -579,6 +579,10 @@ test('Theme keys with underscores are suggested with underscores', async () => { /* This will get suggeted with an underscore */ --spacing-logo_margin: 0.875rem; } + + @utility ex-* { + width: --value(--spacing- *); + } ` let design = await __unstable__loadDesignSystem(input, { @@ -588,15 +592,25 @@ test('Theme keys with underscores are suggested with underscores', async () => { }), }) - let entries = design.getClassList().filter(([name]) => name.startsWith('p-')) + let entries = design + .getClassList() + .filter(([name]) => name.startsWith('p-') || name.startsWith('ex-')) expect(entries).toContainEqual(['p-1.5', { modifiers: [] }]) expect(entries).toContainEqual(['p-2.5', { modifiers: [] }]) expect(entries).toContainEqual(['p-logo_margin', { modifiers: [] }]) + expect(entries).toContainEqual(['ex-1.5', { modifiers: [] }]) + expect(entries).toContainEqual(['ex-2.5', { modifiers: [] }]) + expect(entries).toContainEqual(['ex-logo_margin', { modifiers: [] }]) + expect(entries).not.toContainEqual(['p-1_5', { modifiers: [] }]) expect(entries).not.toContainEqual(['p-2_5', { modifiers: [] }]) expect(entries).not.toContainEqual(['p-logo.margin', { modifiers: [] }]) + + expect(entries).not.toContainEqual(['ex-1_5', { modifiers: [] }]) + expect(entries).not.toContainEqual(['ex-2_5', { modifiers: [] }]) + expect(entries).not.toContainEqual(['ex-logo.margin', { modifiers: [] }]) }) test('shadow utility default suggestions', async () => { diff --git a/packages/tailwindcss/src/utilities.ts b/packages/tailwindcss/src/utilities.ts index d19db5131d3f..c695ae13d106 100644 --- a/packages/tailwindcss/src/utilities.ts +++ b/packages/tailwindcss/src/utilities.ts @@ -266,6 +266,15 @@ function resolveThemeColor( return value ? asColor(value, candidate.modifier, theme) : null } +/** + * The alpha and beta releases used `_` in theme keys to represent a `.`. This meant we used + * `--leading-1_5` instead of `--leading-1\.5` to add utilities like `leading-1.5`. + * + * We prefer the use of the escaped dot now but still want to make sure suggestions for the + * legacy key format still works as expected when surrounded by numbers. + */ +const LEGACY_NUMERIC_KEY = /(\d+)_(\d+)/g + export function createUtilities(theme: Theme) { let utilities = new Utilities() @@ -273,15 +282,6 @@ export function createUtilities(theme: Theme) { * Register list of suggestions for a class */ function suggest(classRoot: string, defns: () => SuggestionDefinition[]) { - /** - * The alpha and beta releases used `_` in theme keys to represent a `.`. This meant we used - * `--leading-1_5` instead of `--leading-1\.5` to add utilities like `leading-1.5`. - * - * We prefer the use of the escaped dot now but still want to make sure suggestions for the - * legacy key format still works as expected when surrounded by numbers. - */ - const LEGACY_NUMERIC_KEY = /(\d+)_(\d+)/g - function* resolve(themeKeys: ThemeKey[]) { for (let value of theme.keysInNamespaces(themeKeys)) { yield value.replace(LEGACY_NUMERIC_KEY, (_, a, b) => { @@ -6060,7 +6060,11 @@ export function createCssUtility(node: AtRule) { // Suggest theme values. E.g.: `--value(--color-*)` for (let value of designSystem.theme.keysInNamespaces(themeKeys)) { - target.push(value) + target.push( + value.replace(LEGACY_NUMERIC_KEY, (_, a, b) => { + return `${a}.${b}` + }), + ) } }