1<template>
2 <!-- px-4 lives once here so the header and content share a single horizontal
3 padding instead of each declaring their own. -->
4 <div class="px-4">
5 <slot name="header" v-bind="{ opened, hide, open, close, toggle }">
6 <div
7 v-if="!hide"
8 class="section-header sticky top-0 z-10 flex cursor-pointer select-none items-center gap-1 bg-surface-base py-3.5"
9 :class="headerClass"
10 @click="collapsible && toggle()"
11 >
12 <!-- Figma: text/base/medium, ink-gray-8 -->
13 <Tooltip v-if="tooltip" :text="__(tooltip)">
14 <span
15 class="text-base font-medium text-ink-gray-8"
16 :class="labelClass"
17 >
18 {{ __(label) || "Untitled" }}
19 </span>
20 </Tooltip>
21 <span
22 v-else
23 class="text-base font-medium text-ink-gray-8"
24 :class="labelClass"
25 >
26 {{ __(label) || "Untitled" }}
27 </span>
28 <LucideChevronRight
29 v-if="collapsible"
30 class="size-3.5 text-ink-gray-5 transition-transform"
31 :class="{ 'rotate-90': opened }"
32 />
33 <slot name="actions"></slot>
34 </div>
35 </slot>
36 <transition
37 enter-active-class="transition-all duration-300 ease-in"
38 leave-active-class="transition-all duration-300 ease-[cubic-bezier(0,1,0.5,1)]"
39 enter-to-class="max-h-[2000px] overflow-hidden"
40 leave-from-class="max-h-[2000px] overflow-hidden"
41 enter-from-class="max-h-0 opacity-0"
42 leave-to-class="max-h-0 opacity-0"
43 >
44 <div class="columns" v-bind="$attrs" v-show="opened">
45 <slot v-bind="{ opened, open, close, toggle }" />
46 </div>
47 </transition>
48 </div>
49</template>
50<script setup>
51import { __ } from "@/translation";
52import { Tooltip } from "frappe-ui";
53import { ref, watch } from "vue";
54import LucideChevronRight from "~icons/lucide/chevron-right";
55
56const props = defineProps({
57 label: {
58 type: String,
59 default: "",
60 },
61 tooltip: {
62 type: String,
63 default: "",
64 },
65 hideLabel: {
66 type: Boolean,
67 default: false,
68 },
69 opened: {
70 type: Boolean,
71 default: true,
72 },
73 collapsible: {
74 type: Boolean,
75 default: true,
76 },
77 labelClass: {
78 type: [String, Object, Array],
79 default: "",
80 },
81 headerClass: {
82 type: [String, Object, Array],
83 default: "",
84 },
85});
86
87const emit = defineEmits(["update:opened"]);
88
89const hide = ref(props.hideLabel);
90const opened = ref(props.opened);
91
92watch(
93 () => props.opened,
94 (val) => {
95 opened.value = val;
96 }
97);
98
99function setOpened(value) {
100 opened.value = value;
101 emit("update:opened", value);
102}
103
104function toggle() {
105 setOpened(!opened.value);
106}
107
108function open() {
109 setOpened(true);
110}
111
112function close() {
113 setOpened(false);
114}
115</script>
116<script>
117export default {
118 inheritAttrs: false,
119};
120</script>
121