将前端 TailwindCSS 版本从v3 升级到 v4

This commit is contained in:
DrSmoothl
2026-03-14 18:11:37 +08:00
parent 037bc493a0
commit 51f2455ee1
8 changed files with 118 additions and 126 deletions

View File

@@ -7,7 +7,7 @@
[![React](https://img.shields.io/badge/React-19.2-61DAFB?logo=react&logoColor=white)](https://react.dev/)
[![TypeScript](https://img.shields.io/badge/TypeScript-5.9-3178C6?logo=typescript&logoColor=white)](https://www.typescriptlang.org/)
[![Vite](https://img.shields.io/badge/Vite-7.2-646CFF?logo=vite&logoColor=white)](https://vitejs.dev/)
[![TailwindCSS](https://img.shields.io/badge/TailwindCSS-3.4-38B2AC?logo=tailwind-css&logoColor=white)](https://tailwindcss.com/)
[![TailwindCSS](https://img.shields.io/badge/TailwindCSS-4.2-38B2AC?logo=tailwind-css&logoColor=white)](https://tailwindcss.com/)
</div>
@@ -134,7 +134,7 @@ React 19.2.0 # UI 框架
├── TanStack Router # 路由管理
├── TanStack Virtual # 虚拟滚动
├── Jotai # 状态管理
├── Tailwind CSS 3.4 # 样式框架
├── Tailwind CSS 4.2 # 样式框架
├── ReactFlow # 知识图谱可视化
├── Recharts # 数据图表
└── shadcn/ui # 组件库
@@ -213,7 +213,7 @@ MaiBot-Dashboard/
│ └── index.css # 全局样式
├── public/ # 静态资源
├── vite.config.ts # Vite 配置
├── tailwind.config.js # Tailwind 配置
├── tailwind.config.js # Tailwind v4 兼容占位配置
├── tsconfig.json # TypeScript 配置
└── package.json # 依赖管理
```
@@ -328,7 +328,7 @@ proxy: {
|------|------|------|
| @radix-ui/react-* | ^1.x | 无障碍组件基础 |
| lucide-react | ^0.553.0 | 图标库 |
| tailwindcss | ^3.4 | CSS 框架 |
| tailwindcss | ^4.2.1 | CSS 框架 |
| class-variance-authority | ^0.7.1 | 类名管理 |
| tailwind-merge | ^3.4.0 | Tailwind 类合并 |
| date-fns | ^3.x | 日期处理 |

View File

@@ -1,3 +1,4 @@
import tailwindcss from '@tailwindcss/vite'
import react from '@vitejs/plugin-react'
import { defineConfig } from 'electron-vite'
import path from 'path'
@@ -40,7 +41,7 @@ export default defineConfig({
'@': path.resolve(__dirname, './src'),
},
},
plugins: [react()],
plugins: [tailwindcss(), react()],
server: {
port: 7999,
proxy: {

View File

@@ -159,6 +159,7 @@
"@use-gesture/react": "^10.3.1"
},
"devDependencies": {
"@tailwindcss/vite": "^4.2.1",
"@eslint/js": "^9.39.1",
"@testing-library/dom": "^10.4.1",
"@testing-library/jest-dom": "^6.9.1",
@@ -169,7 +170,6 @@
"@types/react-dom": "^19.2.3",
"@vitejs/plugin-react": "^5.1.2",
"@vitest/ui": "^4.0.18",
"autoprefixer": "^10.4.22",
"electron": "^40.6.1",
"electron-builder": "^26.8.1",
"electron-store": "11.0.2",
@@ -179,10 +179,9 @@
"eslint-plugin-react-refresh": "^0.4.24",
"globals": "^16.5.0",
"jsdom": "^28.1.0",
"postcss": "^8.5.6",
"prettier": "^3.7.4",
"prettier-plugin-tailwindcss": "^0.7.2",
"tailwindcss": "^3",
"tailwindcss": "^4.2.1",
"typescript": "~5.9.3",
"typescript-eslint": "^8.49.0",
"vite": "^7.2.7",

View File

@@ -1,6 +0,0 @@
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}

View File

@@ -1,6 +1,104 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
@import "tailwindcss";
@source "./**/*.{js,ts,jsx,tsx}";
@custom-variant dark (&:where(.dark, .dark *));
@theme inline {
--color-border: hsl(var(--border));
--color-input: hsl(var(--input));
--color-ring: hsl(var(--ring));
--color-background: hsl(var(--background));
--color-foreground: hsl(var(--foreground));
--color-primary: hsl(var(--primary));
--color-primary-foreground: hsl(var(--primary-foreground));
--color-secondary: hsl(var(--secondary));
--color-secondary-foreground: hsl(var(--secondary-foreground));
--color-muted: hsl(var(--muted));
--color-muted-foreground: hsl(var(--muted-foreground));
--color-accent: hsl(var(--accent));
--color-accent-foreground: hsl(var(--accent-foreground));
--color-card: hsl(var(--card));
--color-card-foreground: hsl(var(--card-foreground));
--color-popover: hsl(var(--popover));
--color-popover-foreground: hsl(var(--popover-foreground));
--color-destructive: hsl(var(--destructive));
--color-destructive-foreground: hsl(var(--destructive-foreground));
--radius-sm: var(--visual-radius-sm);
--radius-md: var(--visual-radius-md);
--radius-lg: var(--visual-radius-lg);
--radius-xl: var(--visual-radius-xl);
--font-sans: var(--typography-font-family-base);
--font-mono: var(--typography-font-family-code);
--shadow-sm: var(--visual-shadow-sm);
--shadow-md: var(--visual-shadow-md);
--shadow-lg: var(--visual-shadow-lg);
--shadow-xl: var(--visual-shadow-xl);
--animate-slide-in-from-right: slide-in-from-right 0.3s ease-out;
--animate-slide-out-to-right: slide-out-to-right 0.2s ease-in;
--animate-slide-in-from-top: slide-in-from-top 0.3s ease-out;
--animate-slide-out-to-top: slide-out-to-top 0.2s ease-in;
--animate-fade-in: fade-in 0.2s ease-out;
--animate-fade-out: fade-out 0.15s ease-in;
}
@keyframes slide-in-from-right {
from {
transform: translateX(100%);
}
to {
transform: translateX(0);
}
}
@keyframes slide-out-to-right {
from {
transform: translateX(0);
}
to {
transform: translateX(100%);
}
}
@keyframes slide-in-from-top {
from {
transform: translateY(-100%);
}
to {
transform: translateY(0);
}
}
@keyframes slide-out-to-top {
from {
transform: translateY(0);
}
to {
transform: translateY(-100%);
}
}
@keyframes fade-in {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes fade-out {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
/* JetBrains Mono 字体 - 用于代码编辑器 */
@font-face {

View File

@@ -13,9 +13,9 @@ export function AboutTab() {
return (
<div className="space-y-4 sm:space-y-6">
{/* GitHub 开源地址 */}
<div className="rounded-lg border-2 border-primary/30 bg-gradient-to-r from-primary/5 to-primary/10 p-4 sm:p-6">
<div className="rounded-lg border-2 border-primary/30 bg-linear-to-r from-primary/5 to-primary/10 p-4 sm:p-6">
<div className="flex items-start gap-3 sm:gap-4">
<div className="flex-shrink-0 rounded-lg bg-primary/10 p-2 sm:p-3">
<div className="shrink-0 rounded-lg bg-primary/10 p-2 sm:p-3">
<svg
className="h-6 w-6 sm:h-8 sm:w-8 text-primary"
fill="currentColor"
@@ -120,7 +120,7 @@ export function AboutTab() {
<ul className="space-y-0.5 list-disc list-inside">
<li>shadcn/ui</li>
<li>Radix UI</li>
<li>Tailwind CSS 3.4.17</li>
<li>Tailwind CSS 4.2.1</li>
<li>Lucide Icons</li>
</ul>
</div>
@@ -138,7 +138,6 @@ export function AboutTab() {
<ul className="space-y-0.5 list-disc list-inside">
<li>Bun / npm</li>
<li>ESLint 9.17.0</li>
<li>PostCSS</li>
</ul>
</div>
</div>
@@ -220,7 +219,6 @@ export function AboutTab() {
<LibraryItem name="TypeScript" description={t('settings.about.lib.typescript')} license="Apache-2.0" />
<LibraryItem name="Vite" description={t('settings.about.lib.vite')} license="MIT" />
<LibraryItem name="ESLint" description={t('settings.about.lib.eslint')} license="MIT" />
<LibraryItem name="PostCSS" description={t('settings.about.lib.postcss')} license="MIT" />
</div>
</div>
</div>
@@ -233,7 +231,7 @@ export function AboutTab() {
<div className="space-y-3">
<div className="rounded-lg bg-primary/5 border border-primary/20 p-3 sm:p-4">
<div className="flex items-start gap-2 sm:gap-3">
<div className="flex-shrink-0 mt-0.5">
<div className="mt-0.5 shrink-0">
<div className="rounded-md bg-primary/10 px-2 py-1">
<span className="text-xs sm:text-sm font-bold text-primary">GPLv3</span>
</div>

View File

@@ -1,101 +1,2 @@
/** @type {import('tailwindcss').Config} */
export default {
darkMode: ['class'],
content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'],
theme: {
extend: {
colors: {
border: 'hsl(var(--color-border))',
input: 'hsl(var(--color-input))',
ring: 'hsl(var(--color-ring))',
background: 'hsl(var(--color-background))',
foreground: 'hsl(var(--color-foreground))',
primary: {
DEFAULT: 'hsl(var(--color-primary))',
foreground: 'hsl(var(--color-primary-foreground))',
},
secondary: {
DEFAULT: 'hsl(var(--color-secondary))',
foreground: 'hsl(var(--color-secondary-foreground))',
},
muted: {
DEFAULT: 'hsl(var(--color-muted))',
foreground: 'hsl(var(--color-muted-foreground))',
},
accent: {
DEFAULT: 'hsl(var(--color-accent))',
foreground: 'hsl(var(--color-accent-foreground))',
},
card: {
DEFAULT: 'hsl(var(--color-card))',
foreground: 'hsl(var(--color-card-foreground))',
},
popover: {
DEFAULT: 'hsl(var(--color-popover))',
foreground: 'hsl(var(--color-popover-foreground))',
},
destructive: {
DEFAULT: 'hsl(var(--color-destructive))',
foreground: 'hsl(var(--color-destructive-foreground))',
},
},
borderRadius: {
lg: 'var(--visual-radius-lg)',
md: 'var(--visual-radius-md)',
sm: 'var(--visual-radius-sm)',
xl: 'var(--visual-radius-xl)',
full: 'var(--visual-radius-full)',
},
fontFamily: {
sans: 'var(--typography-font-family-base)',
mono: 'var(--typography-font-family-code)',
},
boxShadow: {
sm: 'var(--visual-shadow-sm)',
md: 'var(--visual-shadow-md)',
lg: 'var(--visual-shadow-lg)',
xl: 'var(--visual-shadow-xl)',
},
transitionDuration: {
fast: 'var(--animation-anim-duration-fast)',
normal: 'var(--animation-anim-duration-normal)',
slow: 'var(--animation-anim-duration-slow)',
},
keyframes: {
'slide-in-from-right': {
from: { transform: 'translateX(100%)' },
to: { transform: 'translateX(0)' },
},
'slide-out-to-right': {
from: { transform: 'translateX(0)' },
to: { transform: 'translateX(100%)' },
},
'slide-in-from-top': {
from: { transform: 'translateY(-100%)' },
to: { transform: 'translateY(0)' },
},
'slide-out-to-top': {
from: { transform: 'translateY(0)' },
to: { transform: 'translateY(-100%)' },
},
'fade-in': {
from: { opacity: '0' },
to: { opacity: '1' },
},
'fade-out': {
from: { opacity: '1' },
to: { opacity: '0' },
},
},
animation: {
'slide-in-from-right': 'slide-in-from-right 0.3s ease-out',
'slide-out-to-right': 'slide-out-to-right 0.2s ease-in',
'slide-in-from-top': 'slide-in-from-top 0.3s ease-out',
'slide-out-to-top': 'slide-out-to-top 0.2s ease-in',
'fade-in': 'fade-in 0.2s ease-out',
'fade-out': 'fade-out 0.15s ease-in',
},
},
},
plugins: [],
}
// Tailwind v4 theme tokens and custom utilities are defined in src/index.css.
export default {}

View File

@@ -1,10 +1,11 @@
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'
import react from '@vitejs/plugin-react'
import { defineConfig } from 'vite'
import path from 'path'
// https://vite.dev/config/
export default defineConfig({
plugins: [react()],
plugins: [tailwindcss(), react()],
server: {
port: 7999,
proxy: {