Skip to content

Commit d61e4e6

Browse files
committed
refactor: migrate Tailwind CSS v3 to v4
- Replace JS config (tailwind.config.ts) with CSS-first config (@config in global.css) - Migrate postcss.config.js to postcss.config.mjs with @tailwindcss/postcss - Reorganize CSS into focused files: base.css, theme.css, utilities.css, semantic-tokens.css - Migrate renamed/removed utilities: rounded, shadow, outline, ring, opacity classes - Convert space-y patterns to gap where needed, resolve negative margin conflicts - Fix variant selectors: not-[:first] → not-[:first-child], last variant on alert - Move custom utilities (staking-grid, area-glyph) to @Utility for variant support - Use @theme inline for nested .dark containers to resolve semantic tokens correctly - Import docsearch CSS into cascade layer to restore library styles - Add json loader for .all-contributorsrc in storybook webpack config - Fix leading-base setting --tw-leading on code elements - Remove first heading top margin in content pages for v4 compat - Update 100+ components with renamed utility classes
1 parent 3139240 commit d61e4e6

135 files changed

Lines changed: 1805 additions & 1671 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.storybook/main.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,12 @@ const config: StorybookConfig = {
6868
use: ["@svgr/webpack"],
6969
})
7070

71+
// .all-contributorsrc is JSON without a .json extension
72+
config.module.rules.push({
73+
test: /\.all-contributorsrc$/,
74+
type: "json",
75+
})
76+
7177
return config
7278
},
7379

.storybook/preview.tsx

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,6 @@ import nextIntl, { baseLocales } from "./next-intl"
1010
import { withNextThemes } from "./withNextThemes"
1111

1212
import "../src/styles/global.css"
13-
import "../src/styles/docsearch.css"
14-
15-
import "@docsearch/css"
1613

