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

Add component docs demos and tests

上级 962a1402
<template>
<div style="display: flex; flex-direction: column; gap: 8px;">
<ZStatusDot color="#722ed1" text="自定义紫色" />
<ZStatusDot color="#13c2c2" text="自定义青色" />
<ZStatusDot status="success" color="#000" text="覆盖语义色:黑色" />
</div>
</template>
# 状态点 StatusDot
TODO: 补充默认、处理中、成功、警告、失败和自定义颜色示例。
StatusDot 用一个圆点加文字表达对象当前的状态,常用于列表、详情、卡片标题等场景。
## 何时使用
- 列表/表格里需要展示运行中、已启用、异常等状态。
- 卡片标题边上需要一个轻量的状态标记。
- 不要把 StatusDot 用作可点击控件,它只是一个展示元素。
## 演示
下面的示例分别演示:
- `basic``success` 状态搭配文案。
- `custom-color``color` 属性可以覆盖默认的语义色,用于特殊业务场景。
- `status`:五种语义状态 `default / processing / success / warning / error`
<!-- DEMO -->
<demo vue="status-dot/demos/basic.vue" />
<demo vue="status-dot/demos/custom-color.vue" />
<demo vue="status-dot/demos/status.vue" />
<!-- DEMO -->
......@@ -14,7 +28,18 @@ TODO: 补充默认、处理中、成功、警告、失败和自定义颜色示
<!-- API -->
TODO: 对照 `src/status-dot/src/interface.ts` 补充 Props 和 Slots 表格。
### StatusDot Props
<!-- API -->
| 名称 | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| status | `'default' \| 'processing' \| 'success' \| 'warning' \| 'error'` | `'default'` | 语义状态,决定默认颜色与是否带呼吸动画(processing) |
| text | `string` | `undefined` | 状态描述文案,可被默认插槽覆盖 |
| color | `string` | `undefined` | 自定义圆点颜色,会覆盖 `status` 对应的默认色 |
### StatusDot Slots
| 名称 | 参数 | 说明 |
| --- | --- | --- |
| default | `()` | 状态描述区域,优先级高于 `text` 属性 |
<!-- API -->
<template>
<div style="display: flex; flex-direction: column; gap: 8px;">
<ZStatusDot status="default" text="default:默认" />
<ZStatusDot status="processing" text="processing:进行中" />
<ZStatusDot status="success" text="success:已启用" />
<ZStatusDot status="warning" text="warning:需关注" />
<ZStatusDot status="error" text="error:异常" />
</div>
</template>
import { mount } from '@vue/test-utils'
import { ZStatusDot } from '../index'
describe('statusDot', () => {
it('renders the text prop next to the dot', () => {
const wrapper = mount(ZStatusDot, {
props: { text: '运行中' },
})
expect(wrapper.text()).toContain('运行中')
expect(wrapper.findAll('span').length).toBeGreaterThanOrEqual(2)
})
it('prefers the default slot over the text prop', () => {
const wrapper = mount(ZStatusDot, {
props: { text: '默认' },
slots: { default: '<b class="custom">自定义</b>' },
})
expect(wrapper.find('.custom').exists()).toBe(true)
expect(wrapper.text()).not.toContain('默认')
})
it('uses the default status color when no color prop is provided', () => {
const wrapper = mount(ZStatusDot, {
props: { status: 'success' },
})
const dot = wrapper.findAll('span').at(1)!
const style = dot.attributes('style') ?? ''
expect(style).toContain('background-color: #2f9e44')
})
it('lets the color prop override the status color', () => {
const wrapper = mount(ZStatusDot, {
props: { status: 'success', color: 'rgb(255, 0, 0)' },
})
const dot = wrapper.findAll('span').at(1)!
const style = dot.attributes('style') ?? ''
expect(style).toContain('background-color: rgb(255, 0, 0)')
})
it('mounts every supported status variant', () => {
for (const status of ['default', 'processing', 'success', 'warning', 'error'] as const) {
const wrapper = mount(ZStatusDot, {
props: { status, text: status },
})
expect(wrapper.text()).toContain(status)
}
})
})
<script setup lang="ts">
import { ref } from 'vue'
const tags = ref(['Vue', 'TypeScript', 'JSS', '可关闭'])
function handleClose(index: number) {
tags.value.splice(index, 1)
}
</script>
<template>
<div style="display: flex; gap: 8px; flex-wrap: wrap;">
<ZTag
v-for="(tag, index) in tags"
:key="tag"
closable
@close="handleClose(index)"
>
{{ tag }}
</ZTag>
<span v-if="tags.length === 0" style="color: #86909c;">
标签都被关闭了
</span>
</div>
</template>
<template>
<div style="display: flex; gap: 8px; flex-wrap: wrap;">
<ZTag>默认</ZTag>
<ZTag color="#e8f3ff" text-color="#1677ff">
信息
</ZTag>
<ZTag color="#e8ffea" text-color="#2f9e44">
成功
</ZTag>
<ZTag color="#fff3e0" text-color="#d97706">
警告
</ZTag>
<ZTag color="#ffe8e8" text-color="#d92d20">
失败
</ZTag>
</div>
</template>
# 标签 Tag
TODO: 补充基础标签、自定义颜色、可关闭标签和插槽内容示例。
标签用于对内容做简短的语义化标记,例如分类、状态或筛选条件。
## 何时使用
- 列表项、卡片或表格里需要标记类别或状态。
- 用户选中的筛选项需要回显在表单上方,并支持单独关闭。
- 不需要点击进入下一级页面时使用 Tag;如果需要,请使用按钮或链接。
## 演示
下面的示例分别演示:
- `basic`:默认中性标签。
- `closable`:设置 `closable` 后显示关闭按钮,点击触发 `close` 事件。
- `color`:通过 `color``textColor` 组合语义色板。
<!-- DEMO -->
<demo vue="tag/demos/basic.vue" />
<demo vue="tag/demos/closable.vue" />
<demo vue="tag/demos/color.vue" />
<!-- DEMO -->
......@@ -14,7 +28,24 @@ TODO: 补充基础标签、自定义颜色、可关闭标签和插槽内容示
<!-- API -->
TODO: 对照 `src/tag/src/interface.ts` 补充 Props、Events 和 Slots 表格。
### Tag Props
<!-- API -->
| 名称 | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| color | `string` | `'#f2f3f5'` | 标签背景色,可使用十六进制或 rgb 字符串 |
| textColor | `string` | `'#1f2329'` | 标签文字颜色 |
| closable | `boolean` | `false` | 是否显示关闭按钮 |
### Tag Events
| 名称 | 参数 | 说明 |
| --- | --- | --- |
| close | `()` | 点击关闭按钮时触发,需由父组件决定是否真正移除 |
### Tag Slots
| 名称 | 参数 | 说明 |
| --- | --- | --- |
| default | `()` | 标签内容 |
<!-- API -->
import { mount } from '@vue/test-utils'
import { ZTag } from '../index'
describe('tag', () => {
it('renders slot content', () => {
const wrapper = mount(ZTag, {
slots: {
default: '已完成',
},
})
expect(wrapper.text()).toContain('已完成')
})
it('does not show the close button by default', () => {
const wrapper = mount(ZTag, {
slots: { default: '默认' },
})
expect(wrapper.find('button').exists()).toBe(false)
})
it('renders the close button when closable', () => {
const wrapper = mount(ZTag, {
props: { closable: true },
slots: { default: '可关闭' },
})
const closeBtn = wrapper.find('button')
expect(closeBtn.exists()).toBe(true)
expect(closeBtn.attributes('aria-label')).toBe('关闭')
})
it('emits close event when the close button is clicked', async () => {
const wrapper = mount(ZTag, {
props: { closable: true },
slots: { default: '可关闭' },
})
await wrapper.find('button').trigger('click')
expect(wrapper.emitted('close')).toHaveLength(1)
})
it('applies custom color and textColor as inline styles', () => {
const wrapper = mount(ZTag, {
props: { color: 'rgb(255, 0, 0)', textColor: 'rgb(255, 255, 255)' },
slots: { default: '' },
})
const style = wrapper.attributes('style') ?? ''
expect(style).toContain('background-color: rgb(255, 0, 0)')
expect(style).toContain('color: rgb(255, 255, 255)')
})
})
# 提示 Tip
TODO: 补充组件用途、提示类型、标题和默认插槽用法。
Tip 用于在表单、卡片、详情等区域里展示一段说明性文字,让用户更容易理解当前页面或操作。
## 何时使用
- 表单或操作区域需要补充使用说明。
- 详情页里需要提醒用户注意的字段、条款。
- 与 Alert 的区别:Tip 偏静态说明,Alert 偏动态反馈与可操作(关闭、跳转)。
## 演示
下面的示例分别演示:
- `basic`:带标题与内容的 `info` 类型提示。
- `slot``title` 与默认插槽都可以使用富文本,便于嵌入链接或图标。
- `types`:四种语义类型 `info / success / warning / error`
<!-- DEMO -->
<demo vue="tip/demos/basic.vue" />
<demo vue="tip/demos/slot.vue" />
<demo vue="tip/demos/types.vue" />
<!-- DEMO -->
......@@ -14,7 +28,19 @@ TODO: 补充组件用途、提示类型、标题和默认插槽用法。
<!-- API -->
TODO: 对照 `src/tip/src/interface.ts` 补充 Props 和 Slots 表格。
### Tip Props
<!-- API -->
| 名称 | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| type | `'info' \| 'success' \| 'warning' \| 'error'` | `'info'` | 语义类型 |
| title | `string` | `undefined` | 标题文案,可被 `title` 插槽覆盖;不填则不渲染标题区 |
| content | `string` | `undefined` | 正文文案,可被默认插槽覆盖 |
### Tip Slots
| 名称 | 参数 | 说明 |
| --- | --- | --- |
| title | `()` | 标题插槽 |
| default | `()` | 正文插槽,优先级高于 `content` 属性 |
<!-- API -->
<template>
<ZTip type="warning">
<template #title>
<strong>请留意</strong>
</template>
<span>
操作不可撤销,建议先 <a href="#" style="color: #1677ff;">导出备份</a>
</span>
</ZTip>
</template>
<template>
<div style="display: flex; flex-direction: column; gap: 12px;">
<ZTip type="info" title="info" content="一般性提示信息。" />
<ZTip type="success" title="success" content="操作成功类的提示。" />
<ZTip type="warning" title="warning" content="需要用户留意的警告。" />
<ZTip type="error" title="error" content="出现异常或失败时的提示。" />
</div>
</template>
import { mount } from '@vue/test-utils'
import { ZTip } from '../index'
describe('tip', () => {
it('renders content via prop', () => {
const wrapper = mount(ZTip, {
props: { content: '请先选择一个项目' },
})
expect(wrapper.text()).toContain('请先选择一个项目')
})
it('prefers the default slot over the content prop', () => {
const wrapper = mount(ZTip, {
props: { content: '默认内容' },
slots: { default: '<em class="custom">自定义内容</em>' },
})
expect(wrapper.find('.custom').exists()).toBe(true)
expect(wrapper.text()).not.toContain('默认内容')
})
it('renders the title prop above the content', () => {
const wrapper = mount(ZTip, {
props: { title: '注意', content: '操作不可撤销' },
})
expect(wrapper.text()).toContain('注意')
expect(wrapper.text()).toContain('操作不可撤销')
})
it('prefers the title slot over the title prop', () => {
const wrapper = mount(ZTip, {
props: { title: '默认标题', content: '内容' },
slots: { title: '<strong class="custom">自定义</strong>' },
})
expect(wrapper.find('.custom').exists()).toBe(true)
expect(wrapper.text()).not.toContain('默认标题')
})
it('omits the title block when neither title prop nor slot is provided', () => {
const wrapper = mount(ZTip, {
props: { content: '内容' },
})
expect(wrapper.find('strong').exists()).toBe(false)
expect(wrapper.text()).toBe('内容')
})
it('mounts every supported type variant', () => {
for (const type of ['info', 'success', 'warning', 'error'] as const) {
const wrapper = mount(ZTip, {
props: { type, content: type },
})
expect(wrapper.text()).toContain(type)
}
})
})
支持 Markdown
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册