Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (14)
💤 Files with no reviewable changes (7)
🚧 Files skipped from review as they are similar to previous changes (2)
WalkthroughThis PR migrates the workspace to Tailwind v4.1.0 and the new PostCSS plugin: adds Possibly related PRs
Suggested labels
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. 📝 Coding Plan
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 |
Deploying usesend with
|
| Latest commit: |
16d6bb7
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://71304410.usesend.pages.dev |
| Branch Preview URL: | https://better-ui.usesend.pages.dev |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (3)
packages/ui/src/dropdown-menu.tsx (1)
50-50: Consider using idiomatic Tailwind v4 syntax for CSS variables.Per Tailwind v4 breaking changes, CSS variables in arbitrary values should use parentheses instead of brackets:
- Old (v3):
origin-[--radix-dropdown-menu-content-transform-origin]- New (v4):
origin-(--radix-dropdown-menu-content-transform-origin)The current
origin-[var(...)]syntax will work but wrapping invar()inside brackets isn't the idiomatic v4 approach.♻️ Suggested change for both occurrences
Line 50:
- "z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[var(--radix-dropdown-menu-content-transform-origin)]", + "z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-(--radix-dropdown-menu-content-transform-origin)",Line 68:
- "z-50 max-h-[var(--radix-dropdown-menu-content-available-height)] min-w-[8rem] overflow-y-auto overflow-x-hidden rounded-xl border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[var(--radix-dropdown-menu-content-transform-origin)]", + "z-50 max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem] overflow-y-auto overflow-x-hidden rounded-xl border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-(--radix-dropdown-menu-content-transform-origin)",Note: Line 68 also has
max-h-[var(--radix-dropdown-menu-content-available-height)]which should becomemax-h-(--radix-dropdown-menu-content-available-height).Also applies to: 68-68
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/ui/src/dropdown-menu.tsx` at line 50, The Tailwind classes in the Dropdown Menu component use legacy bracketed CSS-variable syntax; update the arbitrary-value usages to Tailwind v4 idiomatic parentheses. Replace occurrences of origin-[var(--radix-dropdown-menu-content-transform-origin)] with origin-(--radix-dropdown-menu-content-transform-origin) and max-h-[var(--radix-dropdown-menu-content-available-height)] with max-h-(--radix-dropdown-menu-content-available-height) in the className string(s) inside packages/ui/src/dropdown-menu.tsx (the dropdown content class that currently contains "origin-[var(...)]" and the one containing "max-h-[var(...)]") so they follow Tailwind v4 syntax.packages/ui/src/charts.tsx (1)
71-73: Avoid shadowingconfigin the filter callback.Using
configas the callback variable shadows the outerconfigprop and makes this block harder to read.♻️ Suggested readability tweak
- const colorConfig = Object.entries(config).filter( - ([_, config]) => config.theme || config.color, - ); + const colorConfig = Object.entries(config).filter( + ([_, itemConfig]) => itemConfig.theme || itemConfig.color, + );🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/ui/src/charts.tsx` around lines 71 - 73, The filter callback in the colorConfig computation shadows the outer config prop by reusing the name "config"; rename the inner destructured variable (e.g., from ([_, config]) to ([_, cfg]) or ([_, entry]) and update the predicate to use that new name so the expression becomes ([_, cfg]) => cfg.theme || cfg.color, ensuring the outer config prop is not shadowed and readability is improved for the colorConfig constant.apps/web/src/app/(dashboard)/dasboard-layout.tsx (1)
33-33: Remove duplicatedmin-w-0onSidebarInset.
SidebarInsetalready appliesmin-w-0in its base classes (packages/ui/src/sidebar.tsx, Lines 343-345), so this prop is redundant.♻️ Proposed cleanup
- <SidebarInset className="min-w-0"> + <SidebarInset>🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/web/src/app/`(dashboard)/dasboard-layout.tsx at line 33, The SidebarInset component is being passed a redundant className ("min-w-0") even though SidebarInset already includes min-w-0 in its base classes; remove the className="min-w-0" prop from the SidebarInset JSX in dasboard-layout.tsx (the SidebarInset element) so the component relies on its internal base classes and avoids duplicate/unused props.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/email-editor/src/styles/index.css`:
- Line 1: The CSS file uses the Tailwind v4 at-rule `@reference` "tailwindcss"
which will be flagged by linters; update project lint configs by adding
ignoreAtRules: ["reference","config","theme","source","custom-variant"] to
.stylelintrc.json rules and adjust biome.json to either exclude
packages/email-editor/src/styles/index.css from CSS parsing or add support for
Tailwind v4 directives so the `@reference` at-rule is not reported as invalid.
---
Nitpick comments:
In `@apps/web/src/app/`(dashboard)/dasboard-layout.tsx:
- Line 33: The SidebarInset component is being passed a redundant className
("min-w-0") even though SidebarInset already includes min-w-0 in its base
classes; remove the className="min-w-0" prop from the SidebarInset JSX in
dasboard-layout.tsx (the SidebarInset element) so the component relies on its
internal base classes and avoids duplicate/unused props.
In `@packages/ui/src/charts.tsx`:
- Around line 71-73: The filter callback in the colorConfig computation shadows
the outer config prop by reusing the name "config"; rename the inner
destructured variable (e.g., from ([_, config]) to ([_, cfg]) or ([_, entry])
and update the predicate to use that new name so the expression becomes ([_,
cfg]) => cfg.theme || cfg.color, ensuring the outer config prop is not shadowed
and readability is improved for the colorConfig constant.
In `@packages/ui/src/dropdown-menu.tsx`:
- Line 50: The Tailwind classes in the Dropdown Menu component use legacy
bracketed CSS-variable syntax; update the arbitrary-value usages to Tailwind v4
idiomatic parentheses. Replace occurrences of
origin-[var(--radix-dropdown-menu-content-transform-origin)] with
origin-(--radix-dropdown-menu-content-transform-origin) and
max-h-[var(--radix-dropdown-menu-content-available-height)] with
max-h-(--radix-dropdown-menu-content-available-height) in the className
string(s) inside packages/ui/src/dropdown-menu.tsx (the dropdown content class
that currently contains "origin-[var(...)]" and the one containing
"max-h-[var(...)]") so they follow Tailwind v4 syntax.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 66a062cf-d412-413d-b19b-e12b96985a8b
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (23)
apps/marketing/package.jsonapps/marketing/postcss.config.cjsapps/marketing/src/app/globals.cssapps/marketing/src/app/layout.tsxapps/marketing/tailwind.config.tsapps/web/package.jsonapps/web/postcss.config.cjsapps/web/src/app/(dashboard)/dasboard-layout.tsxapps/web/src/app/(dashboard)/webhooks/add-webhook.tsxapps/web/src/app/(dashboard)/webhooks/webhook-update-dialog.tsxapps/web/src/app/globals.cssapps/web/src/app/layout.tsxapps/web/src/components/AppSideBar.tsxpackages/email-editor/package.jsonpackages/email-editor/postcss.config.cjspackages/email-editor/src/styles/index.csspackages/tailwind-config/package.jsonpackages/tailwind-config/tailwind.config.tspackages/ui/package.jsonpackages/ui/src/charts.tsxpackages/ui/src/dropdown-menu.tsxpackages/ui/src/sidebar.tsxpackages/ui/styles/globals.css
💤 Files with no reviewable changes (2)
- packages/ui/styles/globals.css
- apps/marketing/tailwind.config.ts
| @@ -1,3 +1,5 @@ | |||
| @reference "tailwindcss"; | |||
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== CSS files using Tailwind v4 directives =="
rg -n --type=css '@reference|@theme|@source|@utility|@variant|@custom-variant|@config|@apply'
echo
echo "== Stylelint unknown-at-rule configuration =="
rg -n -C2 'scss/at-rule-no-unknown|at-rule-no-unknown|ignoreAtRules' .
echo
echo "== Biome/Stylelint config files =="
fd -HI 'biome.json|biome.jsonc|stylelint.config.*|.stylelintrc.*|.stylelintrc' -x sh -c 'echo "----- {} -----"; sed -n "1,220p" "{}"'Repository: usesend/useSend
Length of output: 1143
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== Finding Biome config files =="
find . -maxdepth 3 -type f \( -name "biome.json" -o -name "biome.jsonc" \) 2>/dev/null || echo "No biome config found"
echo
echo "== Finding Stylelint config files =="
find . -maxdepth 3 -type f \( -name ".stylelintrc*" -o -name "stylelint.config.*" \) 2>/dev/null || echo "No stylelint config found"
echo
echo "== Checking package.json for linting setup =="
find . -maxdepth 2 -name "package.json" -type f -exec grep -l "stylelint\|biome" {} \;Repository: usesend/useSend
Length of output: 209
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== Content of biome.json =="
cat biome.json
echo
echo "== Content of .stylelintrc.json =="
cat .stylelintrc.jsonRepository: usesend/useSend
Length of output: 2903
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== Checking for GitHub Actions workflows =="
find .github -type f -name "*.yml" -o -name "*.yaml" 2>/dev/null | head -5
echo
echo "== Checking package.json scripts for linting =="
find . -maxdepth 2 -name "package.json" -type f | xargs grep -l "lint" 2>/dev/null | head -3
echo
echo "== Root package.json lint scripts =="
grep -A 10 '"scripts"' ./package.json | grep -E 'lint|stylelint|biome' || echo "No lint scripts found"Repository: usesend/useSend
Length of output: 387
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== packages/email-editor/package.json =="
cat packages/email-editor/package.json 2>/dev/null || echo "File not found"
echo
echo "== Check for tailwind.config in email-editor =="
find packages/email-editor -name "tailwind.config.*" -o -name "postcss.config.*" 2>/dev/null
echo
echo "== Check for tailwind.config at root =="
ls -la tailwind.config.* postcss.config.* 2>/dev/null || echo "None found"
echo
echo "== All CSS files in email-editor =="
find packages/email-editor -name "*.css" -type fRepository: usesend/useSend
Length of output: 2328
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== postcss.config.cjs in email-editor =="
cat packages/email-editor/postcss.config.cjs
echo
echo "== tailwind.config.ts in email-editor =="
cat packages/email-editor/tailwind.config.ts
echo
echo "== Checking if Biome is configured to scan email-editor =="
grep -A 20 '"biome"' biome.json || echo "No biome workspace config found"Repository: usesend/useSend
Length of output: 546
Configure linting tools to support Tailwind v4 at-rules.
The @reference "tailwindcss" directive at line 1 will be flagged as invalid by both Biome and Stylelint without explicit configuration.
Update .stylelintrc.json to add ignoreAtRules: ["reference", "config", "theme", "source", "custom-variant"] to the rules, and configure biome.json to either skip CSS parsing for this file or add support for Tailwind v4 directives.
🧰 Tools
🪛 Biome (2.4.6)
[error] 1-1: Tailwind-specific syntax is disabled.
(parse)
🪛 Stylelint (17.4.0)
[error] 1-1: Unexpected unknown at-rule "@reference" (scss/at-rule-no-unknown)
(scss/at-rule-no-unknown)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@packages/email-editor/src/styles/index.css` at line 1, The CSS file uses the
Tailwind v4 at-rule `@reference` "tailwindcss" which will be flagged by linters;
update project lint configs by adding ignoreAtRules:
["reference","config","theme","source","custom-variant"] to .stylelintrc.json
rules and adjust biome.json to either exclude
packages/email-editor/src/styles/index.css from CSS parsing or add support for
Tailwind v4 directives so the `@reference` at-rule is not reported as invalid.
Summary
tailwindcssand switching PostCSS to@tailwindcss/postcssin web, marketing, ui, email-editor, and shared tailwind-config packagesglobals.cssfiles that import Tailwind v4 and shared UI globals via@config, preserving existing shared theme tokens and component stylesvar(...)syntax (for sidebar/dropdown/charts widths and origins), adding@reference "tailwindcss"for email-editor@apply, and resolving dashboard content overlap next to the fixed sidebarVerification
pnpm installpnpm --filter=@usesend/email-editor dev(build starts successfully; watch process runs)pnpm --filter=web exec next dev -p 3100 --turbopack(startup/compile succeeds)http://localhost:3000/contactsafter restart/hard refresh confirms sidebar/content no longer overlapSummary by cubic
Migrates the workspace to Tailwind CSS v4 with
@tailwindcss/postcss. Moves Tailwind setup into CSS directives and app-localglobals.css, and fixes v4 UI regressions in the sidebar, dropdowns, charts, and email editor.Dependencies
tailwindcssto v4 acrossweb,marketing,ui, andemail-editor; replace PostCSS plugin with@tailwindcss/postcss.@usesend/tailwind-configand all per-apptailwind.config.ts; define theme, plugins, and dark mode via CSS (@plugin,@theme,@custom-variant) in@usesend/uiglobals.globals.cssthat importstailwindcss, defines@sourceglobs, and imports@usesend/uiglobals.Bug Fixes
var(...)in dropdown widths/origin, chart tooltip colors, and sidebar widths.min-w-0,overflow-x-hidden, and resetting horizontal scroll on route changes.@applyinemail-editorby adding@reference "tailwindcss".Written for commit 16d6bb7. Summary will update on new commits.
Summary by CodeRabbit
Bug Fixes
Chores