fix(tailwind): convert modern CSS to legacy syntax for email client compatibility#3144
fix(tailwind): convert modern CSS to legacy syntax for email client compatibility#3144wesleyramalho wants to merge 3 commits intoresend:canaryfrom
Conversation
…ompatibility Tailwind v4 outputs CSS with range media queries (width>=40rem) and CSS nesting that email clients like Gmail on Android don't support. This adds a downlevelCss transformation step that converts range syntax to min-width/max-width and unnests rules to top-level @media blocks. Closes resend#3009
🦋 Changeset detectedLatest commit: c958bed The changes in this PR will be included in the next version bump. This PR includes changesets to release 3 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
@wesleyramalho is attempting to deploy a commit to the resend Team on Vercel. A member of the Team first needs to authorize it. |
commit: |
There was a problem hiding this comment.
2 issues found across 5 files
Confidence score: 2/5
- There is a high regression risk in
packages/tailwind/src/utils/css/downlevel-css.ts: resolving&appears to insert parent selector tokens in reverse order, which can change selector semantics (for example, descendant relationships flipping). - Nesting expansion in
packages/tailwind/src/utils/css/downlevel-css.tsreportedly uses only the first selector from a parentSelectorList, which can silently drop intended selectors and produce incomplete CSS output. - Given the medium-high severities (7/10 and 6/10) with strong confidence, this is likely user-facing behavior breakage rather than a minor cleanup issue.
- Pay close attention to
packages/tailwind/src/utils/css/downlevel-css.ts- selector ordering andSelectorListexpansion may generate incorrect or missing selectors.
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="packages/tailwind/src/utils/css/downlevel-css.ts">
<violation number="1" location="packages/tailwind/src/utils/css/downlevel-css.ts:211">
P2: Nesting resolution drops selectors by expanding `&` with only the first selector from a parent `SelectorList`.</violation>
<violation number="2" location="packages/tailwind/src/utils/css/downlevel-css.ts:218">
P1: Resolving `&` inserts parent selector tokens in reverse order, which can change selector meaning (e.g., `.foo .bar` becoming `.bar .foo`).</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
- Fix P1: insert parent selector tokens in correct order (insertData before the & node instead of tracking prev pointer) - Fix TS: define proper interfaces for css-tree v3 node types (FeatureRange, Feature) not yet in @types/css-tree@2.3.x - Type walk callback parameters explicitly
There was a problem hiding this comment.
1 issue found across 1 file (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="packages/tailwind/src/utils/css/downlevel-css.ts">
<violation number="1" location="packages/tailwind/src/utils/css/downlevel-css.ts:74">
P1: Nesting resolution only uses the first selector from a selector list, dropping additional parent selectors when replacing `&`.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
@cubic-dev-ai can you review again? |
@wesleyramalho I have started the AI code review. It will take a few minutes to complete. |
There was a problem hiding this comment.
1 issue found across 5 files
Confidence score: 3/5
- Nesting resolution in
packages/tailwind/src/utils/css/downlevel-css.tsonly expands&for the first selector, so multi-selector parents can lose selectors and change styling behavior. - This is a concrete, user-visible behavior change (severity 6/10), so there’s some regression risk despite being a single issue.
- Pay close attention to
packages/tailwind/src/utils/css/downlevel-css.ts- ensure&expansion preserves all parent selectors in selector lists.
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="packages/tailwind/src/utils/css/downlevel-css.ts">
<violation number="1" location="packages/tailwind/src/utils/css/downlevel-css.ts:267">
P2: Nesting resolution only expands `&` using the first selector in a selector list, so parent rules with multiple selectors (e.g., `.a, .b { &:hover { ... } }`) will drop additional selectors and change behavior.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
Summary
width>=40rem) and CSS nesting that email clients like Gmail on Android don't supportdownlevelCsstransformation step that converts range syntax tomin-width/max-widthand unnests rules to top-level@mediablocksCloses #3009
Before
After
Test plan
downlevelCss()covering range conversion, unnesting,&resolution, triple nesting, and passthrough (9 tests)Summary by cubic
Downlevels Tailwind v4 CSS to legacy syntax for email clients by converting range media queries and unnesting rules. Adds a
downlevelCssstep so styles render correctly in Gmail on Android and similar clients.downlevelCssto@react-email/tailwindto convert range media features tomin-width/max-width.@mediaand resolves&into top-level rules, preserving selector token order.Written for commit c958bed. Summary will update on new commits.