flnxi-Wu/docs/guides/THEME_STYLES_MIGRATION.md
WuYongJie e4dcb6260a
Some checks failed
CI Check / check (push) Has been cancelled
feat: Admin页面重构 & UI三层架构系统
- 创建统一UI三层架构系统(基础层、颜色层、组合层)
- 拆分Admin页面为独立Tab组件(MonitorTab、UsersTab、DepartmentsTab等)
- 提取公共逻辑到Hooks(useToast、useDataFetch、useUserOperations等)
- 提取工具函数(validators、formatters、api等)
- 创建统一弹窗组件(Modal)和useModal Hook
- 添加错误边界和统一状态组件
- 完善类型定义和可访问性支持
- 更新文档(优化记录、优化计划、更新日志)
2025-11-22 15:17:10 +08:00

5.0 KiB
Raw Blame History

深浅色样式分离迁移指南

概述

为了解决深浅色适配问题,我们重构了 UI 样式系统,采用两套独立的配置文件:

  • 浅色模式:lib/ui-styles-light.ts
  • 深色模式:lib/ui-styles-dark.ts

优势

之前的问题

  • 每个样式字符串都包含 dark: 前缀,代码冗长
  • 容易遗漏 dark: 前缀,导致深色模式显示不正确
  • 维护困难,需要在同一字符串中同时考虑两种模式

现在的优势

  • ✅ 代码更清晰:每个样式只包含一套类名
  • ✅ 更容易维护:修改时只需要考虑一种模式
  • ✅ 避免遗漏:不会忘记添加 dark: 前缀
  • ✅ 类型安全:TypeScript 能更好地检查样式使用

使用方式

方式一:使用 useThemeStyles() Hook(推荐)

适用于客户端组件('use client'):

'use client'

import { useThemeStyles } from '@/lib/ui-styles'

export default function MyComponent() {
  // 自动根据当前主题返回对应的样式配置
  const styles = useThemeStyles()
  
  return (
    <div className={styles.cardStyles.base}>
      <button className={styles.buttonStyles.primary}>
        主要按钮
      </button>
      <button className={`${styles.buttonStyles.secondary} ${styles.buttonModifiers.compact}`}>
        次要按钮
      </button>
    </div>
  )
}

方式二:继续使用原有导入(向后兼容)

原有的 lib/ui-styles.ts 仍然保留,包含 dark: 前缀的样式:

import { cardStyles, buttonStyles, buttonModifiers } from '@/lib/ui-styles'

export default function MyComponent() {
  return (
    <div className={cardStyles.base}>
      <button className={buttonStyles.primary}>
        主要按钮
      </button>
    </div>
  )
}

注意:这种方式仍然可以工作,但建议逐步迁移到 useThemeStyles()。

迁移步骤

1. 将组件改为客户端组件

如果组件是服务端组件,需要添加 'use client':

'use client'  // 添加这一行

import { useThemeStyles } from '@/lib/ui-styles'

2. 替换样式导入

之前:

import { cardStyles, buttonStyles } from '@/lib/ui-styles'

export default function MyComponent() {
  return (
    <div className={cardStyles.base}>
      <button className={buttonStyles.primary}>按钮</button>
    </div>
  )
}

之后:

'use client'
import { useThemeStyles } from '@/lib/ui-styles'

export default function MyComponent() {
  const styles = useThemeStyles()
  
  return (
    <div className={styles.cardStyles.base}>
      <button className={styles.buttonStyles.primary}>按钮</button>
    </div>
  )
}

3. 批量替换模式

如果有多个组件需要迁移,可以使用搜索替换:

查找:

import { cardStyles, buttonStyles, inputStyles, buttonModifiers } from '@/lib/ui-styles'

替换为:

'use client'
import { useThemeStyles } from '@/lib/ui-styles'

// 在组件内部:
const styles = useThemeStyles()
// 然后使用 styles.cardStyles、styles.buttonStyles 等

可用样式

两套配置的结构完全相同,包含:

  • cardStyles - 卡片样式

    • base, hover, large, flat, rainbow, glass, neon
  • buttonStyles - 按钮样式

    • primary, secondary, ghost, danger, success, rainbow, neon, glass
  • buttonModifiers - 按钮修饰符

    • compact, compactXs, icon, block, pill
  • inputStyles - 输入框样式

    • base, error
  • inputModifiers - 输入框修饰符

    • compact, compactXs
  • navItemStyles - 导航项样式

    • base, hover, active, rainbow, tabBase, tabActive
  • badgeStyles - 徽章样式

    • base, primary, success, warning, danger
  • spacingStyles - 间距样式

    • section, card, form, compact

示例

完整的组件示例

'use client'

import { useThemeStyles } from '@/lib/ui-styles'
import { cn } from '@/lib/ui-styles'

export default function UserCard({ user }: { user: User }) {
  const styles = useThemeStyles()
  
  return (
    <div className={styles.cardStyles.hover}>
      <h3 className="text-lg font-semibold">{user.name}</h3>
      <p className="text-sm opacity-75">{user.email}</p>
      
      <div className="mt-4 flex gap-2">
        <button className={styles.buttonStyles.primary}>
          编辑
        </button>
        <button className={cn(styles.buttonStyles.secondary, styles.buttonModifiers.compact)}>
          删除
        </button>
      </div>
    </div>
  )
}

注意事项

  1. 客户端组件:使用 useThemeStyles() 的组件必须是客户端组件(添加 'use client')
  2. 主题切换:Hook 会自动监听主题变化,组件会自动更新样式
  3. 性能:样式配置是静态导入的,不会影响打包大小
  4. 向后兼容:原有代码仍然可以工作,可以逐步迁移

下一步

  • 迁移现有组件到新的样式系统
  • 移除 lib/ui-styles.ts 中的 dark: 前缀(迁移完成后)
  • 统一使用 useThemeStyles() Hook