diff --git a/assets/js/components/BottomTabs/MoreItem.vue b/assets/js/components/BottomTabs/MoreItem.vue index 8d05241b9..87a6b6d1a 100644 --- a/assets/js/components/BottomTabs/MoreItem.vue +++ b/assets/js/components/BottomTabs/MoreItem.vue @@ -98,10 +98,22 @@ export default defineComponent({ return "bg-darker-green"; }, }, + mounted() { + document.addEventListener("click", this.closeOnClickOutside, true); + }, + unmounted() { + document.removeEventListener("click", this.closeOnClickOutside, true); + }, methods: { toggleMenu() { this.open = !this.open; }, + // the tab item wraps both toggle and menu, clicks inside are handled by them + closeOnClickOutside(e: MouseEvent) { + if (this.open && !this.$el.contains(e.target as Node)) { + this.open = false; + } + }, }, }); diff --git a/assets/js/components/BottomTabs/MoreMenu.vue b/assets/js/components/BottomTabs/MoreMenu.vue index 2eae0f827..2ed8516d0 100644 --- a/assets/js/components/BottomTabs/MoreMenu.vue +++ b/assets/js/components/BottomTabs/MoreMenu.vue @@ -115,10 +115,7 @@ export default defineComponent({ }, emits: ["close"], data() { - return { - isApp: isApp(), - onClickOutside: undefined as ((e: MouseEvent) => void) | undefined, - }; + return { isApp: isApp() }; }, computed: { providers() { @@ -168,19 +165,6 @@ export default defineComponent({ return Object.keys(this.vehicles).length > 0; }, }, - mounted() { - this.onClickOutside = (e: MouseEvent) => { - if (this.open && !this.$el.contains(e.target as Node)) { - this.$emit("close"); - } - }; - document.addEventListener("click", this.onClickOutside, true); - }, - unmounted() { - if (this.onClickOutside) { - document.removeEventListener("click", this.onClickOutside, true); - } - }, methods: { handleAuthRequired() { this.$router.push({ path: "/config" }); diff --git a/tests/navigation.spec.ts b/tests/navigation.spec.ts index bf73f34d2..113d69882 100644 --- a/tests/navigation.spec.ts +++ b/tests/navigation.spec.ts @@ -30,9 +30,16 @@ test.describe("bottom navigation", async () => { await expect(tabMore).toBeVisible(); await expect(tabBattery).toHaveCount(0); + // more menu opens and closes on the same tab + const configLink = tabMore.getByRole("link", { name: "Configuration" }); + await tabMore.click(); + await expect(configLink).toBeVisible(); + await tabMore.click(); + await expect(configLink).not.toBeVisible(); + // navigate to config via More menu await tabMore.click(); - await tabMore.getByRole("link", { name: "Configuration" }).click(); + await configLink.click(); await expect(page.getByRole("heading", { name: "Configuration" })).toBeVisible(); // create battery meter