你好,我是 Kagol,个人公众号:前端开源星球

TinyVue 主题系统提供了一个全面的多层架构,用于为不同设计系统和主题需求设置组件样式。该架构既支持传统的基于 LESS 的主题,也支持现代的 Tailwind CSS 实用程序集成,能够在整个组件生态系统中保持一致性的同时,实现动态主题切换和广泛的自定义功能。

主题包组织结构

TinyVue 将其样式系统组织为专门的包,每个包服务于不同的主题需求和设计系统实现。核心主题包位于 packages/ 目录中,其中 @opentiny/vue-theme 提供传统的基于 LESS 的主题,而 @opentiny/vue-theme-saas 则为 SaaS 设计系统提供 Tailwind CSS 集成。

主题架构遵循三层包结构

样式技术 主要用例 关键特性
@opentiny/vue-theme LESS + CSS 变量 中小企业 (SMB) 三种内置主题、CSS 自定义属性、旧版支持
@opentiny/vue-theme-saas Tailwind CSS + Design Tokens SaaS 企业应用 实用程序优先、驱动令牌、现代主题
@opentiny/vue-theme (Design) Design Tokens 设计系统变体 Aurora、SaaS、SMB 变体

动态主题切换架构

主题系统通过 TinyThemeTool 类实现了一个复杂的运行时主题切换机制,该类利用现代浏览器 API 实现无需页面重载的无缝主题切换。该工具在两个主题包中都提供相同实现,为主题管理提供统一的 API。

TinyThemeTool 类使用 CSSStyleSheet API 将主题样式动态注入到文档或 shadow DOM 根中。该架构采用懒加载模式,并通过样式表缓存进行性能优化:

export default class TinyThemeTool {
  constructor(theme) {
    this.loaded = {} // 已加载样式表的缓存
    if (theme) {
      this.changeTheme(theme)
    }
  }
 
  changeTheme(theme, target = document) {
    let loadedSheet = this.loaded[target]
    if (!loadedSheet) {
      loadedSheet = new CSSStyleSheet()
      target.adoptedStyleSheets = [...target.adoptedStyleSheets, loadedSheet]
      this.loaded[target] = loadedSheet
    }
    // 处理并应用主题 CSS
    if (theme && (theme.data || theme.css)) {
      // 生成 CSS 变量或注入 CSS 字符串
      loadedSheet.replaceSync(cssContent)
    }
  }
}

主题变体和设计系统

TinyVue 提供多个预构建的主题变体,每个都针对特定用例和视觉偏好进行了优化。主题变体作为独立模块实现,可以根据应用程序需求按需加载或打包在一起。

标准主题变体

