Published on

项目中的样式解决方案:Tailwind与Material-UI的协同使用

第三篇:样式解决方案集成

Web3项目中的样式解决方案:Tailwind与Material-UI的协同使用

在Web3项目开发中,样式解决方案的选择直接影响开发效率和用户体验。经过多次尝试,我发现将Tailwind CSS的原子化样式与Material-UI的组件库结合使用,可以兼顾开发效率和设计一致性。

为什么选择这种组合?

Tailwind CSS的优势

  • 开发效率高:原子化CSS类,无需编写自定义CSS
  • 高度可定制:可以轻松定制主题和颜色系统
  • 响应式设计:内置的响应式工具类
  • Web3适配性:适合快速构建区块链应用的界面

Material-UI的优势

  • 组件丰富:提供完整的Material Design组件库
  • 可访问性:内置的无障碍支持
  • 主题系统:完善的主题定制能力
  • Web3组件:可以扩展构建区块链特有的UI组件

集成配置

1. Tailwind CSS配置

首先安装必要的依赖:

pnpm add -D tailwindcss@3.4.0 postcss@8.5.6 autoprefixer@10.4.21
npx tailwindcss init -p

然后配置tailwind.config.js

// tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    './src/**/*.{js,jsx,ts,tsx}',
    './stories/**/*.{js,jsx,ts,tsx}',
  ],
  theme: {
    extend: {
      colors: {
        primary: {
          50: '#eff6ff',
          100: '#dbeafe',
          200: '#bfdbfe',
          300: '#93c5fd',
          400: '#60a5fa',
          500: '#3b82f6', // 主色调:蓝色,代表信任和技术感
          600: '#2563eb',
          700: '#1d4ed8',
          800: '#1e40af',
          900: '#1e3a8a',
        },
        secondary: {
          500: '#ec4899', // 辅助色:粉色,用于强调和交互元素
        },
        neutral: {
          50: '#f8fafc',
          100: '#f1f5f9',
          200: '#e2e8f0',
          300: '#cbd5e1',
          400: '#94a3b8',
          500: '#64748b',
          600: '#475569',
          700: '#334155',
          800: '#1e293b',
          900: '#0f172a',
        },
      },
      fontFamily: {
        sans: ['Inter', 'system-ui', 'sans-serif'],
      },
    },
  },
  plugins: [],
};

创建样式入口文件src/tailwind.css

/* src/tailwind.css */
@tailwind base;
@tailwind components;
@tailwind utilities;

/* 自定义全局样式 */
@layer base {
  html {
    @apply scroll-smooth;
  }
  
  body {
    @apply font-sans bg-neutral-50 text-neutral-800;
  }
  
  /* Web3特有的样式重置 */
  .wallet-adapter-button {
    @apply rounded-lg bg-primary-500 hover:bg-primary-600 text-white px-4 py-2 transition-colors;
  }
}

/* 自定义组件类 */
@layer components {
  .card {
    @apply bg-white rounded-xl shadow-md overflow-hidden hover:shadow-lg transition-shadow;
  }
  
  .btn-primary {
    @apply bg-primary-500 hover:bg-primary-600 text-white font-medium py-2 px-4 rounded-lg transition-colors;
  }
  
  .btn-secondary {
    @apply bg-secondary-500 hover:bg-secondary-600 text-white font-medium py-2 px-4 rounded-lg transition-colors;
  }
  
  .input-field {
    @apply w-full px-4 py-2 border border-neutral-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary-500;
  }
}

2. Material-UI集成

安装Material-UI依赖:

pnpm add @mui/material@7.2.0 @emotion/react@11.14.0 @emotion/styled@11.14.1
pnpm add @mui/icons-material@7.2.0

配置MUI主题以匹配Tailwind颜色系统:

// src/theme.ts
import { createTheme } from '@mui/material/styles';

// 创建与Tailwind配置匹配的MUI主题
const theme = createTheme({
  palette: {
    primary: {
      main: '#3b82f6', // Tailwind primary-500
      light: '#60a5fa', // primary-400
      dark: '#1d4ed8', // primary-700
    },
    secondary: {
      main: '#ec4899', // Tailwind secondary-500
    },
    background: {
      default: '#f8fafc', // Tailwind neutral-50
      paper: '#ffffff',
    },
    text: {
      primary: '#0f172a', // Tailwind neutral-900
      secondary: '#475569', // neutral-600
    },
  },
  typography: {
    fontFamily: '"Inter", "system-ui", "sans-serif"',
    h1: {
      fontWeight: 700,
    },
    h2: {
      fontWeight: 600,
    },
    button: {
      textTransform: 'none', // 取消按钮文字大写
      fontWeight: 500,
    },
  },
  shape: {
    borderRadius: 12, // 匹配Tailwind的rounded-lg
  },
  components: {
    MuiButton: {
      styleOverrides: {
        root: {
          borderRadius: '0.5rem', // 8px
          fontWeight: 500,
        },
      },
    },
    MuiCard: {
      styleOverrides: {
        root: {
          borderRadius: '0.75rem', // 12px
          boxShadow: '0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)',
        },
      },
    },
  },
});

