Skip to content

Commit

Permalink
feat(comp:desc): add Descriptions component (#1470)
Browse files Browse the repository at this point in the history
* feat(comp:desc): add Descriptions component

* feat(comp:desc): style update
  • Loading branch information
danranVm committed Feb 27, 2023
1 parent 79a7acc commit a7faf13
Show file tree
Hide file tree
Showing 50 changed files with 819 additions and 15 deletions.
7 changes: 7 additions & 0 deletions packages/components/config/src/defaultConfig.ts
Expand Up @@ -93,6 +93,13 @@ export const defaultConfig: GlobalConfig = {
size: 'md',
suffix: 'calendar',
},
desc: {
col: 3,
colonless: false,
labelAlign: 'end',
layout: 'horizontal',
size: 'md',
},
divider: {
dashed: false,
labelPlacement: 'center',
Expand Down
4 changes: 4 additions & 0 deletions packages/components/config/src/seerConfig.ts
Expand Up @@ -18,6 +18,10 @@ export const seerConfig: DeepPartialGlobalConfig = {
button: {
size: 'sm',
},
desc: {
colonless: true,
labelAlign: 'start',
},
form: {
colonless: true,
labelAlign: 'start',
Expand Down
10 changes: 10 additions & 0 deletions packages/components/config/src/types.ts
Expand Up @@ -18,6 +18,7 @@ import type { CarouselDotPlacement, CarouselDotTrigger } from '@idux/components/
import type { CascaderData } from '@idux/components/cascader'
import type { CollapseSize } from '@idux/components/collapse'
import type { DatePickerType } from '@idux/components/date-picker'
import type { DescLabelAlign, DescLayout, DescSize } from '@idux/components/desc'
import type { FormLabelAlign, FormLayout, FormSize } from '@idux/components/form'
import type { ListSize } from '@idux/components/list'
import type { LoadingBarAnimation } from '@idux/components/loading-bar'
Expand Down Expand Up @@ -64,6 +65,7 @@ export interface GlobalConfig {
checkbox: CheckboxConfig
collapse: CollapseConfig
datePicker: DatePickerConfig
desc: DescConfig
divider: DividerConfig
drawer: DrawerConfig
dropdown: DropdownConfig
Expand Down Expand Up @@ -204,6 +206,14 @@ export interface DatePickerConfig {
overlayContainer?: OverlayContainerType
}

export interface DescConfig {
col: number | Record<BreakpointKey, number>
colonless: boolean
labelAlign: DescLabelAlign
layout: DescLayout
size: DescSize
}

export interface DividerConfig {
dashed: boolean
plain: boolean
Expand Down
1 change: 1 addition & 0 deletions packages/components/default.less
Expand Up @@ -25,6 +25,7 @@
@import './collapse/style/themes/default.less';
@import './comment/style/themes/default.less';
@import './date-picker/style/themes/default.less';
@import './desc/style/themes/default.less';
@import './divider/style/themes/default.less';
@import './drawer/style/themes/default.less';
@import './dropdown/style/themes/default.less';
Expand Down
@@ -0,0 +1,35 @@
// Vitest Snapshot v1

exports[`Desc > render work 1`] = `
"<div class=\\"ix-row ix-desc ix-desc-md\\">
<!---->
<div class=\\"ix-col ix-col-span-8 ix-desc-item\\">
<div class=\\"ix-desc-item-label ix-desc-item-label-colon\\"><label>A</label></div>
<div class=\\"ix-desc-content\\"><span>aaa</span></div>
</div>
<div class=\\"ix-col ix-col-span-8 ix-desc-item\\">
<div class=\\"ix-desc-item-label ix-desc-item-label-colon\\"><label>B</label></div>
<div class=\\"ix-desc-content\\"><span>bbb</span></div>
</div>
<div class=\\"ix-col ix-col-span-8 ix-desc-item\\">
<div class=\\"ix-desc-item-label ix-desc-item-label-colon\\"><label>C</label></div>
<div class=\\"ix-desc-content\\"><span>ccc</span></div>
</div>
<div class=\\"ix-col ix-col-span-8 ix-desc-item\\">
<div class=\\"ix-desc-item-label ix-desc-item-label-colon\\"><label>D</label></div>
<div class=\\"ix-desc-content\\"><span>ddd</span></div>
</div>
<div class=\\"ix-col ix-col-span-8 ix-desc-item\\">
<div class=\\"ix-desc-item-label ix-desc-item-label-colon\\"><label>E</label></div>
<div class=\\"ix-desc-content\\"><span>eee</span></div>
</div>
<div class=\\"ix-col ix-col-span-8 ix-desc-item\\">
<div class=\\"ix-desc-item-label ix-desc-item-label-colon\\"><label>F</label></div>
<div class=\\"ix-desc-content\\"><span>fff</span></div>
</div>
<div class=\\"ix-col ix-col-span-16 ix-desc-item\\">
<div class=\\"ix-desc-item-label ix-desc-item-label-start\\"><label style=\\"width: 120px;\\">G</label></div>
<div class=\\"ix-desc-content\\"><span>ggg</span></div>
</div>
</div>"
`;
117 changes: 117 additions & 0 deletions packages/components/desc/__tests__/descriptions.spec.ts
@@ -0,0 +1,117 @@
import { MountingOptions, mount } from '@vue/test-utils'
import { h } from 'vue'

import { renderWork } from '@tests'

import Desc from '../src/Desc'
import DescItem from '../src/DescItem'
import { DescProps } from '../src/types'

const defaultSlot = () => [
h(DescItem, { label: 'A' }, () => 'aaa'),
h(DescItem, { label: 'B' }, () => 'bbb'),
h(DescItem, { label: 'C' }, () => 'ccc'),
h(DescItem, { label: 'D' }, () => 'ddd'),
h(DescItem, { label: 'E' }, () => 'eee'),
h(DescItem, { label: 'F' }, () => 'fff'),
h(DescItem, { label: 'G', col: 2, colonless: true, labelAlign: 'start', labelWidth: '120px' }, () => 'ggg'),
]

describe('Desc', () => {
const DescMount = (options?: MountingOptions<Partial<DescProps>>) => {
const { slots, ...reset } = options || {}
return mount(Desc, { ...(reset as MountingOptions<DescProps>), slots: { default: defaultSlot, ...slots } })
}

renderWork<DescProps>(Desc, {
props: {},
slots: { default: defaultSlot },
})

test('col work', async () => {
const wrapper = DescMount({ props: { col: 3 } })

const allItems = wrapper.findAllComponents(DescItem)

expect(allItems[0].classes()).toContain('ix-col-span-8')
expect(allItems[6].classes()).toContain('ix-col-span-16')

await wrapper.setProps({ col: 4 })

expect(allItems[0].classes()).toContain('ix-col-span-6')
expect(allItems[6].classes()).toContain('ix-col-span-12')
})

test('colonless work', async () => {
const wrapper = DescMount({ props: { colonless: true } })

const allItems = wrapper.findAllComponents(DescItem)

expect(allItems[0].find('.ix-desc-item-label').classes()).not.toContain('ix-desc-item-label-colon')
expect(allItems[6].find('.ix-desc-item-label').classes()).not.toContain('ix-desc-item-label-colon')

await wrapper.setProps({ colonless: false })

expect(allItems[0].find('.ix-desc-item-label').classes()).toContain('ix-desc-item-label-colon')
expect(allItems[6].find('.ix-desc-item-label').classes()).not.toContain('ix-desc-item-label-colon')
})

test('header work', async () => {
const wrapper = DescMount({ props: { header: '哈哈哈' } })

expect(wrapper.find('.ix-header-title').text()).toBe('哈哈哈')

await wrapper.setProps({ header: { title: '嘿嘿嘿', suffix: 'setting' } })

expect(wrapper.find('.ix-header-title').text()).toBe('嘿嘿嘿')
expect(wrapper.find('.ix-header-suffix').find('.ix-icon-setting').exists()).toBe(true)
})

test('labelAlign work', async () => {
const wrapper = DescMount({ props: { labelAlign: 'start' } })

const allItems = wrapper.findAllComponents(DescItem)

expect(allItems[0].find('.ix-desc-item-label').classes()).toContain('ix-desc-item-label-start')
expect(allItems[6].find('.ix-desc-item-label').classes()).toContain('ix-desc-item-label-start')

await wrapper.setProps({ labelAlign: 'end' })

expect(allItems[0].find('.ix-desc-item-label').classes()).not.toContain('ix-desc-item-label-start')
expect(allItems[6].find('.ix-desc-item-label').classes()).toContain('ix-desc-item-label-start')
})

test('labelWidth work', async () => {
const wrapper = DescMount({ props: { labelWidth: '80px' } })

const allItems = wrapper.findAllComponents(DescItem)

expect(allItems[0].find('label').element.style.width).toBe('80px')
expect(allItems[6].find('label').element.style.width).toBe('120px')

await wrapper.setProps({ labelWidth: 99 })

expect(allItems[0].find('label').element.style.width).toBe('99px')
expect(allItems[6].find('label').element.style.width).toBe('120px')
})

test('layout work', async () => {
const wrapper = DescMount({ props: { layout: 'vertical' } })

expect(wrapper.classes()).toContain('ix-desc-vertical')

await wrapper.setProps({ layout: 'horizontal' })

expect(wrapper.classes()).not.toContain('ix-desc-vertical')
})

test('size work', async () => {
const wrapper = DescMount({ props: { size: 'sm' } })

expect(wrapper.classes()).toContain('ix-desc-sm')

await wrapper.setProps({ size: 'lg' })

expect(wrapper.classes()).toContain('ix-desc-lg')
})
})
14 changes: 14 additions & 0 deletions packages/components/desc/demo/Basic.md
@@ -0,0 +1,14 @@
---
order: 0
title:
zh: 多列数据
en: Multiple columns
---

## zh

最简单的用法。

## en

The simplest usage.
10 changes: 10 additions & 0 deletions packages/components/desc/demo/Basic.vue
@@ -0,0 +1,10 @@
<template>
<IxDesc header="多列数据" labelWidth="56px">
<IxDescItem label="策略名称">保障网络会议</IxDescItem>
<IxDescItem label="状态">禁用</IxDescItem>
<IxDescItem label="操作人">saas</IxDescItem>
<IxDescItem label="描述信息">优先保证网络会议带宽的使用</IxDescItem>
<IxDescItem label="优先级">高</IxDescItem>
<IxDescItem label="更新时间">2022-02-20 16:29</IxDescItem>
</IxDesc>
</template>
14 changes: 14 additions & 0 deletions packages/components/desc/demo/Col.md
@@ -0,0 +1,14 @@
---
order: 3
title:
zh: 响应式列
en: Reactive column
---

## zh

`col` 支持响应式的对象

## en

the `col` supports reactive objects.
10 changes: 10 additions & 0 deletions packages/components/desc/demo/Col.vue
@@ -0,0 +1,10 @@
<template>
<IxDesc header="响应式列" :col="{ xs: 1, sm: 2, md: 3, lg: 4, xl: 6 }">
<IxDescItem label="策略名称">保障网络会议</IxDescItem>
<IxDescItem label="状态">禁用</IxDescItem>
<IxDescItem label="操作人">saas</IxDescItem>
<IxDescItem label="描述信息">优先保证网络会议带宽的使用</IxDescItem>
<IxDescItem label="优先级">高</IxDescItem>
<IxDescItem label="更新时间">2022-02-20 16:29</IxDescItem>
</IxDesc>
</template>
14 changes: 14 additions & 0 deletions packages/components/desc/demo/Header.md
@@ -0,0 +1,14 @@
---
order: 4
title:
zh: 自定义头部
en: Custom header
---

## zh

通过配置 `header` 来自定义头部

## en

Customize the header by setting `header`.
20 changes: 20 additions & 0 deletions packages/components/desc/demo/Header.vue
@@ -0,0 +1,20 @@
<template>
<IxDesc :header="header">
<IxDescItem label="策略名称">保障网络会议</IxDescItem>
<IxDescItem label="状态">禁用</IxDescItem>
<IxDescItem label="操作人">saas</IxDescItem>
<IxDescItem label="描述信息">优先保证网络会议带宽的使用</IxDescItem>
<IxDescItem label="优先级">高</IxDescItem>
<IxDescItem label="更新时间">2022-02-20 16:29</IxDescItem>
</IxDesc>
</template>

<script setup lang="ts">
import { HeaderProps } from '@idux/components/header'
const header: HeaderProps = {
title: '自定义头部',
suffix: 'setting',
onSuffixClick: () => console.log('onSuffixClick'),
}
</script>
14 changes: 14 additions & 0 deletions packages/components/desc/demo/Layout.md
@@ -0,0 +1,14 @@
---
order: 8
title:
zh: 垂直布局
en: Vertical
---

## zh

垂直的排列。

## en

Vertical display.
10 changes: 10 additions & 0 deletions packages/components/desc/demo/Layout.vue
@@ -0,0 +1,10 @@
<template>
<IxDesc header="垂直布局" layout="vertical">
<IxDescItem label="策略名称">保障网络会议</IxDescItem>
<IxDescItem label="状态">禁用</IxDescItem>
<IxDescItem label="操作人">saas</IxDescItem>
<IxDescItem label="描述信息">优先保证网络会议带宽的使用</IxDescItem>
<IxDescItem label="优先级">高</IxDescItem>
<IxDescItem label="更新时间">2022-02-20 16:29</IxDescItem>
</IxDesc>
</template>
14 changes: 14 additions & 0 deletions packages/components/desc/demo/LongText.md
@@ -0,0 +1,14 @@
---
order: 2
title:
zh: 超长文本
en: Long text
---

## zh

对于较长的文本,默认会进行换行,你也可以设置 `IxDescItem``col` 来单独处理。

## en

For longer text, it will be wrapped by default, you can also set `col` of `IxDescItem` to handle it separately.
11 changes: 11 additions & 0 deletions packages/components/desc/demo/LongText.vue
@@ -0,0 +1,11 @@
<template>
<IxDesc header="超长本文" labelWidth="56px">
<IxDescItem label="策略名称"> 保障网络会议保障网络会议保障网络会议保障网络会议保障网络会议保障网络会议 </IxDescItem>
<IxDescItem label="状态">禁用</IxDescItem>
<IxDescItem label="操作人">saas</IxDescItem>
<IxDescItem label="描述信息" col="2">
优先保证网络会议带宽的使用优先保证网络会议带宽的使用优先保证网络会议带宽的使用
</IxDescItem>
<IxDescItem label="更新时间">2022-02-20 16:29</IxDescItem>
</IxDesc>
</template>
14 changes: 14 additions & 0 deletions packages/components/desc/demo/Single.md
@@ -0,0 +1,14 @@
---
order: 1
title:
zh: 单列数据
en: Single column
---

## zh

每行只渲染一列数据

## en

Only one column of data is rendered per row.
10 changes: 10 additions & 0 deletions packages/components/desc/demo/Single.vue
@@ -0,0 +1,10 @@
<template>
<IxDesc header="单列数据" col="1" labelWidth="56px">
<IxDescItem label="策略名称">保障网络会议</IxDescItem>
<IxDescItem label="状态">禁用</IxDescItem>
<IxDescItem label="操作人">saas</IxDescItem>
<IxDescItem label="描述信息">优先保证网络会议带宽的使用</IxDescItem>
<IxDescItem label="优先级">高</IxDescItem>
<IxDescItem label="更新时间">2022-02-20 16:29</IxDescItem>
</IxDesc>
</template>
14 changes: 14 additions & 0 deletions packages/components/desc/demo/Size.md
@@ -0,0 +1,14 @@
---
order: 10
title:
zh: 尺寸
en: Size
---

## zh

支持 3 种尺寸以使用不同的场景

## en

Support 3 sizes to use different scenes.

0 comments on commit a7faf13

Please sign in to comment.