一、安装Tailwind CSS及其支持
pnpm add -D @types/node
pnpm add -D tailwindcss @tailwindcss/vite
二、配置Tailwind CSS
在 vite.config.ts中导入tailwindcss依赖
import tailwindcss from "@tailwindcss/vite";
增加tailwindcss插件
plugins: [react(), tailwindcss()]
三、配置路径别名和tsconfig
在 tsconfig.json中添加Path别名
{
"compilerOptions": {
/* Path aliases */
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
},
/* 其他配置不变 */
},
/* 其他配置不变 */
}
在 vite.config.ts中添加别名
import path from "path";
export default defineConfig(async () => ({
plugins: [react(), tailwindcss()],
resolve: {
alias: {
"@": path.resolve(__dirname, "./src"),
},
},
// 其他配置不变
}));
四、安装shadcn/ui依赖
pnpm add class-variance-authority clsx tailwind-merge lucide-react
五、配置shadcn/ui
新建 components.json
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "new-york",
"rsc": false,
"tsx": true,
"tailwind": {
"config": "",
"css": "src/index.css",
"baseColor": "zinc",
"cssVariables": true,
"prefix": ""
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils",
"ui": "@/components/ui",
"lib": "@/lib",
"hooks": "@/hooks"
},
"iconLibrary": "lucide"
}
新建 src/lib/utils.ts
import { clsx, type ClassValue } from "clsx"
import { twMerge } from "tailwind-merge"
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}
六、添加全局样式
新建 index.css
@import "tailwindcss";
@theme inline {
--color-background: hsl(0 0% 100%);
--color-foreground: hsl(240 10% 3.9%);
--color-card: hsl(0 0% 100%);
--color-card-foreground: hsl(240 10% 3.9%);
--color-popover: hsl(0 0% 100%);
--color-popover-foreground: hsl(240 10% 3.9%);
--color-primary: hsl(240 5.9% 10%);
--color-primary-foreground: hsl(0 0% 98%);
--color-secondary: hsl(240 4.8% 95.9%);
--color-secondary-foreground: hsl(240 5.9% 10%);
--color-muted: hsl(240 4.8% 95.9%);
--color-muted-foreground: hsl(240 3.8% 46.1%);
--color-accent: hsl(240 4.8% 95.9%);
--color-accent-foreground: hsl(240 5.9% 10%);
--color-destructive: hsl(0 84.2% 60.2%);
--color-destructive-foreground: hsl(0 0% 98%);
--color-border: hsl(240 5.9% 90%);
--color-input: hsl(240 5.9% 90%);
--color-ring: hsl(240 10% 3.9%);
--color-chart-1: hsl(12 76% 61%);
--color-chart-2: hsl(173 58% 39%);
--color-chart-3: hsl(197 37% 24%);
--color-chart-4: hsl(43 74% 66%);
--color-chart-5: hsl(27 87% 67%);
--radius-sm: calc(0.25rem - 2px);
--radius-md: calc(0.25rem - 1px);
--radius-lg: 0.25rem;
--radius-xl: calc(0.25rem + 1px);
}
@layer base {
* {
@apply border-border;
}
body {
@apply bg-background text-foreground;
}
}
在 main.tsx中导入 index.css
import "./index.css";
七、测试配置
项目打包构建
pnpm build
创建一个简单的shadcn/ui组件示例来验证配置
pnpm dlx shadcn@latest add button
更新 App.tsx使用shadcn组件
import { useState } from "react";
import reactLogo from "./assets/react.svg";
import { invoke } from "@tauri-apps/api/core";
import { Button } from "@/components/ui/button";
function App() {
const [greetMsg, setGreetMsg] = useState("");
const [name, setName] = useState("");
async function greet() {
setGreetMsg(await invoke("greet", { name }));
}
return (
<main className="min-h-screen flex flex-col items-center justify-center p-8">
<div className="max-w-md w-full space-y-8">
<div className="text-center space-y-2">
<h1 className="text-3xl font-bold">Welcome to Tauri + React + shadcn/ui</h1>
<p className="text-muted-foreground">
Click on the logos to learn more
</p>
</div>
<div className="flex justify-center gap-4">
<a href="https://vite.dev" target="_blank">
<img src="/vite.svg" className="h-12 w-12" alt="Vite logo" />
</a>
<a href="https://tauri.app" target="_blank">
<img src="/tauri.svg" className="h-12 w-12" alt="Tauri logo" />
</a>
<a href="https://react.dev" target="_blank">
<img src={reactLogo} className="h-12 w-12" alt="React logo" />
</a>
</div>
<form
className="space-y-4"
onSubmit={(e) => {
e.preventDefault();
greet();
}}
>
<div className="space-y-2">
<input
id="greet-input"
className="flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-xs transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50"
onChange={(e) => setName(e.currentTarget.value)}
placeholder="Enter a name..."
/>
</div>
<Button type="submit" className="w-full">
Greet
</Button>
</form>
{greetMsg && (
<div className="p-4 rounded-md bg-secondary">
<p className="text-sm">{greetMsg}</p>
</div>
)}
</div>
</main>
);
}
export default App;
启动Tauri桌面应用
pnpm tauri dev
评论