export default theme;

3. 集成使用

在应用入口文件中集成:

// src/index.tsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import { ThemeProvider } from '@mui/material/styles';
import CssBaseline from '@mui/material/CssBaseline';
import App from './App';
import theme from './theme';

// 先导入Tailwind样式
import './tailwind.css';
import './index.css';

const root = ReactDOM.createRoot(document.getElementById('app') as HTMLElement);
root.render(
  <React.StrictMode>
    <ThemeProvider theme={theme}>
      <CssBaseline />
      <App />
    </ThemeProvider>
  </React.StrictMode>
);

实际应用示例

结合使用Tailwind和MUI的组件

// src/components/WalletCard.tsx
import { Card, CardContent, Typography, Button } from '@mui/material';
import { AccountBalanceWallet, Logout } from '@mui/icons-material';
import { useWallet } from '../contexts/WalletContext';
import { formatAddress } from '../utils/web3';

const WalletCard = () => {
  const { account, balance, disconnect } = useWallet();

  return (
    <Card className="card w-full max-w-md mx-auto">
      <CardContent className="p-6">
        <div className="flex items-center justify-between mb-4">
          <div className="flex items-center space-x-2">
            <AccountBalanceWallet className="text-primary-500" />
            <Typography variant="h6" className="font-semibold">
              钱包信息
            </Typography>
          </div>
          <Button 
            variant="outlined" 
            size="small"
            startIcon={<Logout />}
            onClick={disconnect}
            className="text-neutral-600 border-neutral-300"
          >
            断开连接
          </Button>
        </div>
        
        <div className="space-y-3">
          <div>
            <Typography variant="body2" className="text-neutral-500">
              地址
            </Typography>
            <Typography className="font-mono text-sm">
              {formatAddress(account)}
            </Typography>
          </div>
          
          <div>
            <Typography variant="body2" className="text-neutral-500">
              余额
            </Typography>
            <Typography className="font-bold">
              {parseFloat(balance).toFixed(4)} ETH
            </Typography>
          </div>
          
          <Button 
            variant="contained" 
            className="btn-primary w-full mt-4"
          >
            发送交易
          </Button>
        </div>
      </CardContent>
    </Card>
  );
};

export default WalletCard;

Web3特色组件

// src/components/TransactionButton.tsx
import { Button, CircularProgress } from '@mui/material';
import { useState } from 'react';

interface TransactionButtonProps {
  onClick: () => Promise<void>;
  children: React.ReactNode;
  className?: string;
}

const TransactionButton = ({ onClick, children, className = '' }: TransactionButtonProps) => {
  const [loading, setLoading] = useState(false);
  const [success, setSuccess] = useState(false);

  const handleClick = async () => {
    setLoading(true);
    setSuccess(false);
    
    try {
      await onClick();
      setSuccess(true);
    } catch (error) {
      console.error('Transaction failed:', error);
    } finally {
      setTimeout(() => {
        setLoading(false);
        setSuccess(false);
      }, 2000);
    }
  };

  return (
    <Button
      variant="contained"
      onClick={handleClick}
      disabled={loading}
      className={`btn-primary relative overflow-hidden ${className}`}
      startIcon={loading && <CircularProgress size={20} className="text-white" />}
    >
      <span className={`transition-all ${loading ? 'opacity-0' : 'opacity-100'}`}>
        {children}
      </span>
      <span className={`absolute inset-0 flex items-center justify-center ${success ? 'opacity-100' : 'opacity-0'}`}>
        ✅ 成功
      </span>
    </Button>
  );
};

export default TransactionButton;

样式设计思考

在设计Web3应用的样式系统时,我考虑了以下几点:

  1. 品牌一致性:使用统一的颜色系统,建立品牌识别度
  2. 用户体验:清晰的视觉层次和交互反馈
  3. Web3特性:区块链相关元素的视觉设计
  4. 响应式设计:适配不同设备的显示需求
  5. 可访问性:符合WCAG标准的色彩对比度和交互设计

遇到的挑战

  1. 样式冲突:Tailwind和MUI的样式优先级需要仔细处理
  2. 主题一致性:确保两套系统的设计语言统一
  3. 性能优化:避免样式类的过度使用

总结

Tailwind CSS与Material-UI的组合为Web3项目提供了强大的样式解决方案。Tailwind的原子化CSS提高了开发效率,而Material-UI提供了丰富的组件和完善的设计系统。通过合理的配置和集成,可以充分发挥两者的优势,打造出既美观又实用的Web3应用界面。

下一篇,我将分享Web3技术栈的整合经验,包括Ethers.js与钱包连接方案的实现。