Skip to content

Commit 6f5cb91

Browse files
authored
feat(preview-server): update to tailwindcss@v4 (#2720)
1 parent 8e6ae06 commit 6f5cb91

23 files changed

+725
-291
lines changed

.changeset/tender-buckets-sin.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@react-email/preview-server": patch
3+
---
4+
5+
use tailwindcss v4 in the UI

biome.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@
77
}
88
}
99
},
10+
"css": {
11+
"parser": {
12+
"tailwindDirectives": true
13+
}
14+
},
1015
"vcs": {
1116
"enabled": true,
1217
"clientKind": "git",

packages/preview-server/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
"@radix-ui/react-tooltip": "1.2.8",
3232
"@react-email/components": "workspace:*",
3333
"@react-email/tailwind": "workspace:2.0.1",
34+
"@tailwindcss/postcss": "4.1.17",
3435
"@types/babel__core": "7.20.5",
3536
"@types/babel__traverse": "7.20.7",
3637
"@types/css-tree": "2.3.10",
@@ -41,7 +42,6 @@
4142
"@types/react": "19.0.10",
4243
"@types/react-dom": "19.0.4",
4344
"@types/webpack": "5.28.5",
44-
"autoprefixer": "10.4.21",
4545
"clsx": "2.1.1",
4646
"colorjs.io": "0.5.2",
4747
"esbuild": "0.25.10",
@@ -63,7 +63,7 @@
6363
"source-map-js": "1.2.1",
6464
"stacktrace-parser": "0.1.11",
6565
"tailwind-merge": "3.2.0",
66-
"tailwindcss": "3.4.0",
66+
"tailwindcss": "4.1.17",
6767
"typescript": "5.8.3",
6868
"use-debounce": "10.0.4",
6969
"zod": "4.1.12"
Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
1-
const path = require('node:path');
2-
31
module.exports = {
42
plugins: {
5-
tailwindcss: { config: path.resolve(__dirname, 'tailwind.config.ts') },
6-
autoprefixer: {},
3+
'@tailwindcss/postcss': {},
74
},
85
};

packages/preview-server/src/app/globals.css

Lines changed: 124 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,127 @@
1-
@tailwind base;
2-
@tailwind components;
3-
@tailwind utilities;
1+
@import "tailwindcss";
2+
3+
@theme {
4+
--background-image-gradient: linear-gradient(
5+
145.37deg,
6+
rgba(255, 255, 255, 0.09) -8.75%,
7+
rgba(255, 255, 255, 0.027) 83.95%
8+
);
9+
--background-image-gradient-hover: linear-gradient(
10+
145.37deg,
11+
rgba(255, 255, 255, 0.1) -8.75%,
12+
rgba(255, 255, 255, 0.057) 83.95%
13+
);
14+
--background-image-shine: linear-gradient(
15+
45deg,
16+
rgba(255, 255, 255, 0) 45%,
17+
rgba(255, 255, 255, 1) 50%,
18+
rgba(255, 255, 255, 0) 55%,
19+
rgba(255, 255, 255, 0) 100%
20+
);
21+
22+
--color-cyan-1: #0091f70a;
23+
--color-cyan-2: #02a7f211;
24+
--color-cyan-3: #00befd28;
25+
--color-cyan-4: #00baff3b;
26+
--color-cyan-5: #00befd4d;
27+
--color-cyan-6: #00c7fd5e;
28+
--color-cyan-7: #14cdff75;
29+
--color-cyan-8: #11cfff95;
30+
--color-cyan-9: #00cfffc3;
31+
--color-cyan-10: #28d6ffcd;
32+
--color-cyan-11: #52e1fee5;
33+
--color-cyan-12: #bbf3fef7;
34+
35+
--color-slate-1: #00000000;
36+
--color-slate-2: #d8f4f609;
37+
--color-slate-3: #ddeaf814;
38+
--color-slate-4: #d3edf81d;
39+
--color-slate-5: #d9edfe25;
40+
--color-slate-6: #d6ebfd30;
41+
--color-slate-7: #d9edff40;
42+
--color-slate-8: #d9edff5d;
43+
--color-slate-9: #dfebfd6d;
44+
--color-slate-10: #e5edfd7b;
45+
--color-slate-11: #f1f7feb5;
46+
--color-slate-12: #fcfdffef;
47+
48+
--font-sans:
49+
var(--font-inter), ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji",
50+
"Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
51+
--font-mono:
52+
var(--font-sf-mono), ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
53+
"Liberation Mono", "Courier New", monospace;
54+
55+
--animate-spin-slow: spin 3s linear infinite;
56+
--animate-spin-fast: spin 1.5s linear infinite;
57+
58+
@keyframes shine {
59+
0% {
60+
background-position: -100%;
61+
}
62+
63+
100% {
64+
background-position: 100%;
65+
}
66+
}
67+
68+
@keyframes dash {
69+
0% {
70+
stroke-dashoffset: 1000;
71+
}
72+
73+
100% {
74+
stroke-dashoffset: 0;
75+
}
76+
}
77+
78+
@keyframes spin {
79+
0% {
80+
transform: rotate(0deg);
81+
}
82+
83+
100% {
84+
transform: rotate(360deg);
85+
}
86+
}
87+
}
88+
89+
@utility arrow-hide {
90+
appearance: textfield;
91+
92+
&::-webkit-inner-spin-button {
93+
appearance: none;
94+
margin: 0px;
95+
}
96+
97+
&::-webkit-outer-spin-button {
98+
appearance: none;
99+
margin: 0px;
100+
}
101+
}
102+
103+
/*
104+
The default border color has changed to `currentcolor` in Tailwind CSS v4,
105+
so we've added these compatibility styles to make sure everything still
106+
looks the same as it did with Tailwind CSS v3.
107+
108+
If we ever want to remove these styles, we need to add an explicit border
109+
color utility to any element that depends on these defaults.
110+
*/
111+
@layer base {
112+
*,
113+
::after,
114+
::before,
115+
::backdrop,
116+
::file-selector-button {
117+
border-color: var(--color-gray-200, currentcolor);
118+
}
119+
120+
button:not(:disabled),
121+
[role="button"]:not(:disabled) {
122+
cursor: pointer;
123+
}
124+
}
4125

5126
html {
6127
color-scheme: dark;

packages/preview-server/src/app/layout.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ export default async function RootLayout({
3333
lang="en"
3434
>
3535
<body className="relative h-screen bg-black text-slate-11 leading-loose selection:bg-cyan-5 selection:text-cyan-12">
36-
<div className="bg-gradient-to-t from-slate-3 flex flex-col">
36+
<div className="bg-linear-to-t from-slate-3 flex flex-col">
3737
<EmailsProvider
3838
initialEmailsDirectoryMetadata={emailsDirectoryMetadata}
3939
>

packages/preview-server/src/app/preview/[...slug]/error-overlay.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,17 +36,17 @@ export const ErrorOverlay = ({ error }: ErrorOverlayProps) => {
3636
min-h-[50vh] w-full max-w-lg sm:rounded-lg md:max-w-[568px] lg:max-w-[920px]
3737
absolute left-[50%] top-[50%] z-50 translate-x-[-50%] translate-y-[-50%]
3838
rounded-t-sm overflow-hidden bg-white text-black shadow-lg duration-200
39-
flex flex-col selection:!text-black
39+
flex flex-col selection:text-black!
4040
"
4141
>
4242
<div className="bg-red-500 h-3" />
43-
<div className="flex flex-grow p-6 min-w-0 max-w-full flex-col space-y-1.5">
44-
<div className="flex-shrink pb-2 text-xl tracking-tight">
43+
<div className="flex grow p-6 min-w-0 max-w-full flex-col space-y-1.5">
44+
<div className="shrink pb-2 text-xl tracking-tight">
4545
<b>{error.name}</b>: <Message>{error.message}</Message>
4646
</div>
4747
{error.stack ? (
48-
<div className="flex-grow scroll-px-4 overflow-x-auto rounded-lg bg-black p-2 text-gray-100">
49-
<pre className="w-full min-w-0 font-mono leading-6 selection:!text-cyan-12 text-xs">
48+
<div className="grow scroll-px-4 overflow-x-auto rounded-lg bg-black p-2 text-gray-100">
49+
<pre className="w-full min-w-0 font-mono leading-6 selection:text-cyan-12! text-xs">
5050
{error.stack}
5151
</pre>
5252
</div>

packages/preview-server/src/components/button.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,14 +70,14 @@ const getAppearance = (appearance: Appearance | undefined) => {
7070
return [
7171
'border-white bg-white text-black transition-colors duration-200 ease-in-out',
7272
'hover:bg-white/90',
73-
'focus:bg-white/90 focus:outline-none focus:ring-2 focus:ring-white/20',
73+
'focus:bg-white/90 focus:outline-hidden focus:ring-2 focus:ring-white/20',
7474
'mt-2 mb-2 aria-disabled:border-transparent aria-disabled:bg-slate-11',
7575
];
7676
case 'gradient':
7777
return [
7878
'bg-gradient border-[#34343A] backdrop-blur-[1.25rem]',
79-
'hover:bg-gradientHover',
80-
'focus:bg-gradientHover focus:outline-none focus:ring-2 focus:ring-white/20',
79+
'hover:bg-gradient-hover',
80+
'focus:bg-gradient-hover focus:outline-hidden focus:ring-2 focus:ring-white/20',
8181
];
8282
default:
8383
unreachable(appearance);

packages/preview-server/src/components/code.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,8 +129,8 @@ export const Code: React.FC<Readonly<CodeProps>> = ({
129129
scroll={false}
130130
aria-selected={isHighlighted}
131131
className={cn(
132-
'text-[#49494f] relative text-[13px] font-light font-[MonoLisa,_Menlo,_monospace] align-middle scroll-mt-[325px] select-none pr-3 cursor-pointer hover:text-slate-12 transition-colors',
133-
'aria-selected:text-cyan-11 aria-selected:hover:text-cyan-11 aria-selected:bg-cyan-5 [&+*]:aria-selected:bg-cyan-5',
132+
'text-[#49494f] relative text-[13px] font-light font-[MonoLisa,Menlo,monospace] align-middle scroll-mt-[325px] select-none pr-3 cursor-pointer hover:text-slate-12 transition-colors',
133+
'aria-selected:text-cyan-11 aria-selected:hover:text-cyan-11 aria-selected:bg-cyan-5 aria-selected:[&+*]:bg-cyan-5',
134134
isHighlightStart && 'rounded-tl-sm',
135135
isHighlightEnd && 'rounded-bl-sm',
136136
)}

packages/preview-server/src/components/icons/icon-button.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export const IconButton = React.forwardRef<
1111
type="button"
1212
{...props}
1313
className={cn(
14-
'focus:ring-gray-8 rounded text-slate-11 transition duration-200 ease-in-out hover:text-slate-12 focus:text-slate-12 focus:outline-none focus:ring-2',
14+
'focus:ring-gray-8 rounded-sm text-slate-11 transition duration-200 ease-in-out hover:text-slate-12 focus:text-slate-12 focus:outline-hidden focus:ring-2',
1515
className,
1616
)}
1717
ref={forwardedRef}

0 commit comments

Comments
 (0)