未验证 提交 3bdb469b 编辑于 作者: cyole's avatar cyole
浏览文件

chore: initialize zui demo project

上级
root = true
[*]
indent_size = 2
end_of_line = lf
insert_final_newline = true
## 本次完成
-
## 处理组件
-
## 修改文件
-
## 验证结果
- [ ] `pnpm lint`
- [ ] `pnpm typecheck`
- [ ] `pnpm test`
- [ ] `pnpm dev` 手动查看文档站点
## 遗留问题
-
name: CI
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install pnpm
uses: pnpm/action-setup@v4.1.0
- name: Set node
uses: actions/setup-node@v4
with:
node-version: lts/*
cache: pnpm
- name: Install
run: pnpm install
- name: Lint
run: pnpm lint
typecheck:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install pnpm
uses: pnpm/action-setup@v4.1.0
- name: Set node
uses: actions/setup-node@v4
with:
node-version: lts/*
cache: pnpm
- name: Install
run: pnpm install
- name: Typecheck
run: pnpm typecheck
name: Release
permissions:
contents: write
on:
push:
tags:
- 'v*'
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-node@v4
with:
node-version: lts/*
- run: npx changelogithub
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
name: Unit Test
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install pnpm
uses: pnpm/action-setup@v4.1.0
- name: Set node LTS
uses: actions/setup-node@v4
with:
node-version: lts/*
cache: pnpm
- name: Install
run: pnpm install
- name: Build
run: pnpm build
- name: Test
run: pnpm test
node_modules
dist
es
*.log
.DS_Store
.eslintcache
coverage
cache
docs/.vitepress/.temp
docs/.vitepress/cache
# generated
components.d.ts
auto-imports.d.ts
typed-router.d.ts
shamefully-hoist=true
strict-peer-dependencies=false
enforce-constraints=false
trust-check=false
trust-policy=ignore-all
@zsdx:registry=https://developer-center.wxhand.com/verdaccio/
@zui:registry=https://developer-center.wxhand.com/verdaccio/
# Agent Instructions for ZUI Demo
This is a demo scaffold for a Vue 3 component library modeled after ZUI.
## Commands
- Install dependencies: `pnpm install`
- Build library: `pnpm build`
- Run docs: `pnpm dev`
- Run playground: `pnpm play`
- Lint: `pnpm lint`
- Typecheck: `pnpm typecheck`
- Test: `pnpm test`
## Component Structure
New components should follow this structure:
```text
src/[component-name]/
├── index.ts
├── src/
│ ├── [ComponentName].vue
│ ├── interface.ts
│ └── styles/
│ └── index.ts
├── demos/
│ ├── index.md
│ └── basic.vue
└── tests/
└── [ComponentName].test.ts
```
## Conventions
- Use Vue 3 `<script setup lang="ts">`.
- Component names should use the `Z` prefix, for example `ZButton`.
- Props should be declared in `interface.ts` and consumed through `defineProps(componentProps)`.
- Use JSS through `createStyleSheet` from `src/_utils/jss`.
- Keep demos reusable and focused on one usage scenario.
- Keep API tables aligned with `interface.ts`.
# ZUI Demo
这是一个从 ZUI 拆出的组件库示例项目。
它保留了组件库项目所需的基础工程能力,包括:
- Vue 3 组件库源码目录。
- VitePress 文档站点。
- Playground 调试项目。
- tsdown 构建配置。
- Vitest 测试配置。
- pnpm workspace 配置。
- ESLint、TypeScript、JSS 基础工具。
当前项目保留 `src/example-button` 作为完整写法参考,同时预置了多个简单组件骨架,例如 `button``tip``avatar-tag``badge``alert``card``copy-text``divider``empty``loading``progress``section-title``stat-card``status-dot``tag`。预置组件的 demo 和文档内容故意留得比较少,方便同学按任务要求补充。
## 开发命令
```bash
pnpm install
pnpm dev
pnpm play
pnpm build
pnpm lint
pnpm typecheck
pnpm test
```
## 任务提交
新手介绍文档见 [docs/guide/student-guide.md](./docs/guide/student-guide.md)
任务提交说明见 [SUBMISSION.md](./SUBMISSION.md)
## 目录说明
```text
src/ 组件库源码
docs/ VitePress 文档站点
playground/ 本地调试项目
tests/ 公共测试
templates/ 任务交付模板
```
# 任务提交说明
本文档用于说明同学在本项目中完成组件库支持任务时,应该如何开发、提交和交付。
## 工作范围
优先处理预置组件的以下内容:
- 补充 `src/[component]/demos/*.vue` 示例。
- 完善 `src/[component]/demos/index.md` 文档说明。
- 对照 `src/[component]/src/interface.ts` 补充 API 表格。
- 整理测试场景,必要时补充 `src/[component]/tests/*.test.ts`
- 记录发现的问题和建议。
`src/example-button` 是完整参考组件,可以参考它的目录结构、文档、demo 和测试写法。
## 开发流程
1.`main` 拉取最新代码。
2. 创建任务分支,建议命名为 `task/[组件名]-docs``task/[组件名]-demo`
3. 选择 1 到 3 个组件完成文档、demo、API 或测试场景补充。
4. 本地运行文档站点检查效果。
5. 运行必要的质量检查。
6. 提交代码并发起 PR。
## 常用命令
```bash
pnpm install
pnpm dev
pnpm lint
pnpm typecheck
pnpm test
```
如只运行某个组件测试:
```bash
npx vitest src/[component]/tests/[ComponentName].test.ts
```
## 提交信息规范
建议使用以下格式:
```text
type(scope): description
```
常用类型:
- `docs`:文档调整。
- `demo`:示例补充。
- `test`:测试补充。
- `fix`:问题修复。
- `chore`:工程配置或非功能调整。
示例:
```text
docs(button): 补充按钮组件 API 表格
demo(empty): 新增自定义图片示例
test(tag): 增加可关闭标签测试场景
```
## PR 内容要求
PR 描述至少包含:
- 本次处理的组件。
- 新增或修改的文档、demo、测试文件。
- 已运行的验证命令。
- 发现但尚未处理的问题。
## 验收口径
- 文档描述清晰,命名统一,无明显错别字。
- demo 可以在文档站点正常展示,代码可复用。
- API 表格与 `interface.ts` 一致。
- 测试场景覆盖核心使用方式、禁用态、边界值或异常态。
- 问题反馈包含复现方式、预期结果和实际结果。
import type { ComponentResolver } from 'unplugin-vue-components/types'
import type { DefaultTheme } from 'vitepress'
import { existsSync, readdirSync, readFileSync } from 'node:fs'
import path from 'node:path'
import VueJsx from '@vitejs/plugin-vue-jsx'
import UnoCSS from 'unocss/vite'
import Components from 'unplugin-vue-components/vite'
import { defineConfig } from 'vitepress'
import { vitepressDemoPlugin } from 'vitepress-demo-plugin'
import { groupIconMdPlugin, groupIconVitePlugin } from 'vitepress-plugin-group-icons'
import { version } from '../../package.json'
import { DocsPlugin } from './plugins/vite-plugin-docs'
const title = 'ZUI Demo'
const description = 'Vue 3 Component Library Demo'
const componentNameRE = /^(?:Z[A-Z]|z-[a-z])/
const markdownTitleRE = /# (.*)/
const docsRootDir = path.resolve(__dirname, '../../')
const sourceDir = path.resolve(docsRootDir, 'src')
function ZuiResolver(): ComponentResolver {
return {
type: 'component',
resolve: (name: string) => {
if (componentNameRE.test(name))
return { name, from: sourceDir }
},
}
}
const Start: DefaultTheme.NavItemWithLink[] = [
{ text: '介绍', link: '/docs/guide/introduction' },
{ text: '新手任务指南', link: '/docs/guide/student-guide' },
{ text: '快速上手', link: '/docs/guide/getting-started' },
{ text: '任务提交', link: '/docs/guide/submission' },
{ text: '常见问题', link: '/docs/guide/faq' },
]
function getComponentsList(): DefaultTheme.NavItemWithLink[] {
const files = readdirSync(sourceDir, { withFileTypes: true })
const exclude = ['_utils', 'composables']
return files.map((file) => {
const mdFile = `${sourceDir}/${file.name}/demos/index.md`
if (file.isDirectory() && existsSync(mdFile) && !exclude.includes(file.name)) {
const component = file.name
const componentTitle = readFileSync(mdFile, 'utf-8').match(markdownTitleRE)?.[1] ?? component
return {
text: componentTitle,
link: `/components/${component}`,
}
}
return undefined
}).filter(item => !!item)
}
const SidebarComponents: DefaultTheme.NavItemWithLink[] = getComponentsList()
export default defineConfig({
lang: 'zh-Hans',
title,
description,
srcDir: docsRootDir,
outDir: '../dist',
srcExclude: ['playground', 'packages', '**/README.md', 'AGENTS.md'],
rewrites: {
'docs/index.md': 'index.md',
'docs/components/index.md': 'components/index.md',
'src/:component/demos/index.md': 'components/:component.md',
},
markdown: {
languages: ['js', 'jsx', 'ts', 'tsx', 'vue'],
config: (md) => {
md.use(groupIconMdPlugin)
md.use(vitepressDemoPlugin, {
demoDir: sourceDir,
})
},
},
vite: {
plugins: [
Components({
dts: 'docs/components.d.ts',
include: [/\.vue$/, /\.vue\?vue/, /\.md$/],
resolvers: [
ZuiResolver(),
],
}),
UnoCSS(),
groupIconVitePlugin(),
DocsPlugin(),
VueJsx(),
],
},
lastUpdated: true,
cleanUrls: true,
themeConfig: {
search: {
provider: 'local',
options: {},
},
nav: [
{ text: '主页', link: '/' },
{
text: '文档',
items: Start,
activeMatch: '^/docs/',
},
{
text: '组件',
link: '/components/',
activeMatch: '^/components/',
},
{
text: `v${version}`,
items: [],
},
],
sidebar: {
'/docs/': [
{
text: '开始',
items: Start,
},
],
'/components/': [
{
text: '组件总览',
link: '/components/',
},
{
text: '组件',
items: SidebarComponents,
},
],
},
footer: {
message: '基于 MIT 许可发布',
},
docFooter: {
prev: '上一页',
next: '下一页',
},
outline: {
label: '页面导航',
},
lastUpdated: {
text: '最后更新于',
},
notFound: {
title: '页面未找到',
linkLabel: '回到首页',
linkText: '回到首页',
},
},
})
import type { Plugin, ResolvedConfig } from 'vite'
import { existsSync, readFileSync, writeFileSync } from 'node:fs'
import fg from 'fast-glob'
const demoBlockRE = /<!-- DEMO -->[\s\S]*<!-- DEMO -->/
const demoFileRE = /demos\/.*\.vue$/
function generateDemos(demosDir: string) {
const currentMdPath = `${demosDir}/index.md`
if (!existsSync(currentMdPath))
return
const currentMdContent = readFileSync(currentMdPath, 'utf-8')
const allDemos = fg.sync(`${demosDir}/*.vue`, { objectMode: true })
const allDemosContent = allDemos.map((demo) => {
const demoPath = `${demosDir.split('/').slice(-2).join('/')}/${demo.name}`
return `<demo vue="${demoPath}" />`
}).join('\n')
const newMdContent = currentMdContent.replace(demoBlockRE, `<!-- DEMO -->\n\n${allDemosContent}\n\n<!-- DEMO -->`)
writeFileSync(currentMdPath, newMdContent)
}
export function DocsPlugin(): Plugin {
let userConfig: ResolvedConfig | undefined
return {
name: 'vite-plugin-docs',
configResolved(config) {
userConfig = config
},
configureServer({ watcher }) {
watcher.on('all', (event, filePath) => {
if (event !== 'add' && event !== 'unlink')
return
if (!demoFileRE.test(filePath))
return
const demosDir = filePath.split('/').slice(0, -1).join('/')
generateDemos(demosDir)
})
},
buildStart() {
const allDemosDir = fg.sync(`${userConfig?.root}/src/**/demos`, { onlyDirectories: true })
allDemosDir.forEach((demoDir) => {
if (existsSync(`${demoDir}/index.md`))
generateDemos(demoDir)
})
},
}
}
# 组件总览
当前项目保留了一个完整参考组件:
- [示例按钮 ExampleButton](/components/example-button)
同时预置了以下待补充组件:
- [按钮 Button](/components/button)
- [提示 Tip](/components/tip)
- [头像标签 AvatarTag](/components/avatar-tag)
- [徽标 Badge](/components/badge)
- [警告提示 Alert](/components/alert)
- [卡片 Card](/components/card)
- [复制文本 CopyText](/components/copy-text)
- [分割线 Divider](/components/divider)
- [空状态 Empty](/components/empty)
- [加载 Loading](/components/loading)
- [进度条 Progress](/components/progress)
- [区块标题 SectionTitle](/components/section-title)
- [统计卡片 StatCard](/components/stat-card)
- [状态点 StatusDot](/components/status-dot)
- [标签 Tag](/components/tag)
参考组件用于说明完整写法;预置组件用于同学补充 demo、文档、API 表格和测试场景。
# 常见问题
## 为什么组件总览为空?
这是空项目骨架。只有当组件目录中存在 `demos/index.md` 时,该组件才会出现在文档站点组件导航中。
## API 表格从哪里校对?
优先对照组件目录下的 `src/interface.ts`
# 快速上手
## 安装依赖
```bash
pnpm install
```
## 启动文档站点
```bash
pnpm dev
```
## 启动 Playground
```bash
pnpm play
```
## 新增组件
`src` 下创建组件目录:
```text
src/button/
├── index.ts
├── src/
│ ├── Button.vue
│ ├── interface.ts
│ └── styles/index.ts
├── demos/
│ ├── index.md
│ └── basic.vue
└── tests/
└── Button.test.ts
```
然后在 `src/index.ts` 中导出组件。
## 参考示例
项目保留了 `src/example-button` 作为示例组件,可以参考它的源码、文档、demo 和测试写法。
# 介绍
ZUI Demo 是一个 Vue 3 组件库示例项目,用于快速开始组件库研发、文档维护和示例沉淀。
## 特性
- 基于 Vue 3。
- 使用 VitePress 管理文档。
- 使用 tsdown 构建组件库产物。
- 使用 Vitest 进行单元测试。
- 使用 JSS 组织组件样式。
# ZUI Demo 新手任务指南
这份文档是给刚开始接触前端、Vue 或组件库的同学看的。你不需要一开始就完全理解项目里的每一行代码,只要按步骤完成文档、示例、API 校对和测试场景整理,就可以逐步上手。
## 你要做什么
一句话:帮助组件库变得更好用、更好懂、更容易推广。
具体来说,你主要做这些事情:
- 给组件补充使用文档。
- 给组件补充可运行的 demo 示例。
- 对照源码校对 Props、Events、Slots 等 API 信息。
- 整理组件应该测试哪些场景。
- 发现文档、示例或组件问题时,记录清楚并反馈。
你不是来一开始就写复杂组件的,也不是来大规模改底层架构的。这个任务更像是“组件库助教”:把已有组件讲清楚、示例补完整、问题整理出来。
## 先理解几个词
组件:页面上的一个可复用功能块,例如按钮、标签、空状态、进度条。
Props:外部传给组件的参数,例如按钮的 `type``disabled``loading`
Events:组件向外发出的事件,例如按钮被点击后触发 `click`
Slots:组件预留的内容位置,例如卡片组件里的标题、右侧操作区、正文内容。
Demo:一个可以直接运行的示例,用来告诉别人“这个组件应该怎么用”。
API 文档:把 Props、Events、Slots 用表格写清楚,方便使用者查询。
测试场景:列出组件在不同情况下应该表现成什么样,例如正常、禁用、加载、空数据、错误状态。
PR:Pull Request,意思是把你改好的代码提交给负责人检查和合并。
## 项目是什么
`ZUI Demo` 是一个组件库示例项目。它保留了真实组件库常见的工程结构,但组件比较简单,适合练习组件文档、demo 和测试整理。
项目里有一个完整参考组件:
- `src/example-button`
你可以先看它,了解一个完整组件通常包含哪些文件。
项目里还有一些待补充组件,例如:
- `src/button`
- `src/tip`
- `src/avatar-tag`
- `src/badge`
- `src/alert`
- `src/card`
- `src/copy-text`
- `src/divider`
- `src/empty`
- `src/loading`
- `src/progress`
- `src/section-title`
- `src/stat-card`
- `src/status-dot`
- `src/tag`
这些组件的源码已经有了,也保留了基础 demo。你的任务不是从零开始,而是在基础 demo 之上继续补充更多场景,例如禁用态、加载态、自定义内容、边界值和异常状态。
## 目录怎么看
你最常看的目录是 `src`
一个组件通常长这样:
```text
src/button/
├── index.ts
├── src/
│ ├── Button.vue
│ ├── interface.ts
│ └── styles/
│ └── index.ts
└── demos/
└── index.md
```
几个关键文件:
- `Button.vue`:组件本体,写页面结构和交互逻辑。
- `interface.ts`:组件参数、事件、插槽的类型定义。
- `styles/index.ts`:组件样式。
- `demos/index.md`:组件文档页面。
- `demos/*.vue`:组件示例。
如果你只做文档和示例,通常主要改 `demos/index.md``demos/*.vue`。每个预置组件都有一个 `basic.vue`,可以先看它,再补更多 demo。
## 第一次怎么跑项目
进入项目目录:
```bash
cd ~/code/zui-demo
```
安装依赖:
```bash
pnpm install
```
启动文档站点:
```bash
pnpm dev
```
启动后打开终端里显示的地址,一般是:
```text
http://localhost:5173/
```
如果端口被占用,终端会显示另一个端口,按终端提示打开即可。
## 一次任务怎么做
建议每次只选 1 到 3 个组件,不要一口气改太多。
1. 选一个组件,例如 `button`
2. 打开 `src/button/src/interface.ts`,看它有哪些 Props、Events、Slots。
3. 打开 `src/button/src/Button.vue`,大概看组件实际怎么用这些参数。
4. 打开 `src/button/demos/index.md`,补充组件介绍和 API 表格。
5. 查看已有的 `basic.vue`,再新增更多 demo,例如 `disabled.vue``loading.vue`
6. 启动 `pnpm dev`,在文档站点里检查 demo 能不能正常显示。
7. 整理这个组件还应该测试哪些场景。
8. 提交代码前运行检查命令。
## 文档怎么写
组件文档建议包含四部分:
```md
# 按钮 Button
一句话说明这个组件是做什么的。
## 何时使用
说明适合用在什么场景,不适合用在什么场景。
## 演示
<!-- DEMO -->
<demo vue="button/demos/basic.vue" />
<!-- DEMO -->
## API
### Button Props
| 名称 | 类型 | 默认值 | 说明 |
| ---- | ------------------------ | ----------- | -------- |
| type | `'default' \| 'primary'` | `'default'` | 按钮类型 |
```
写文档时注意:
- 先说人话,再列 API。
- 不要只写“基础用法”,要说明这个示例展示了什么。
- API 表格必须对照 `interface.ts`,不要凭感觉写。
- 默认值要认真检查,源码里没有默认值时不要乱写。
## Demo 怎么写
一个 demo 只讲一个场景。
推荐命名:
- `basic.vue`:基础用法。
- `disabled.vue`:禁用状态。
- `loading.vue`:加载状态。
- `custom.vue`:自定义内容。
- `size.vue`:尺寸。
- `color.vue`:颜色。
一个简单 demo 可以这样写:
```vue
<template>
<ZButton type="primary">
保存
</ZButton>
</template>
```
如果 demo 里有交互,可以这样写:
```vue
<script setup lang="ts">
function handleClick() {
console.log('clicked')
}
</script>
<template>
<ZButton @click="handleClick">
点击
</ZButton>
</template>
```
写 demo 时注意:
- 代码要短,能说明问题就好。
- 不要写太复杂的业务逻辑。
- 示例里的中文文案要自然,例如“保存”“提交”“暂无数据”。
- 一个 demo 里不要混太多场景。
- 写完一定要在文档站点里看一遍。
## API 怎么校对
API 主要看 `interface.ts`
例如:
```ts
export const buttonProps = {
type: {
type: String as PropType<ButtonType>,
default: 'default',
},
loading: Boolean,
disabled: Boolean,
} as const
```
就可以整理成:
| 名称 | 类型 | 默认值 | 说明 |
| -------- | ------------------------------------ | ----------- | ---------------- |
| type | `'default' \| 'primary' \| 'danger'` | `'default'` | 按钮类型 |
| loading | `boolean` | `false` | 是否展示加载状态 |
| disabled | `boolean` | `false` | 是否禁用按钮 |
校对顺序:
1. 先找 Props。
2. 再找 Events,也就是 `defineEmits``interface.ts` 里的 Events。
3. 再找 Slots,也就是 `defineSlots` 或 Slots 类型。
4. 最后看 demo 是否覆盖了常用 API。
## 测试场景怎么整理
如果你还不熟悉写测试,可以先整理测试场景清单。
例如按钮组件可以整理:
| 场景 | 预期结果 |
| ---------------- | ---------------------------- |
| 默认渲染 | 页面能看到按钮文字 |
| type 为 primary | 展示主要按钮样式 |
| disabled 为 true | 按钮不可点击 |
| loading 为 true | 展示加载状态,点击不触发事件 |
| 点击按钮 | 触发 click 事件 |
如果要补测试,可以参考:
```ts
import { mount } from '@vue/test-utils'
import { ZButton } from '../index'
it('emits click event', async () => {
const wrapper = mount(ZButton)
await wrapper.trigger('click')
expect(wrapper.emitted('click')).toHaveLength(1)
})
```
## 提交前检查
提交前至少跑:
```bash
pnpm lint
pnpm typecheck
pnpm test
```
如果你改了文档或 demo,还要启动文档站点看页面:
```bash
pnpm dev
```
如果检查失败,不要慌。先看终端里报错的文件名和行号,通常会告诉你哪里写错了。
## 每周交付什么
每周交付建议包含:
- 完成了哪些组件。
- 每个组件补了哪些 demo。
- 每个组件 API 是否校对完成。
- 发现了哪些问题。
- 运行了哪些检查命令。
- 还有哪些不确定的地方。
可以使用 `templates/weekly-report.md` 填写周报。
## 分支和提交怎么写
分支名建议:
```text
task/button-docs
task/empty-demo
task/tag-tests
```
提交信息建议:
```text
docs(button): 补充按钮组件文档
demo(empty): 新增空状态示例
test(tag): 补充标签组件测试
```
PR 描述可以直接使用项目里的 `.github/pull_request_template.md`
## 可以用 AI 吗
可以,但要注意:
- AI 可以帮你起草文档,但你要对照源码确认。
- AI 可以帮你列测试场景,但你要判断是否真的适合这个组件。
- AI 可以帮你写 demo,但你要在文档站点里运行验证。
- 不要把没看懂、没验证的内容直接提交。
一个比较好的使用方式:
```text
请根据这个 interface.ts 帮我整理 Props 表格,并给出 3 个 demo 场景建议。
```
然后你自己再检查类型、默认值、说明是否准确。
## 常见问题
看不懂组件源码怎么办?
先看 `interface.ts`,再看 demo,不需要一开始读懂所有实现细节。
不知道 demo 写什么怎么办?
先写基础用法、禁用态、加载态、空状态、自定义内容这几类。
API 表格不知道默认值怎么办?
`interface.ts` 里找 `default`。如果没有 default,布尔值通常是 `false`,字符串或对象不要乱猜,可以写 `undefined` 或询问负责人。
测试不会写怎么办?
先整理测试场景清单。能写测试时,再参考 `src/example-button/tests/ExampleButton.test.ts`
改完页面没变化怎么办?
先确认文件保存了,再刷新浏览器。如果新增了 demo 文件,检查 `demos/index.md` 里有没有 `<demo vue="..." />`
## 最后给你的建议
不要追求一次写得很大,组件库维护更看重准确、清楚、可复用。
每次做好一个小组件,就是一次完整交付。先把一个组件的文档、demo、API 和测试场景做扎实,再去做下一个。
# 任务提交
## 每次提交需要包含什么?
- 本次处理的组件名称。
- 修改过的文档、demo、测试或源码文件。
- 本地验证方式和结果。
- 仍需确认的问题。
## 推荐分支命名
```text
task/button-docs
task/empty-demo
task/tag-tests
```
## 推荐提交信息
```text
docs(button): 补充按钮组件 API 表格
demo(empty): 新增自定义图片示例
test(tag): 增加可关闭标签测试场景
```
## 提交前检查
```bash
pnpm lint
pnpm typecheck
pnpm test
```
如果只改了文档或 demo,也需要启动文档站点确认页面展示正常:
```bash
pnpm dev
```
## PR 描述模板
```md
## 本次完成
-
## 修改文件
-
## 验证结果
- [ ] pnpm lint
- [ ] pnpm typecheck
- [ ] pnpm test
- [ ] pnpm dev 手动查看
## 遗留问题
-
```
---
layout: home
hero:
name: "ZUI Demo"
text: "Vue 3 Component Library Scaffold"
tagline: 从这里开始补充组件、文档、示例和测试
actions:
- theme: brand
text: 快速上手
link: /docs/guide/getting-started
- theme: alt
text: 组件总览
link: /components/
features:
- title: 组件库骨架
details: 保留源码、文档、示例、测试和构建目录。
- title: 文档站点
details: 使用 VitePress 管理组件文档和示例。
- title: 本地调试
details: 使用 Playground 快速验证组件行为。
---
支持 Markdown
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册