From a1f9212712de83ae6117c7a6f0ad54c9d4fa91fc Mon Sep 17 00:00:00 2001 From: Stefan Dietz Date: Wed, 22 Jan 2025 16:32:05 +0100 Subject: [PATCH] Fix Drawer controlled mode: Allow to open with an initial _open property Refs: #7165 --- .../src/components/drawer/drawer.e2e.ts | 28 +++++++++++++++++-- .../src/components/drawer/shadow.tsx | 27 ++++++++++++++---- 2 files changed, 48 insertions(+), 7 deletions(-) diff --git a/packages/components/src/components/drawer/drawer.e2e.ts b/packages/components/src/components/drawer/drawer.e2e.ts index 44d7bb63f7..fa6499db3f 100644 --- a/packages/components/src/components/drawer/drawer.e2e.ts +++ b/packages/components/src/components/drawer/drawer.e2e.ts @@ -5,11 +5,10 @@ import { KolEvent } from '../../utils/events'; test.describe('kol-drawer', () => { test.describe('Callbacks', () => { test(`should call 'onClose' callback when drawer is closed`, async ({ page }) => { - await page.setContent('Drawer content'); + await page.setContent('Drawer content'); const kolDrawer = page.locator('kol-drawer'); const callbackPromise = kolDrawer.evaluate((element: HTMLKolDrawerElement) => { - element._open = true; // see #7165 return new Promise((resolve) => { element._on = { onClose: () => { @@ -25,6 +24,31 @@ test.describe('kol-drawer', () => { }); }); + test.describe('_open property', () => { + test(`should open initially when _open property is true`, async ({ page }) => { + await page.setContent('
Drawer content
'); + await expect(page.getByTestId('drawer-content')).toBeVisible(); + }); + + test(`should open when _open property becomes true`, async ({ page }) => { + await page.setContent('
Drawer content
'); + const kolDrawer = page.locator('kol-drawer'); + await kolDrawer.evaluate((element: HTMLKolDrawerElement) => { + element._open = true; + }); + await expect(page.getByTestId('drawer-content')).toBeVisible(); + }); + + test(`should close when _open property becomes false`, async ({ page }) => { + await page.setContent('
Drawer content
'); + const kolDrawer = page.locator('kol-drawer'); + await kolDrawer.evaluate((element: HTMLKolDrawerElement) => { + element._open = false; + }); + await expect(page.getByTestId('drawer-content')).not.toBeVisible(); + }); + }); + test.describe('DOM events', () => { test(`should emit 'close' when drawer is closed`, async ({ page }) => { await page.setContent('Drawer content'); diff --git a/packages/components/src/components/drawer/shadow.tsx b/packages/components/src/components/drawer/shadow.tsx index 7a3f5adbb6..d1be34ad60 100644 --- a/packages/components/src/components/drawer/shadow.tsx +++ b/packages/components/src/components/drawer/shadow.tsx @@ -65,7 +65,12 @@ export class KolDrawer implements DrawerAPI { ); } - private getRef = (el: HTMLDialogElement | undefined) => (this.dialogElement = el as HTMLDialogElement); + private getRef = (el: HTMLDialogElement | undefined) => { + this.dialogElement = el as HTMLDialogElement; + setTimeout(() => { + void this.openOrCloseBasedOnState(); // handle initial state as soon as element is ready + }); + }; public render(): JSX.Element { return ( @@ -115,10 +120,22 @@ export class KolDrawer implements DrawerAPI { } @Watch('_open') - public async validateOpen(value?: OpenPropType): Promise { + public validateOpen(value?: OpenPropType) { if (typeof value === 'boolean') { validateOpen(this, value); - value ? await this.open() : await this.close(); + + if (this.dialogElement) { + // handle property changes but not the initial validateOpen call + void this.openOrCloseBasedOnState(); + } + } + } + + private async openOrCloseBasedOnState() { + if (this.state._open) { + await this.open(); + } else { + await this.close(); } } @@ -165,9 +182,9 @@ export class KolDrawer implements DrawerAPI { this.dialogElement?.removeEventListener('close', this.handleClose.bind(this)); } - public async componentWillLoad(): Promise { + public componentWillLoad() { this.validateLabel(this._label); - await this.validateOpen(this._open); + this.validateOpen(this._open); this.validateAlign(this._align); this.validateOn(this._on); }