Skip to content

Commit 5740591

Browse files
authored
feat(collapse): 搭建collapse基本Dom结构 (DevCloudFE#803)
1 parent e223799 commit 5740591

File tree

8 files changed

+282
-0
lines changed

8 files changed

+282
-0
lines changed
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { mount } from '@vue/test-utils';
2+
import { ref, reactive } from 'vue';
3+
import { useNamespace } from '../../shared/hooks/use-namespace';
4+
import { Collapse, CollapseItem } from '../index';
5+
6+
const ns = useNamespace('collapse', true);
7+
8+
const baseClass = ns.b();
9+
const collapseItemClass = ns.e('item');
10+
11+
describe('d-collapse', () => {
12+
it('collapse render work', () => {
13+
const value = ref('');
14+
const items = ['Item1', 'Item2', 'Item3'];
15+
const options = reactive(items);
16+
const wrapper = mount({
17+
setup() {
18+
return () => (
19+
<Collapse v-model={value.value}>
20+
{options.map((item, index) => (
21+
<CollapseItem title={item} key={index}>
22+
{item}
23+
</CollapseItem>
24+
))}
25+
</Collapse>
26+
);
27+
},
28+
});
29+
30+
expect(wrapper.find(baseClass).exists()).toBeTruthy();
31+
const collapseItems = wrapper.findAll(collapseItemClass);
32+
expect(collapseItems.length).toBe(3);
33+
});
34+
});
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import type { App } from 'vue';
2+
import Collapse from './src/collapse';
3+
import CollapseItem from './src/collapse-item';
4+
5+
export * from './src/collapse-types';
6+
7+
export { Collapse, CollapseItem };
8+
9+
export default {
10+
title: 'Collapse 折叠面板',
11+
category: '数据展示',
12+
status: '10%',
13+
install(app: App): void {
14+
app.component(Collapse.name, Collapse);
15+
app.component(CollapseItem.name, CollapseItem);
16+
},
17+
};
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { defineComponent, computed, inject, Transition } from 'vue';
2+
import { collapseItemProps } from './collapse-types';
3+
import { useNamespace } from '../../shared/hooks/use-namespace';
4+
import { Icon } from '../../icon';
5+
import { SELECT_TOKEN } from './const';
6+
7+
export default defineComponent({
8+
name: 'DCollapseItem',
9+
props: collapseItemProps,
10+
setup(props, ctx) {
11+
const ns = useNamespace('collapse');
12+
const collapse = inject(SELECT_TOKEN, null);
13+
const isOpen = computed(() => {
14+
if (Array.isArray(collapse?.modelValue)) {
15+
return Boolean(collapse?.modelValue.length) && collapse?.modelValue.includes(props.name);
16+
} else {
17+
return Boolean(collapse?.modelValue) && collapse?.modelValue === props.name;
18+
}
19+
});
20+
return () => {
21+
return (
22+
<div class={ns.e('item')}>
23+
<div class={[ns.e('item-title'), ns.m('overflow-ellipsis'), isOpen.value && ns.m('open')]}>
24+
{props.title}
25+
<span class={ns.e('open-icon')}>
26+
<Icon name="select-arrow" size="16px" />
27+
</span>
28+
</div>
29+
<Transition name="fade">
30+
<div v-show={isOpen.value} class={ns.e('item-content')}>
31+
{ctx.slots.default?.()}
32+
</div>
33+
</Transition>
34+
</div>
35+
);
36+
};
37+
},
38+
});
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { ExtractPropTypes, PropType } from 'vue';
2+
export type ModelValue = number | string | Array<number | string>;
3+
export const collapseProps = {
4+
modelValue: {
5+
type: [String, Number, Array] as PropType<ModelValue>,
6+
default: '',
7+
},
8+
accordion: {
9+
type: Boolean,
10+
default: false,
11+
},
12+
} as const;
13+
14+
export type CollapseProps = ExtractPropTypes<typeof collapseProps>;
15+
16+
export const collapseItemProps = {
17+
name: {
18+
type: [String, Number] as PropType<string | number>,
19+
default: '',
20+
},
21+
title: {
22+
type: String,
23+
default: '',
24+
},
25+
} as const;
26+
27+
export type CollapseItemProps = ExtractPropTypes<typeof collapseItemProps>;
28+
29+
export type CollapseContext = CollapseProps;
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
@import '../../styles-var/devui-var';
2+
3+
.#{$devui-prefix}-collapse {
4+
font-size: $devui-font-size;
5+
background: $devui-base-bg;
6+
width: 100%;
7+
overflow-y: auto;
8+
}
9+
10+
:host {
11+
display: block;
12+
}
13+
14+
.#{$devui-prefix}-collapse__item {
15+
.#{$devui-prefix}-collapse--overflow-ellipsis {
16+
overflow: hidden;
17+
white-space: nowrap;
18+
text-overflow: ellipsis;
19+
}
20+
}
21+
.#{$devui-prefix}-collapse__item-title {
22+
display: block;
23+
height: 40px;
24+
width: 100%;
25+
padding: 0 28px 0 8px;
26+
font-weight: 400;
27+
line-height: 40px;
28+
color: $devui-text-weak;
29+
background: transparent;
30+
cursor: pointer;
31+
32+
&.#{$devui-prefix}-collapse--disabled {
33+
color: $devui-disabled-text;
34+
cursor: not-allowed;
35+
}
36+
37+
&:not(.#{$devui-prefix}-collapse--disabled) {
38+
&:hover {
39+
background: $devui-list-item-hover-bg;
40+
color: $devui-list-item-hover-text;
41+
}
42+
43+
&.#{$devui-prefix}-collapse--router-active,
44+
&.#{$devui-prefix}-collapse--active:not(.#{$devui-prefix}-collapse--open) {
45+
color: $devui-brand-active;
46+
font-weight: bold;
47+
}
48+
}
49+
}
50+
51+
/* 展开图标相关 */
52+
.#{$devui-prefix}-collapse__item > .#{$devui-prefix}-collapse__item-title {
53+
position: relative;
54+
55+
& > .#{$devui-prefix}-collapse__open-icon {
56+
display: inline-block;
57+
text-indent: 0;
58+
pointer-events: none; /* 让鼠标穿透 */
59+
position: absolute;
60+
right: 6px;
61+
top: 12px;
62+
width: 16px;
63+
height: 16px;
64+
line-height: 16px;
65+
transition: transform ease-out 0.3s;
66+
}
67+
68+
&.#{$devui-prefix}-collapse--open > .#{$devui-prefix}-collapse__open-icon {
69+
transform: rotate(180deg);
70+
transform-origin: center;
71+
}
72+
}
73+
74+
/* 展开内容相关 */
75+
.#{$devui-prefix}-collapse__item-content {
76+
padding: 0 28px 20px 8px;
77+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { defineComponent, provide, reactive, toRefs } from 'vue';
2+
import { SELECT_TOKEN } from './const';
3+
import { collapseProps, CollapseContext } from './collapse-types';
4+
import { useNamespace } from '../../shared/hooks/use-namespace';
5+
import './collapse.scss';
6+
7+
export default defineComponent({
8+
name: 'DCollapse',
9+
props: collapseProps,
10+
emits: ['change', 'update:modelValue'],
11+
setup(props, ctx) {
12+
const ns = useNamespace('collapse');
13+
const scrollbarNs = useNamespace('scrollbar');
14+
provide(
15+
SELECT_TOKEN,
16+
reactive({
17+
...toRefs(props),
18+
}) as CollapseContext
19+
);
20+
21+
return () => {
22+
return <div class={[ns.b(), scrollbarNs.b()]}>{ctx.slots.default?.()}</div>;
23+
};
24+
},
25+
});
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import { InjectionKey } from 'vue';
2+
import { CollapseContext } from './collapse-types';
3+
4+
export const SELECT_TOKEN: InjectionKey<CollapseContext> = Symbol('dCollapse');
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# Collapse 折叠面板
2+
3+
通过折叠面板收纳内容区域
4+
5+
#### 何时使用
6+
7+
需要收纳内容区域的时候使用。
8+
9+
### 基本用法
10+
11+
可同时展开多个面板,面板之前不影响
12+
13+
:::demo
14+
15+
```vue
16+
<template>
17+
<div class="collapse-demo-1">
18+
<d-collapse v-model="collapseValue">
19+
<d-collapse-item v-for="(item, index) in options" :key="index" :title="item.title">
20+
<div>{{ item.content }}</div>
21+
</d-collapse-item>
22+
</d-collapse>
23+
</div>
24+
</template>
25+
<script>
26+
import { defineComponent, reactive, ref } from 'vue';
27+
28+
export default defineComponent({
29+
setup() {
30+
const collapseValue = ref('');
31+
const list = new Array(6).fill(0).map((item, i) => {
32+
return {
33+
title: `item ${i + 1}`,
34+
content: '这是一组测试数据',
35+
};
36+
});
37+
const options = reactive(list);
38+
return {
39+
collapseValue,
40+
options,
41+
};
42+
},
43+
});
44+
</script>
45+
<style>
46+
.collapse-demo-1 {
47+
margin-bottom: 20px;
48+
}
49+
</style>
50+
```
51+
52+
:::
53+
54+
### Collapse 参数
55+
56+
| 参数名 | 类型 | 默认 | 说明 | 跳转 Demo |
57+
| :------ | :---------------- | :--- | :----- | :-------------------- |
58+
| v-model | `string \| array` | '' | 绑定值 | [基本用法](#基本用法) |

0 commit comments

Comments
 (0)