From 09c814f9f7dc529f1a1791d90609083218747216 Mon Sep 17 00:00:00 2001 From: tristan Date: Thu, 21 May 2026 16:56:38 +0200 Subject: [PATCH] =?UTF-8?q?fix=20:=20scroll-lock=20du=20MalioDrawer=20r?= =?UTF-8?q?=C3=A9ellement=20partag=C3=A9=20entre=20instances=20(drawers=20?= =?UTF-8?q?empil=C3=A9s)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/components/malio/drawer/Drawer.test.ts | 33 +++++++++++++++++++++- app/components/malio/drawer/Drawer.vue | 8 ++++-- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/app/components/malio/drawer/Drawer.test.ts b/app/components/malio/drawer/Drawer.test.ts index 2b952a9..b58d91c 100644 --- a/app/components/malio/drawer/Drawer.test.ts +++ b/app/components/malio/drawer/Drawer.test.ts @@ -1,5 +1,5 @@ import { afterEach, describe, expect, it } from 'vitest' -import { mount } from '@vue/test-utils' +import { enableAutoUnmount, mount } from '@vue/test-utils' import type { DefineComponent } from 'vue' import { Icon as IconifyIcon } from '@iconify/vue' import Drawer from './Drawer.vue' @@ -30,6 +30,8 @@ function mountComponent(props: DrawerProps = {}, slots?: Record) } describe('MalioDrawer', () => { + enableAutoUnmount(afterEach) + afterEach(() => { document.body.style.overflow = '' }) @@ -307,4 +309,33 @@ describe('MalioDrawer', () => { expect(document.activeElement).toBe(wrapper.find('[data-test="btn2"]').element) wrapper.unmount() }) + + it('does not release body scroll-lock when one stacked drawer closes while another is still open', async () => { + const wrapperA = mount(DrawerForTest, { + props: { modelValue: false }, + attachTo: document.body, + global: { stubs: { Teleport: true } }, + }) + const wrapperB = mount(DrawerForTest, { + props: { modelValue: false }, + attachTo: document.body, + global: { stubs: { Teleport: true } }, + }) + + // Open drawer A → scroll locked + await wrapperA.setProps({ modelValue: true }) + expect(document.body.style.overflow).toBe('hidden') + + // Open drawer B → still locked + await wrapperB.setProps({ modelValue: true }) + expect(document.body.style.overflow).toBe('hidden') + + // Close drawer B → A is still open, scroll must remain locked + await wrapperB.setProps({ modelValue: false }) + expect(document.body.style.overflow).toBe('hidden') + + // Close drawer A → both closed, scroll-lock released + await wrapperA.setProps({ modelValue: false }) + expect(document.body.style.overflow).toBe('') + }) }) diff --git a/app/components/malio/drawer/Drawer.vue b/app/components/malio/drawer/Drawer.vue index 101872f..fab2d87 100644 --- a/app/components/malio/drawer/Drawer.vue +++ b/app/components/malio/drawer/Drawer.vue @@ -95,9 +95,6 @@ import { twMerge } from 'tailwind-merge' defineOptions({ name: 'MalioDrawer', inheritAttrs: false }) -// Module-level counter shared across all drawer instances to support stacked drawers. -let openDrawerCount = 0 - const props = withDefaults( defineProps<{ id?: string @@ -257,6 +254,11 @@ function close() { } + +