/
collapse-item.vue
104 lines (94 loc) 路 2.54 KB
/
collapse-item.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
<template>
<div
:class="[
ns.b('item'),
ns.is('active', isActive),
ns.is('disabled', disabled),
]"
>
<div
role="tab"
:aria-expanded="isActive"
:aria-controls="ns.b(`content-${id}`)"
:aria-describedby="ns.b(`content-${id}`)"
>
<div
:id="ns.b(`head-${id}`)"
:class="[
ns.be('item', 'header'),
ns.is('active', isActive),
{ focusing: focusing && !disabled },
]"
role="button"
:tabindex="disabled ? -1 : 0"
@click="handleHeaderClick"
@keypress.space.enter.stop.prevent="handleEnterClick"
@focus="handleFocus"
@blur="focusing = false"
>
<slot name="title">{{ title }}</slot>
<el-icon :class="[ns.be('item', 'arrow'), ns.is('active', isActive)]">
<arrow-right />
</el-icon>
</div>
</div>
<el-collapse-transition>
<div
v-show="isActive"
:id="ns.b(`content-${id}`)"
:class="ns.be('item', 'wrap')"
role="tabpanel"
:aria-hidden="!isActive"
:aria-labelledby="ns.b(`head-${id}`)"
>
<div :class="ns.be('item', 'content')">
<slot />
</div>
</div>
</el-collapse-transition>
</div>
</template>
<script lang="ts" setup>
import { computed, inject, ref } from 'vue'
import { generateId } from '@element-plus/utils'
import ElCollapseTransition from '@element-plus/components/collapse-transition'
import ElIcon from '@element-plus/components/icon'
import { ArrowRight } from '@element-plus/icons-vue'
import { useNamespace } from '@element-plus/hooks'
import { collapseContextKey } from '@element-plus/tokens'
import { collapseItemProps } from './collapse-item'
defineOptions({
name: 'ElCollapseItem',
})
const props = defineProps(collapseItemProps)
const collapse = inject(collapseContextKey)
const ns = useNamespace('collapse')
const focusing = ref(false)
const isClick = ref(false)
const id = ref(generateId())
const isActive = computed(() =>
collapse?.activeNames.value.includes(props.name)
)
const handleFocus = () => {
setTimeout(() => {
if (!isClick.value) {
focusing.value = true
} else {
isClick.value = false
}
}, 50)
}
const handleHeaderClick = () => {
if (props.disabled) return
collapse?.handleItemClick(props.name)
focusing.value = false
isClick.value = true
}
const handleEnterClick = () => {
collapse?.handleItemClick(props.name)
}
defineExpose({
/** @description current collapse-item whether active */
isActive,
})
</script>