Support prefixed custom CSS imports#20274
Conversation
Allow `prefix(...)` on imported custom CSS files to scope `@utility` definitions from that import. Custom utilities from prefixed imports now use the public `prefix:utility` candidate format without making that prefix global for core utilities. Imported utility roots are tracked per prefix to avoid exposing unrelated utilities that happen to share the same internal name prefix. Adds coverage for: - custom imports inheriting the Tailwind import prefix - custom imports using their own prefix - prefixed custom imports not prefixing core utilities - avoiding collisions with unrelated `prefix-*` utilities
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
WalkthroughThe changes add import-prefix tracking for utilities, record imported utility roots during AST walking, and use that information to remap and filter parsed candidates. 🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/tailwindcss/src/index.ts`:
- Around line 636-639: The imported-utility candidate override in
designSystem.parseCandidate still lets the internal hyphenated form bypass the
prefix remap and reach parseCandidate(candidate), so ui-card or tw:ui-card can
resolve under the internal name. Update the fallback path in the parseCandidate
wrapper to filter out imported utility roots that were registered via
importedUtilityRootsByPrefix, and ensure the same check is applied in the later
matching branch near the second parseCandidate handling so only the public
prefix form is accepted.
- Around line 536-538: The nested `@theme` handling in index.ts is incorrectly
propagating prefix(...) from imported custom theme blocks into the global
theme.prefix, which can make core utilities unexpectedly require a custom
prefix. Update the logic around the `@theme` and `@utility` walk/processing so
prefix propagation only happens for imports that actually contain Tailwind
utilities (for example, guarded by containsTailwindUtilities), and ensure the
later `@theme` handler only sets theme.prefix for those Tailwind utility imports.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: d21dc37a-cb76-4ff5-85b7-be1f4ba2cbe9
📒 Files selected for processing (2)
packages/tailwindcss/src/index.tspackages/tailwindcss/src/prefix.test.ts
Confidence Score: 5/5Safe to merge. The change is well-scoped, the previously flagged variant-shadowing path now has a correct fallback and a dedicated test, and all standard prefix scenarios are covered by the new test suite. The core translation logic (external No files require special attention. The logic in Reviews (2): Last reviewed commit: "add test: variant order for prefixed imp..." | Re-trigger Greptile |
Summary
This PR makes
prefix(...)work for custom CSS imports that define@utilityrules.Why?
Developing libraries on top of Tailwind CSS may requires the users to use prefixes to avoid conflicts.
If 2 different imported libraries have the same class name, it should be possible to prefix one of them to avoid conflict.
in above code, if
lib1andlib2have same utility class names, and both are 3rd party libraries, we need a way to avoid this conflict.Example:
For example, a custom import like:
where
components.csscontains:can now generate the utility using the prefixed candidate:
The prefix is scoped to utilities imported from that file, so it does not prefix core utilities or expose unrelated utilities that happen to use the same internal name prefix.
This also preserves the existing behavior where
@import "tailwindcss" prefix(tw);configures the global Tailwind prefix.Test plan
All tests passing
Checked formatting:
Example:
Imported file:
button.css
Before this PR:
style.css
Result:
buttonstyle.css
Result:
tw:buttonstyle.css
Result:
tw:buttonAfter this PR:
style.css
✅ Same result:
buttonstyle.css
✅ Same result:
tw:buttonstyle.css
🆕 Result:
Now the custom imported file can have its own prefix.
ui:buttonI assume this won't be a breaking change since it does not change existing behavior, and
@import "./button" prefix(ui);was not doing anything and was never documented.Please let me know if anything needs to be changed.