Skip to content

Commit 35879a0

Browse files
authored
Added React + Antd + TailwindCSS Example (#32)
1 parent bcb7275 commit 35879a0

19 files changed

Lines changed: 371 additions & 0 deletions

File tree

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Logs
2+
logs
3+
*.log
4+
npm-debug.log*
5+
yarn-debug.log*
6+
yarn-error.log*
7+
pnpm-debug.log*
8+
lerna-debug.log*
9+
10+
node_modules
11+
.output
12+
stats.html
13+
stats-*.json
14+
.wxt
15+
web-ext.config.ts
16+
17+
# Editor directories and files
18+
.vscode/*
19+
!.vscode/extensions.json
20+
.idea
21+
.DS_Store
22+
*.suo
23+
*.ntvs*
24+
*.njsproj
25+
*.sln
26+
*.sw?
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
---
2+
name: React with AntD & Tailwind CSS
3+
description: Simple example extension using React, Tailwind CSS, and AntD components.
4+
---
5+
6+
# WXT + React + AntD + Tailwind CSS
7+
8+
This example demonstrates how to integrate React 19+, Tailwind CSS v4+, and AntD components within a WXT extension.
9+
10+
## Installation Walkthrough
11+
12+
1. **Initialize a new WXT project:**
13+
14+
Open your terminal and run the following command to create a new WXT project with the React template:
15+
16+
```sh
17+
pnpm dlx wxt@latest init
18+
```
19+
20+
The CLI will guide you through the project setup. Choose the `react` template and your preferred package manager. For this example, I use pnpm.
21+
22+
```
23+
WXT 0.20.6
24+
ℹ Initializing new project
25+
✔ Project Directory … react-antd-tailwindcss
26+
✔ Choose a template › react
27+
✔ Package Manager › pnpm
28+
✔ Downloading template
29+
✨ WXT project created with the react template.
30+
Next steps:
31+
1. cd react-antd-tailwindcss
32+
2. pnpm install
33+
```
34+
35+
2. **Navigate to the project directory and install dependencies:**
36+
37+
```sh
38+
cd react-antd-tailwindcss
39+
pnpm install
40+
```
41+
42+
3. **Install Tailwind CSS and `@tailwindcss/vite`:**
43+
44+
You should follow the official Tailwind Vite installation [guide](https://tailwindcss.com/docs/installation/using-vite). As the time of creating this example, it asked to run the following command:
45+
46+
```sh
47+
pnpm install tailwindcss @tailwindcss/vite
48+
```
49+
50+
4. **Configure Tailwind CSS in `wxt.config.ts`:**
51+
52+
To configure Tailwind CSS, modify `wxt.config.ts`. While official documentation says to change `vite.config.ts`, WXT configures Vite internally, so you need to update `wxt.config.ts` instead. This file manages the build process. To integrate Tailwind, add it as a Vite plugin within the wxt.config.ts file, as shown here:
53+
54+
```ts
55+
import { defineConfig } from "wxt";
56+
import tailwindcss from "@tailwindcss/vite";
57+
// See https://wxt.dev/api/config.html
58+
export default defineConfig({
59+
modules: ["@wxt-dev/module-react"],
60+
vite: () => ({
61+
plugins: [tailwindcss()],
62+
}),
63+
});
64+
```
65+
66+
5. **Create a `tailwind.css` file:**
67+
68+
Create a `tailwind.css` file in your `assets` directory (or the root directory of your project if you don't have an assets dir) with the following content:
69+
70+
```css
71+
@import "tailwindcss";
72+
```
73+
74+
6. **Import `tailwind.css`:**
75+
76+
You can now easily import the `tailwind.css` file in your React components:
77+
78+
```ts
79+
import "@/assets/tailwind.css"; // Adjust the path if necessary
80+
```
81+
82+
or you can include it directly in your `index.html` file:
83+
84+
```html
85+
<!doctype html>
86+
<html>
87+
<head>
88+
<meta charset="UTF-8" />
89+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
90+
<link href="@/assets/tailwind.css" rel="stylesheet" />
91+
</head>
92+
<body></body>
93+
</html>
94+
```
95+
96+
Now you can use AntD and TailwindCSS together throughout your project.
Lines changed: 1 addition & 0 deletions
Loading
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
@layer theme, base, antd, components, utilities;
2+
3+
@import 'tailwindcss/theme.css' layer(theme);
4+
@import 'tailwindcss/preflight.css' layer(base);
5+
@import 'tailwindcss/utilities.css' layer(utilities);
6+
7+
@custom-variant dark (&:where(.dark, .dark *));
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
2+
import { ThemeProvider } from "@/provider/Theme";
3+
import { Button } from "antd";
4+
import { createRoot } from "react-dom/client";
5+
6+
export default defineContentScript({
7+
matches: ["*://*.example.com/*"],
8+
cssInjectionMode: "ui",
9+
10+
async main(ctx) {
11+
const ui = await createShadowRootUi(ctx, {
12+
name: "react-antd-tailwindcss",
13+
position: "inline",
14+
anchor: "body",
15+
16+
onMount: (container, shadow) => {
17+
const root = createRoot(container);
18+
19+
root.render(
20+
<ThemeProvider cssContainer={shadow.querySelector("head") ?? shadow}>
21+
<Button className="bg-green-100">Button</Button>
22+
</ThemeProvider>
23+
);
24+
25+
return root;
26+
},
27+
});
28+
29+
ui.autoMount();
30+
},
31+
});
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { useState } from "react";
2+
import reactLogo from "@/assets/react.svg";
3+
import wxtLogo from "/wxt.svg";
4+
import antdLogo from "/antd.svg";
5+
import { Button } from "antd";
6+
7+
function App() {
8+
const [count, setCount] = useState(0);
9+
10+
return (
11+
<div className="w-80 p-4 space-y-4 bg-white rounded-md shadow-md">
12+
<div className="flex justify-center items-center space-x-4">
13+
<a href="https://wxt.dev" target="_blank" rel="noopener noreferrer">
14+
<img src={wxtLogo} className="h-8 w-auto" alt="WXT logo" />
15+
</a>
16+
<a href="https://react.dev" target="_blank" rel="noopener noreferrer">
17+
<img src={reactLogo} className="h-8 w-auto" alt="React logo" />
18+
</a>
19+
<a href="https://ant.design" target="_blank" rel="noopener noreferrer">
20+
<img src={antdLogo} className="h-8 w-auto" alt="Antd logo" />
21+
</a>
22+
</div>
23+
24+
<h1 className="text-xl font-semibold text-center text-gray-800">
25+
WXT + React + Antd
26+
</h1>
27+
28+
<div className="bg-gray-100 p-4 rounded-md shadow-inner flex flex-col items-center">
29+
<Button onClick={() => setCount((count) => count + 1)} type="primary">
30+
Count is {count}
31+
</Button>
32+
<p className="text-sm mt-2 text-gray-600 text-center">
33+
Edit <code>src/App.tsx</code> and save to test HMR
34+
</p>
35+
</div>
36+
37+
<p className="text-xs text-center text-gray-500">
38+
Click on the WXT and React logos to learn more
39+
</p>
40+
</div>
41+
);
42+
}
43+
44+
export default App;
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+
<title>Default Popup Title</title>
7+
<meta name="manifest.type" content="browser_action" />
8+
</head>
9+
<body>
10+
<div id="root"></div>
11+
<script type="module" src="./main.tsx"></script>
12+
</body>
13+
</html>
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import React from "react";
2+
import ReactDOM from "react-dom/client";
3+
import App from "./App.tsx";
4+
import "@/assets/tailwind.css";
5+
import { ThemeProvider } from "@/provider/Theme.tsx";
6+
7+
ReactDOM.createRoot(document.getElementById("root")!).render(
8+
<React.StrictMode>
9+
<ThemeProvider>
10+
<App />
11+
</ThemeProvider>
12+
</React.StrictMode>,
13+
);
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
{
2+
"name": "react-antd-tailwindcss",
3+
"description": "manifest.json description",
4+
"private": true,
5+
"version": "0.0.0",
6+
"type": "module",
7+
"scripts": {
8+
"dev": "wxt",
9+
"dev:firefox": "wxt -b firefox",
10+
"build": "wxt build",
11+
"build:firefox": "wxt build -b firefox",
12+
"zip": "wxt zip",
13+
"zip:firefox": "wxt zip -b firefox",
14+
"compile": "tsc --noEmit",
15+
"postinstall": "wxt prepare"
16+
},
17+
"dependencies": {
18+
"@ant-design/cssinjs": "^2.0.1",
19+
"@tailwindcss/vite": "^4.2.1",
20+
"antd": "^6.0.1",
21+
"react": "^19.2.4",
22+
"react-dom": "^19.2.4",
23+
"tailwindcss": "^4.2.0"
24+
},
25+
"devDependencies": {
26+
"@types/node": "^25.3.3",
27+
"@types/react": "^19.2.14",
28+
"@types/react-dom": "^19.2.3",
29+
"@wxt-dev/module-react": "^1.1.5",
30+
"typescript": "^5.9.3",
31+
"wxt": "^0.20.18"
32+
}
33+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import "@/assets/tailwind.css";
2+
import { StyleProvider } from "@ant-design/cssinjs";
3+
import { ConfigProvider } from "antd";
4+
import type { ReactNode } from "react";
5+
6+
type ThemeProviderProps = {
7+
children?: ReactNode;
8+
cssContainer?: HTMLElement | ShadowRoot;
9+
};
10+
11+
export const ThemeProvider = ({
12+
children,
13+
cssContainer,
14+
}: ThemeProviderProps) => {
15+
const container =
16+
cssContainer ??
17+
(typeof document !== "undefined" ? document.head : undefined);
18+
19+
return (
20+
<StyleProvider container={container} layer hashPriority="high">
21+
<ConfigProvider
22+
theme={{
23+
token: {
24+
colorPrimary: "#ff000a",
25+
},
26+
}}
27+
>
28+
{children}
29+
</ConfigProvider>
30+
</StyleProvider>
31+
);
32+
};

0 commit comments

Comments
 (0)