/
NSectionBlock.vue
91 lines (83 loc) · 2.06 KB
/
NSectionBlock.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
<script setup lang="ts">
import { useVModel } from '@vueuse/core'
const props = withDefaults(
defineProps<{
icon?: string
text: string
description?: string
containerClass?: string
headerClass?: string
collapse?: boolean
open?: boolean
padding?: boolean | string
}>(), {
containerClass: '',
open: true,
padding: true,
collapse: true,
},
)
const open = useVModel(props, 'open', undefined, { passive: true })
function onToggle(e: any) {
open.value = e.target.open
}
</script>
<template>
<details :open="open" @toggle="onToggle">
<summary class="cursor-pointer select-none hover:bg-active p4" :class="collapse ? '' : 'pointer-events-none'">
<NIconTitle :icon="icon" :text="text" text-xl transition :class="[open ? 'op100' : 'op60', headerClass]">
<div>
<div text-base>
<slot name="text">
{{ text }}
</slot>
</div>
<div v-if="description || $slots.description" text-sm op50>
<slot name="description">
{{ description }}
</slot>
</div>
</div>
<div class="flex-auto" />
<slot name="actions" />
<NIcon
v-if="collapse"
icon="carbon-chevron-down"
class="chevron"
cursor-pointer place-self-start text-base op75 transition duration-500
/>
</NIconTitle>
</summary>
<div
v-lazy-show="open"
class="flex flex-col flex-gap2 pb6 pt2"
:class="typeof padding === 'string' ? padding : padding ? 'px4' : ''"
>
<slot name="details" />
<div :class="containerClass" class="mt1">
<slot />
</div>
<slot name="footer" />
</div>
</details>
<div class="x-divider" />
</template>
<style scoped>
details {
--at-apply: border-none;
}
summary {
--at-apply: border-none;
list-style: none;
}
details[open] summary {
--at-apply: border-none;
}
details summary::-webkit-details-marker {
display:none;
}
details[open] .chevron {
transform: rotate(180deg);
opacity: 0.75;
}
</style>