From cc99e6ecb32cbf00f48efad9af4bcfb73a536c2a Mon Sep 17 00:00:00 2001 From: Danila Poyarkov Date: Thu, 10 Sep 2026 22:40:19 +0300 Subject: [PATCH] fix(dialog): honor reduced motion over state animations --- src/theme/dialog/index.ts | 2 +- tests/e2e/settings/model-editor.spec.ts | 26 +++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/theme/dialog/index.ts b/src/theme/dialog/index.ts index b1ec6d2a9..eb0713771 100644 --- a/src/theme/dialog/index.ts +++ b/src/theme/dialog/index.ts @@ -1,5 +1,5 @@ const dialogMotion = - 'data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:duration-180 data-[state=open]:ease-out data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:duration-120 data-[state=closed]:ease-in motion-reduce:animate-none' + 'data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:duration-180 data-[state=open]:ease-out data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:duration-120 data-[state=closed]:ease-in motion-reduce:data-[state=open]:animate-none motion-reduce:data-[state=closed]:animate-none' export default { slots: { diff --git a/tests/e2e/settings/model-editor.spec.ts b/tests/e2e/settings/model-editor.spec.ts index 411a1a453..3b3c4b8c4 100644 --- a/tests/e2e/settings/model-editor.spec.ts +++ b/tests/e2e/settings/model-editor.spec.ts @@ -30,6 +30,32 @@ test('model editing keeps the Settings shell stable and isolates the form', asyn expect(await dialog.boundingBox()).toEqual(before) }) +for (const reducedMotion of ['reduce', 'no-preference'] as const) { + test(`model editing restores focus across repeated transitions with ${reducedMotion} motion`, async ({ + page + }) => { + await page.emulateMedia({ reducedMotion }) + await page.setViewportSize({ width: 900, height: 700 }) + await page.goto('/?test') + await new CanvasHelper(page).waitForInit() + await page.getByTestId('app-settings-trigger').click() + await page.getByTestId('settings-section-ai').click() + const dialog = page.getByTestId('app-settings-dialog') + if (reducedMotion === 'reduce') await expect(dialog).toHaveCSS('animation-name', 'none') + const add = page.getByTestId('settings-add-model') + for (let attempt = 0; attempt < 3; attempt++) { + await add.click() + const editor = page.getByTestId('settings-model-editor') + await expect(editor.locator('input').first()).toBeFocused() + await editor.getByRole('button', { name: 'Cancel', exact: true }).click() + await expect(add).toBeFocused() + await expect(dialog.getByRole('tabpanel')).toHaveCount(1) + } + await page.getByTestId('app-settings-done').click() + await expect(dialog).not.toBeVisible() + }) +} + test('page rows keep the same compact height while renaming', async ({ page }) => { await page.goto('/?test') await new CanvasHelper(page).waitForInit()