1714
const inter = Inter({
1815
subsets: ["latin"],

AGENTS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ This is the official Ethereum.org website - a Next.js application that serves as
1111
- **Next.js 14.2+** - React framework with App Router
1212
- **React 18** - UI library
1313
- **TypeScript 5.5+** - Type safety and development experience
14-
- **Tailwind CSS 3.4+** - Utility-first CSS framework
14+
- **Tailwind CSS 4+** - Utility-first CSS framework (CSS-first config in `src/styles/global.css`)
1515

1616
### Key Dependencies
1717

app/[locale]/10years/_components/NFTMintCard/index.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ const NFTMintCard = ({ className }: NFTMintCardProps) => {
2020
return (
2121
<Card
2222
className={cn(
23-
"w-full overflow-hidden rounded-3xl bg-gradient-to-b from-[#A66BFF20] to-[#EED9FE16] shadow-lg",
23+
"w-full overflow-hidden rounded-3xl bg-linear-to-b from-[#A66BFF20] to-[#EED9FE16] shadow-lg",
2424
className
2525
)}
2626
>
@@ -30,7 +30,7 @@ const NFTMintCard = ({ className }: NFTMintCardProps) => {
3030
<div className="flex items-center justify-center pt-12">
3131
<div className="relative max-h-[200px] max-w-[200px] overflow-hidden rounded-full border-4 border-white bg-white">
3232
<video
33-
className="pointer-events-none h-full w-full select-none rounded-full object-cover"
33+
className="pointer-events-none h-full w-full rounded-full object-cover select-none"
3434
src="/videos/10y-video.mp4"
3535
aria-label={t("page-10-year-video-aria-label")}
3636
autoPlay
@@ -47,7 +47,7 @@ const NFTMintCard = ({ className }: NFTMintCardProps) => {
4747
{/* Curved text */}
4848
<Curved10YearsText
4949
viewBox="0 0 313 186"
50-
className="absolute left-1/2 top-0 h-min w-full max-w-[300px] -translate-x-1/2 fill-primary"
50+
className="fill-primary absolute top-0 left-1/2 h-min w-full max-w-[300px] -translate-x-1/2"
5151
width="100%"
5252
height="auto"
5353
/>

app/[locale]/10years/_components/TenYearHero.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,20 +38,20 @@ const TenYearHero = async () => {
3838
<ParallaxImage
3939
src={TenYearGraphicImage}
4040
alt={t("page-10-year-anniversary-meta-title")}
41-
className="absolute left-0 top-0 max-h-[350px] object-contain transition-transform duration-200 ease-out"
41+
className="absolute top-0 left-0 max-h-[350px] object-contain transition-transform duration-200 ease-out"
4242
priority
4343
/>
4444
</div>
4545
<p className="text-center text-3xl">
4646
{t("page-10-year-celebrating")}{" "}
4747
<span className="relative max-md:block md:w-fit">
4848
<span
49-
className="select-none opacity-0 max-md:hidden"
49+
className="opacity-0 select-none max-md:hidden"
5050
data-label="space-holder"
5151
>
5252
{WORDS[0]}
5353
</span>
54-
<span className="text-3xl font-bold text-accent-b md:absolute md:start-0 md:text-nowrap">
54+
<span className="text-accent-b text-3xl font-bold md:absolute md:start-0 md:text-nowrap">
5555
{/* CLIENT SIDE, lazy loaded */}
5656
<Morpher words={WORDS} charSet="abcdfgijklnopqsvwxyz" />
5757
</span>

app/[locale]/10years/_components/TorchHistoryCard.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,9 @@ const TorchHistoryCard: React.FC<TorchHistoryCardProps> = ({
4141
return (
4242
<Card
4343
className={cn(
44-
"flex flex-col rounded-xl border border-gray-100/50 bg-gradient-to-b from-white to-gray-100 px-6 py-12 shadow-lg dark:text-body-inverse",
45-
isCurrentHolder && "bg-gradient-to-b from-[#B38DF0] to-[#DED4ED]",
46-
isPlaceholder &&
47-
"bg-gradient-to-b from-gray-100 to-gray-200 opacity-50",
44+
"dark:text-body-inverse flex flex-col rounded-xl border border-gray-100/50 bg-linear-to-b from-white to-gray-100 px-6 py-12 shadow-lg",
45+
isCurrentHolder && "bg-linear-to-b from-[#B38DF0] to-[#DED4ED]",
46+
isPlaceholder && "bg-linear-to-b from-gray-100 to-gray-200 opacity-50",
4847
className
4948
)}
5049
>
Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
// duplicate 1 2 3, 1 2 3 to fix mobile slider bug where styles are not applied
22
const adoptionStyles = [
3-
"bg-background bg-gradient-to-b from-20% to-60% from-accent-c/10 to-accent-c/5 dark:from-accent-c/20 dark:to-accent-c/10 border-accent-c/10",
4-
"bg-background bg-gradient-to-b from-20% to-60% from-accent-b/10 to-accent-b/5 dark:from-accent-b/20 dark:to-accent-b/10 border-accent-b/10",
5-
"bg-background bg-gradient-to-b from-20% to-60% from-accent-a/10 to-accent-a/5 dark:from-accent-a/20 dark:to-accent-a/10 border-accent-a/10",
6-
"bg-background bg-gradient-to-b from-20% to-60% from-accent-c/10 to-accent-c/5 dark:from-accent-c/20 dark:to-accent-c/10 border-accent-c/10",
7-
"bg-background bg-gradient-to-b from-20% to-60% from-accent-b/10 to-accent-b/5 dark:from-accent-b/20 dark:to-accent-b/10 border-accent-b/10",
8-
"bg-background bg-gradient-to-b from-20% to-60% from-accent-a/10 to-accent-a/5 dark:from-accent-a/20 dark:to-accent-a/10 border-accent-a/10",
3+
"bg-background bg-linear-to-b from-20% to-60% from-accent-c/10 to-accent-c/5 dark:from-accent-c/20 dark:to-accent-c/10 border-accent-c/10",
4+
"bg-background bg-linear-to-b from-20% to-60% from-accent-b/10 to-accent-b/5 dark:from-accent-b/20 dark:to-accent-b/10 border-accent-b/10",
5+
"bg-background bg-linear-to-b from-20% to-60% from-accent-a/10 to-accent-a/5 dark:from-accent-a/20 dark:to-accent-a/10 border-accent-a/10",
6+
"bg-background bg-linear-to-b from-20% to-60% from-accent-c/10 to-accent-c/5 dark:from-accent-c/20 dark:to-accent-c/10 border-accent-c/10",
7+
"bg-background bg-linear-to-b from-20% to-60% from-accent-b/10 to-accent-b/5 dark:from-accent-b/20 dark:to-accent-b/10 border-accent-b/10",
8+
"bg-background bg-linear-to-b from-20% to-60% from-accent-a/10 to-accent-a/5 dark:from-accent-a/20 dark:to-accent-a/10 border-accent-a/10",
99
]
1010

1111
export { adoptionStyles }

app/[locale]/10years/page.tsx

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ const Page = async (props: { params: Promise<PageParams> }) => {
9696
</div>
9797

9898
<div className="w-full px-4 py-8 md:px-8">
99-
<div className="flex flex-col items-center gap-4 rounded-4xl bg-radial-a px-4 pt-8 lg:px-14 lg:pt-14">
99+
<div className="bg-radial-a flex flex-col items-center gap-4 rounded-4xl px-4 pt-8 lg:px-14 lg:pt-14">
100100
<div className="flex flex-col gap-4 text-center">
101101
<h2 className="text-4xl font-black">
102102
{t("page-10-year-livestream-title")}
@@ -117,12 +117,12 @@ const Page = async (props: { params: Promise<PageParams> }) => {
117117
defaultValue={Object.keys(tenYearEventRegions)[0]}
118118
className="w-full"
119119
>
120-
<TabsList className="w-full flex-nowrap justify-start overflow-x-auto overflow-y-hidden rounded-none border-b-2 border-b-primary p-0">
120+
<TabsList className="border-b-primary w-full flex-nowrap justify-start overflow-x-auto overflow-y-hidden rounded-none border-b-2 p-0">
121121
{Object.entries(tenYearEventRegions).map(([key, data]) => (
122122
<TabsTrigger
123123
key={key}
124124
value={key}
125-
className="whitespace-nowrap border-0 text-primary"
125+
className="text-primary border-0 whitespace-nowrap"
126126
>
127127
{data.label}&nbsp;
128128
<span className="text-sm">({data.events.length})</span>
@@ -157,8 +157,8 @@ const Page = async (props: { params: Promise<PageParams> }) => {
157157
key={country}
158158
className={cn("flex flex-col border-b px-4 py-6")}
159159
>
160-
<h3 className="mb-2 flex items-center gap-2 text-2xl font-bold text-body-medium">
161-
<span className="flex min-h-6 min-w-6 items-center justify-center overflow-hidden rounded-full bg-primary-low-contrast">
160+
<h3 className="text-body-medium mb-2 flex items-center gap-2 text-2xl font-bold">
161+
<span className="bg-primary-low-contrast flex min-h-6 min-w-6 items-center justify-center overflow-hidden rounded-full">
162162
<Emoji
163163
text={countryEvents[0].countryFlag}
164164
className="scale-[1.75]"
@@ -170,7 +170,7 @@ const Page = async (props: { params: Promise<PageParams> }) => {
170170
{countryEvents.map((event, index) => (
171171
<LinkBox
172172
key={index}
173-
className="flex flex-col justify-between gap-2 rounded-lg p-2 hover:bg-background-highlight md:flex-row"
173+
className="hover:bg-background-highlight flex flex-col justify-between gap-2 rounded-lg p-2 md:flex-row"
174174
>
175175
<div className="flex flex-col gap-2 md:flex-row md:items-center">
176176
<div>
@@ -206,7 +206,7 @@ const Page = async (props: { params: Promise<PageParams> }) => {
206206

207207
<div
208208
id="torch-history"
209-
className="my-32 flex w-full scroll-mt-32 flex-col bg-gradient-to-b from-[#161A36] via-[#161A36] via-60% to-[#9C63F8] md:rounded-3xl"
209+
className="my-32 flex w-full scroll-mt-32 flex-col bg-linear-to-b from-[#161A36] via-[#161A36] via-60% to-[#9C63F8] md:rounded-3xl"
210210
>
211211
<div className="p-8">
212212
<div className="relative">
@@ -224,13 +224,13 @@ const Page = async (props: { params: Promise<PageParams> }) => {
224224
disablePictureInPicture
225225
playsInline
226226
/>
227-
<div className="pointer-events-none absolute top-0 h-full w-full select-none bg-[url('/images/10-year-anniversary/torch-overlay.png')] bg-contain bg-center bg-no-repeat" />
227+
<div className="pointer-events-none absolute top-0 h-full w-full bg-[url('/images/10-year-anniversary/torch-overlay.png')] bg-contain bg-center bg-no-repeat select-none" />
228228
</div>
229229
</div>
230230
{/* Curved text */}
231231
<Curved10YearsText
232232
viewBox="0 0 356 186"
233-
className="absolute left-1/2 top-0 h-min w-full max-w-[600px] -translate-x-1/2"
233+
className="absolute top-0 left-1/2 h-min w-full max-w-[600px] -translate-x-1/2"
234234
width="100%"
235235
height="auto"
236236
/>
@@ -239,7 +239,7 @@ const Page = async (props: { params: Promise<PageParams> }) => {
239239

240240
<TorchHistorySwiper holders={torchHolders} />
241241

242-
<div className="flex flex-col gap-12 px-8 pb-24 pt-12 text-body-inverse sm:px-16 md:flex-row dark:text-body">
242+
<div className="text-body-inverse dark:text-body flex flex-col gap-12 px-8 pt-12 pb-24 sm:px-16 md:flex-row">
243243
<div className="flex flex-1 flex-col gap-8">
244244
<p>
245245
<Translation
@@ -271,10 +271,10 @@ const Page = async (props: { params: Promise<PageParams> }) => {
271271
<div className="flex w-full flex-col items-center gap-8 px-8 py-8 lg:flex-row">
272272
<div className="flex flex-1 flex-col gap-6">
273273
<h2 className="flex flex-col gap-2 font-black">
274-
<span className="text-4xl text-accent-a">
274+
<span className="text-accent-a text-4xl">
275275
{t("page-10-year-innovation-title")}
276276
</span>
277-
<span className="text-5xl text-body md:text-7xl">
277+
<span className="text-body text-5xl md:text-7xl">
278278
{t("page-10-year-innovation-subtitle")}
279279
</span>
280280
</h2>
@@ -292,10 +292,10 @@ const Page = async (props: { params: Promise<PageParams> }) => {
292292
<div className="relative flex max-w-[350px] flex-1 flex-col gap-6">
293293
<div className="flex flex-col gap-6 lg:sticky lg:top-64 lg:mb-24">
294294
<h2 className="flex flex-col gap-2 font-black">
295-
<span className="text-4xl text-accent-a">
295+
<span className="text-accent-a text-4xl">
296296
{t("page-10-year-adoption-title")}
297297
</span>
298-
<span className="text-5xl text-body md:text-7xl">
298+
<span className="text-body text-5xl md:text-7xl">
299299
{t("page-10-year-adoption-subtitle")}
300300
</span>
301301
</h2>
@@ -348,10 +348,10 @@ const Page = async (props: { params: Promise<PageParams> }) => {
348348
<div className="flex max-w-[350px] flex-1 flex-col gap-6">
349349
<div className="flex flex-col gap-6 lg:sticky lg:top-64 lg:mb-24">
350350
<h2 className="flex flex-col gap-2 font-black">
351-
<span className="text-4xl text-accent-a">
351+
<span className="text-accent-a text-4xl">
352352
{t("page-10-year-stories-title")}
353353
</span>
354-
<span className="text-5xl text-body md:text-7xl">
354+
<span className="text-body text-5xl md:text-7xl">
355355
{t("page-10-year-stories-subtitle")}
356356
</span>
357357
</h2>

app/[locale]/_components/HomepageLazyImports.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export const BentoCardSwiper = dynamic(
1111
ssr: false,
1212
loading: () => (
1313
<div className="flex flex-col items-center gap-4">
14-
<Skeleton className="mx-auto mt-4 h-[476px] w-[512px] max-w-128 rounded-2xl border-primary/10 bg-background bg-gradient-to-b from-primary/10 from-20% to-primary/5 to-60% p-4 opacity-50 shadow-card-hover lg:hidden dark:from-primary/20 dark:to-primary/10" />
14+
<Skeleton className="border-primary/10 bg-background from-primary/10 to-primary/5 shadow-card-hover dark:from-primary/20 dark:to-primary/10 mx-auto mt-4 h-[476px] w-[512px] max-w-128 rounded-2xl bg-linear-to-b from-20% to-60% p-4 opacity-50 lg:hidden" />
1515
<Skeleton className="h-6 w-[12rem] rounded-full" />
1616
</div>
1717
),

0 commit comments

Comments
 (0)