From e76a74d29400238d8668a3b84b58de19aa16772a Mon Sep 17 00:00:00 2001 From: Chris0Jeky Date: Sun, 6 Sep 2026 04:58:48 +0100 Subject: [PATCH] Guard workspace setup against IME Enter --- .../workspace/WorkspaceSetupModal.vue | 10 +++++- .../components/WorkspaceSetupModal.spec.ts | 32 +++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/frontend/taskdeck-web/src/components/workspace/WorkspaceSetupModal.vue b/frontend/taskdeck-web/src/components/workspace/WorkspaceSetupModal.vue index fc87d0d33..06fe69af4 100644 --- a/frontend/taskdeck-web/src/components/workspace/WorkspaceSetupModal.vue +++ b/frontend/taskdeck-web/src/components/workspace/WorkspaceSetupModal.vue @@ -71,6 +71,14 @@ async function applyStarterPack(boardId: string, starterPackId: string): Promise } } +function onBoardNameKeydown(event: KeyboardEvent) { + if (event.isComposing) { + return + } + + void submitSetup() +} + async function submitSetup() { if (!canSubmit.value || !selectedSetup.value) { return @@ -154,7 +162,7 @@ watch( type="text" maxlength="100" placeholder="For example: Product Sprint" - @keydown.enter.prevent="submitSetup" + @keydown.enter.prevent="onBoardNameKeydown" /> diff --git a/frontend/taskdeck-web/src/tests/components/WorkspaceSetupModal.spec.ts b/frontend/taskdeck-web/src/tests/components/WorkspaceSetupModal.spec.ts index fd5ef5de9..ba4a411dc 100644 --- a/frontend/taskdeck-web/src/tests/components/WorkspaceSetupModal.spec.ts +++ b/frontend/taskdeck-web/src/tests/components/WorkspaceSetupModal.spec.ts @@ -120,6 +120,38 @@ describe('WorkspaceSetupModal', () => { expect(mocks.push).toHaveBeenCalledWith('/workspace/boards/board-1') }) + it('ignores Enter while IME composition is active, then submits ordinary Enter once', async () => { + const wrapper = mount(WorkspaceSetupModal, { + props: { + isOpen: true, + }, + }) + + const input = wrapper.get('input[placeholder="For example: Product Sprint"]') + await input.setValue('IME Board') + + const composingEnter = new KeyboardEvent('keydown', { + key: 'Enter', + isComposing: true, + bubbles: true, + cancelable: true, + }) + expect(input.element.dispatchEvent(composingEnter)).toBe(false) + await waitForUi() + expect(mocks.createBoard).not.toHaveBeenCalled() + + const ordinaryEnter = new KeyboardEvent('keydown', { + key: 'Enter', + bubbles: true, + cancelable: true, + }) + expect(input.element.dispatchEvent(ordinaryEnter)).toBe(false) + await waitForUi() + + expect(mocks.createBoard).toHaveBeenCalledTimes(1) + expect(mocks.createBoard).toHaveBeenCalledWith({ name: 'IME Board' }) + }) + it('cancels on a dispatched Escape while allowing the submitting lock to hold', async () => { const wrapper = mount(WorkspaceSetupModal, { props: {