一个基于 Vue 3、TypeScript、Reka UI、Tailwind CSS 和 CSS Variables 的 B2B 组件示例项目。
项目重点不是做一套业务页面,而是沉淀一套可复用的 headless UI 封装:Reka UI 负责无样式交互行为,src/components/ui 提供设计系统组件,主题和视觉状态通过语义 token 管理。
- Vue 3 +
<script setup> - TypeScript
- Vite
- Vue Router
- Reka UI
- Tailwind CSS 4
- CSS Variables theme tokens
- Class Variance Authority
- Iconify local icon pipeline
pnpm install
pnpm dev构建生产产物:
pnpm build预览生产构建:
pnpm preview构建 GitHub Pages 产物:
pnpm build:github-pages重新生成本地图标集合:
pnpm icons:build
dev和build前会自动执行scripts/build-icons.mjs,确保本地图标 JSON 是最新的。
src/
components/
primitives/ # Reka UI primitives 的薄转发层
ui/ # 项目级设计系统组件
business/ # 面向业务场景的组合组件
shared/ # 组件共享工具
composables/ # 组合式逻辑
icons/ # 本地图标生成产物
router/ # 路由
styles/
tokens/ # 基础 token、密度、组件 token
themes/ # 主题变量覆盖
views/ # 示例页面
本项目遵循单向依赖:
primitives -> ui -> business
约束:
- 只有
src/components/primitives可以直接 importreka-ui。 src/components/ui只依赖primitives、共享工具和样式 token。src/components/business可以依赖ui,不直接依赖 Reka UI。- 页面和业务组件不直接使用 Reka UI primitives。
- 主题逻辑只放在 CSS variables,不在 Vue 逻辑里按主题分支。
UI 组件位于 src/components/ui:
buttonselectdropdowndialogswitchslidertooltiptoastinputdate-pickertime-range-pickercascadertabstablepagination
对应需要 Reka 行为的组件,会先在 src/components/primitives 中建立转发层,例如:
selectdropdown-menudialogswitchslidertooltiptoastdate-pickertime-range-fieldtabspagination
当前应用首页是组件总览页,集中展示:
- 按钮和语义色
- 图标
- Tabs
- 表格与分页
- 表单控件
- 浮层与反馈
- 右下角悬浮主题切换
访问开发服务后打开:
http://localhost:5173/
|
|
|
|
项目已内置 GitHub Actions workflow:
.github/workflows/deploy-github-pages.yml
每次推送到 main 后会自动:
- 安装依赖。
- 使用
/headless-2b/作为 Vite base 构建产物。 - 复制
dist/index.html为dist/404.html,支持前端路由刷新回退。 - 发布到 GitHub Pages。
首次使用时需要在 GitHub 仓库设置中启用 Pages:
Settings -> Pages -> Build and deployment -> Source -> GitHub Actions
部署完成后访问:
https://wuchib.github.io/headless-2b/
主题相关文件:
src/styles/tokens/base.csssrc/styles/tokens/density.csssrc/styles/tokens/level/*src/styles/tokens/comps/*src/styles/themes/*
样式规则:
- 优先使用语义 token:
bg-background、bg-surface、text-foreground、text-muted-foreground、border-border、bg-primary。 - 不使用硬编码 Tailwind 色值,例如
bg-blue-500、text-slate-900、border-red-300。 - 状态样式优先使用稳定属性:
data-state、data-disabled、data-selected、aria-invalid。 - 组件视觉差异集中放在
*.variants.ts。 - 每个组件自己的 CSS variables 放在
src/styles/tokens/comps/<component>.css。
项目使用本地图标生成流程,生成产物在:
src/icons/generated/
图标可以在模板中通过 Tailwind Iconify class 使用,例如:
<span class="icon-[app--search] size-4" aria-hidden="true"></span>
<span class="icon-[app-color--vue-mark] size-8" aria-hidden="true"></span>新增组件时建议按以下顺序:
- 判断是否需要 Reka 行为 primitive。
- 如需要,先在
src/components/primitives/<name>/index.ts建立薄转发层。 - 在
src/components/ui/<name>中实现 UI 封装。 - 新增
<name>.variants.ts管理 variant、size、tone 等样式分支。 - 在
src/styles/tokens/comps/<name>.css增加组件 token。 - 更新:
src/components/primitives/index.tssrc/components/ui/index.tssrc/styles/tokens/comps/index.css
- 在
src/views/ComponentOverviewPage.vue增加最小可交互示例。
提交前建议运行:
pnpm build
rg "reka-ui" src
rg "\b(bg|text|border|from|to|via|ring|stroke|fill)-(slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose)-[0-9]{2,3}\b" src
git diff --check预期:
- 构建通过。
reka-ui直引只出现在src/components/primitives。- 没有硬编码 Tailwind 色值。
- 没有空白错误。



