Skip to content

Commit 815b94f

Browse files
fix(menu): properly handle submenu expansion (#28)
* fix(menu): properly handle submenu expansion Correcting menu. * fix(menu): properly handle submenu expansion Correcting menu testing and submenu expansion
1 parent 043942c commit 815b94f

File tree

1 file changed

+34
-20
lines changed

1 file changed

+34
-20
lines changed

src/components/compounds/Menu/MenuItem.vue

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
11
<script setup lang="ts">
2-
import { ref, watchEffect } from "vue";
3-
4-
defineOptions({
5-
inheritAttrs: false,
6-
});
2+
import { ref, useSlots, watchEffect } from "vue";
73
84
const props = withDefaults(
95
defineProps<{
@@ -23,47 +19,65 @@ const props = withDefaults(
2319
},
2420
);
2521
22+
// Notice we add the "click" event here.
2623
const emit = defineEmits<{
2724
(e: "update:expanded", value: boolean): void;
2825
(e: "update:active", value: boolean): void;
26+
(e: "click", event: Event): void;
2927
}>();
3028
31-
const active = ref(props.active);
32-
const expanded = ref(props.expanded);
3329
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();
3434
35-
// Sync with props
35+
// Keep the local expanded state in sync with the prop.
3636
watchEffect(() => {
37-
active.value = props.active;
3837
expanded.value = props.expanded;
3938
});
4039
40+
// Also update the local active state if the parent prop changes:
41+
watchEffect(() => {
42+
activeLocal.value = props.active;
43+
});
44+
4145
const onClick = (event: Event) => {
4246
if (props.disabled) {
4347
event.preventDefault();
4448
return;
4549
}
4650
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).
4855
const newExpanded = !expanded.value;
49-
const newActive = !active.value;
5056
expanded.value = newExpanded;
51-
active.value = newActive;
52-
// Emit changes to parent
5357
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);
5663
}
5764
};
5865
</script>
5966

6067
<template>
6168
<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+
>
6781
<span v-if="icon" class="pr-2">{{ icon }}</span>
6882
<span v-if="label">{{ label }}</span>
6983
<slot v-else name="label" :expanded="expanded" :active="active" />

0 commit comments

Comments
 (0)