@opentiny/vue-theme 包包含三个全面的主题定义:

  1. 旧主题 (tiny-old-theme):具有蓝色品牌色 (#5e7ce0) 的旧版主题,保持向后兼容性
  2. Aurora 主题 (tiny-aurora-theme):具有鲜艳蓝色 (#1890ff) 的现代主题,为当代 UI 优化
  3. 深色主题 (tiny-dark-theme):具有中性品牌色 (#B3B3B3) 和适当对比度的深色模式实现

每个主题定义遵循一致的结构,包含主题元数据和 CSS 自定义属性:

export default {
  id: 'tiny-old-theme',
  name: 'OldTheme',
  cnName: '旧的主题',
  css: `:host,:root{--tv-base-color-brand:#5e7ce0;--tv-base-color-brand-1:#f2f5fc;...}`
}

设计系统集成

packages/design/ 目录包含专门的设计系统实现,扩展了核心主题功能:

  • Aurora 设计系统 (packages/design/aurora/):Aurora 设计语言的主题变体
  • SaaS 设计系统 (packages/design/saas/):企业级设计令牌和组件样式
  • SMB 设计系统 (packages/design/smb/):为中小企业优化的样式

这些设计系统为单个组件提供主题特定的覆盖,允许细粒度自定义,同时保持架构一致性。

Tailwind CSS 集成架构

SaaS 主题包实现了一个复杂的设计令牌系统,在语义设计令牌和 Tailwind CSS 实用程序类之间架起桥梁。该架构通过集中式令牌管理系统实现实用程序优先的样式,同时保持设计系统一致性。

Design Token 流水线

令牌流水线通过多阶段过程将基于 JSON 的设计令牌转换为与 Tailwind 兼容的配置:

loadTheme 插件通过以下关键函数处理设计令牌:

  1. loadColor:通过将语义颜色令牌(如 color-brandcolor-bg-1)映射到具有不透明度支持的原子颜色比例,将其转换为 Tailwind 颜色实用程序
  2. loadLayout:根据设计令牌规范生成 Tailwind 布局配置,包括间距、排版、阴影、边框和不透明度

语义颜色令牌映射

设计令牌系统使用复杂的映射方法,将语义令牌连接到原子颜色比例:

// 语义令牌定义
{
  "colors": {
    "color-brand": "brand-500,100",
    "color-brand-hover": "brand-400,100",
    "color-bg-1": "white,100"
  }
}
 
// 生成 Tailwind 配置
{
  color: {
    brand: 'var(--tiny-color-brand, #0067D1)',
    bg: {
      '1': 'var(--tiny-color-bg-1, #FFFFFF)'
    }
  }
}

这种映射使开发者能够使用语义类名(.bg-color-bg-1.text-color-brand),同时通过集中式令牌定义保持设计系统一致性。

组件样式架构

TinyVue 组件采用混合样式方法,结合预处理器功能和 CSS 自定义属性,实现静态优化和运行时主题灵活性。

基于 LESS 的组件样式

@opentiny/vue-theme 中的传统组件使用 LESS 预处理和系统性架构:

@import '../custom.less';
@import './vars.less';
 
@button-prefix-cls: ~'@{css-prefix}button';
 
.@{button-prefix-cls} {
  .inject-Button-vars();
  
  // 使用 CSS 自定义属性的基础样式
  border-radius: var(--tv-Button-border-radius);
  font-weight: var(--tv-Button-font-weight);
  
  // 响应式设计的尺寸混入
  .size-mixin(@size) {
    @fs: %('var(--tv-Button-font-size%a)', @size);
    @h: %('var(--tv-Button-height%a)', @size);
    // ...
  }
}

此架构提供:

  • 集中式变量管理通过 LESS 导入
  • 运行时主题通过 CSS 自定义属性 (var(--tv-*))
  • 响应式混入用于跨尺寸的一致缩放
  • 主题变体通过单独的主题特定 LESS 文件

Tailwind 实用程序集成

SaaS 主题组件通过 @apply 指令利用 Tailwind CSS 实用程序类:

@import '../mixins/button.less';
@import '../custom.less';
 
.@{button-prefix-cls} {
  @apply inline-block appearance-none text-center;
  @apply ~"min-w-[theme(spacing.18)]";
  @apply h-7;
  @apply text-color-text-primary;
  @apply border border-solid border-color-border;
  @apply rounded;
  transition: border 0.3s ease 0s, color 0.3s ease 0s;
}

此方法提供:

  • 实用程序优先的组合用于快速开发
  • 设计令牌集成通过语义类名(.text-color-text-primary
  • 类型安全令牌访问通过 Tailwind 的主题函数
  • 原子实用程序组合用于一致的样式模式

构建系统架构

主题构建系统实现了一个复杂的多阶段编译流水线,针对传统 LESS 处理和现代 Tailwind CSS 集成进行了优化。构建过程通过 Gulp 任务运行器编排,每个主题包都有专门的配置。

传统主题构建流水线

@opentiny/vue-theme 构建过程遵循以下顺序:

构建过程包括:

  1. 连接:将组件特定的 LESS 文件合并为统一的主题索引
  2. 多主题编译:为每个主题变体构建单独的 CSS 包
  3. SVG 优化:内联 SVG 资源以减少 HTTP 请求
  4. 自动前缀:确保跨浏览器兼容性
  5. 压缩:优化 CSS 用于生产部署

SaaS 主题构建流水线

SaaS 主题构建过程集成了 Tailwind CSS 编译:

gulp.src(lessFiles)
  .pipe(svgInline(svgInlineOption))
  .pipe(less())
  .pipe(postcss([tailwindcss('../tailwind.config.js'), require('autoprefixer')]))
  .pipe(prefixer({ borwsers: ['last 1 version', '> 1%', 'not ie <= 8'] }))
  .pipe(cssmin())
  .pipe(gulp.dest(dist))

关键构建特性:

  • PostCSS 集成用于 Tailwind CSS 处理
  • 设计令牌编译将 JSON 转换为 CSS 实用程序
  • 资源优化包括 SVG 内联和 CSS 压缩
  • 开发模式同步与主 Vue 项目

主题构建系统支持生产优化(压缩、死代码消除)和与主 Vue 项目热模块替换同步的开发工作流。

主题配置和组件映射

TinyVue 实现了一个复杂的组件映射系统,管理不同产品版本和组件集的主题配置。此配置支持对特定组件组的选择性主题,并支持不同产品代之间的迁移策略。

主题配置结构

主题配置以 JavaScript 和 JSON 格式维护,用于不同用例:

// theme.config.js - 组件特定的主题覆盖
export default [
  'action-menu', 'bulletin-board', 'button-group',
  'dialog-box', 'dropdown-menu', 'date-picker',
  // ... 70+ 需要专门主题的组件
]
 
// theme.config.json - 完整组件映射
{
  "tiny2": ["$", "tiny", "chart", "drag", "dialog", ...],
  "components": [
    "alert", "amount", "badge", "button", "calendar",
    "card", "dropdown", "form", "grid", "input", ...
  ]
}

这种双重配置系统支持:

  • 旧版迁移从 Tiny2 (tiny2 数组)
  • 组件级自定义通过选择性覆盖
  • 版本兼容性管理跨 TinyVue 代
  • 主题变体选择用于特定组件组

主题自定义策略

TinyVue 提供多种自定义方法,以适应不同的主题需求和开发者偏好。这些策略范围从简单的变量覆盖到完整的设计令牌替换。

CSS 自定义属性覆盖

最简单的自定义方法涉及覆盖 CSS 自定义属性:

:root {
  --tv-base-color-brand: #custom-brand-color;
  --tv-Button-border-radius: 8px;
  --tv-Button-font-size: 16px;
}

此方法需要最少的配置更改,并且适用于所有主题变体。

Design Token 修改

对于 SaaS 主题,修改设计令牌 JSON:

{
  "themeColor": [{
    "mode": "light",
    "data": {
      "brandColor": "#custom-color",
      "sceneColors": [{
        "title": "Brand Colors",
        "colors": {
          "color-brand": "brand-500,100"
        }
      }]
    }
  }]
}

修改后,重新构建主题包以生成更新的 Tailwind 配置。

自定义主题时,保持设计令牌层次结构的一致性。对语义令牌的更改应传播到所有依赖的原子令牌,以确保视觉一致性。

跨主题一致性模式

主题系统实现架构模式,以确保不同主题变体和设计系统之间的一致性:

令牌命名约定

传统和 SaaS 主题都遵循系统化的命名约定:

令牌类型 传统格式 SaaS 格式 示例
品牌颜色 --tv-base-color-brand --tiny-color-brand 主要品牌颜色
组件变量 --tv-Button-border-radius --tiny-borderRadius 组件特定属性
语义颜色 --tv-base-color-bg-1 --tiny-color-bg-1 背景颜色变体
间距 --tv-base-spacing-sm --tiny-spacing-sm 布局间距

组件样式契约

每个组件都遵循一致的样式契约:

  1. 从包级配置导入基础变量
  2. 使用 CSS 变量定义组件前缀 (@css-prefix)
  3. 使用混入模式注入组件变量 (.inject-Component-vars())
  4. 对所有可主题值应用 CSS 自定义属性
  5. 为响应式设计场景提供尺寸混入

此契约确保组件在所有主题变体中一致工作,同时支持自定义样式扩展。

架构总结

TinyVue 主题系统提供了一个全面的多层架构,支持:

  • 动态主题切换通过 CSSStyleSheet API 和运行时性能优化
  • 多个主题变体包括旧版、现代和深色模式实现
  • 双重样式方法结合传统 LESS 预处理与现代 Tailwind CSS 实用程序
  • 设计令牌系统实现系统化自定义和设计系统一致性
  • 复杂的构建流水线针对开发工作流和生产部署进行优化
  • 组件级主题具有选择性覆盖和版本兼容性管理

此架构使开发者能够创建视觉一致、主题灵活的应用程序,同时在大规模企业部署中保持性能和可维护性。

联系我们

GitHub:https://github.com/opentiny/tiny-vue(欢迎 Star ⭐)

官网:https://opentiny.design/tiny-vue

个人博客:kagol.com.cn

小助手微信:opentiny-official

公众号:OpenTiny

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