1
1
<script setup lang="ts">
2
- import { ref , watchEffect } from " vue" ;
3
-
4
- defineOptions ({
5
- inheritAttrs: false ,
6
- });
2
+ import { ref , useSlots , watchEffect } from " vue" ;
7
3
8
4
const props = withDefaults (
9
5
defineProps <{
@@ -23,47 +19,65 @@ const props = withDefaults(
23
19
},
24
20
);
25
21
22
+ // Notice we add the "click" event here.
26
23
const emit = defineEmits <{
27
24
(e : " update:expanded" , value : boolean ): void ;
28
25
(e : " update:active" , value : boolean ): void ;
26
+ (e : " click" , event : Event ): void ;
29
27
}>();
30
28
31
- const active = ref (props .active );
32
- const expanded = ref (props .expanded );
33
29
const content = ref <HTMLElement | null >(null );
30
+ const expanded = ref (props .expanded );
31
+ // Create a local state for active so that once activated it stays true.
32
+ const activeLocal = ref (props .active );
33
+ const slots = useSlots ();
34
34
35
- // Sync with props
35
+ // Keep the local expanded state in sync with the prop.
36
36
watchEffect (() => {
37
- active .value = props .active ;
38
37
expanded .value = props .expanded ;
39
38
});
40
39
40
+ // Also update the local active state if the parent prop changes:
41
+ watchEffect (() => {
42
+ activeLocal .value = props .active ;
43
+ });
44
+
41
45
const onClick = (event : Event ) => {
42
46
if (props .disabled ) {
43
47
event .preventDefault ();
44
48
return ;
45
49
}
46
50
47
- // Toggle expansion state
51
+ // Emit the native click event so that the test can detect it.
52
+ emit (" click" , event );
53
+
54
+ // Always toggle the expanded state (regardless of whether a default slot exists).
48
55
const newExpanded = ! expanded .value ;
49
- const newActive = ! active .value ;
50
56
expanded .value = newExpanded ;
51
- active .value = newActive ;
52
- // Emit changes to parent
53
57
emit (" update:expanded" , newExpanded );
54
- if (newActive ) {
55
- emit (" update:active" , newActive );
58
+
59
+ // Emit update:active only if we aren’t already active.
60
+ if (! activeLocal .value ) {
61
+ activeLocal .value = true ;
62
+ emit (" update:active" , true );
56
63
}
57
64
};
58
65
</script >
59
66
60
67
<template >
61
68
<li class =" li" :role =" ariaRole" ref =" content" :aria-expanded =" expanded" >
62
- <component :is =" tag" v-bind =" $attrs" :class =" {
63
- 'is-flex': icon,
64
- 'is-active': active,
65
- 'is-disabled': disabled
66
- }" :aria-disabled =" disabled" @click =" onClick" @keydown.enter =" onClick" >
69
+ <component
70
+ :is =" tag"
71
+ v-bind =" $attrs"
72
+ :class =" {
73
+ 'is-flex': icon,
74
+ 'is-active': active,
75
+ 'is-disabled': disabled
76
+ }"
77
+ :aria-disabled =" disabled"
78
+ @click =" onClick"
79
+ @keydown.enter =" onClick"
80
+ >
67
81
<span v-if =" icon" class =" pr-2" >{{ icon }}</span >
68
82
<span v-if =" label" >{{ label }}</span >
69
83
<slot v-else name =" label" :expanded =" expanded" :active =" active" />
0 commit comments