From c156bac5f7f436ca6e9d721ff3247568db998910 Mon Sep 17 00:00:00 2001 From: Ankit Date: Fri, 13 Mar 2026 20:25:36 +0530 Subject: [PATCH] fix(settings): prevent j/k navigation keys from intercepting edit buffer input (#21865) --- .../shared/BaseSettingsDialog.test.tsx | 42 +++++++++++++++++++ .../components/shared/BaseSettingsDialog.tsx | 11 +++-- 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/packages/cli/src/ui/components/shared/BaseSettingsDialog.test.tsx b/packages/cli/src/ui/components/shared/BaseSettingsDialog.test.tsx index 5cc731e3f7..1ac701eff1 100644 --- a/packages/cli/src/ui/components/shared/BaseSettingsDialog.test.tsx +++ b/packages/cli/src/ui/components/shared/BaseSettingsDialog.test.tsx @@ -760,6 +760,48 @@ describe('BaseSettingsDialog', () => { }); unmount(); }); + + it('should allow j and k characters to be typed in string edit fields without triggering navigation', async () => { + const items = createMockItems(4); + const stringItem = items.find((i) => i.type === 'string')!; + const { stdin, waitUntilReady, unmount } = await renderDialog({ + items: [stringItem], + }); + + // Enter edit mode + await act(async () => { + stdin.write(TerminalKeys.ENTER); + }); + await waitUntilReady(); + + // Type 'j' - should appear in field, NOT trigger navigation + await act(async () => { + stdin.write('j'); + }); + await waitUntilReady(); + + // Type 'k' - should appear in field, NOT trigger navigation + await act(async () => { + stdin.write('k'); + }); + await waitUntilReady(); + + // Commit with Enter + await act(async () => { + stdin.write(TerminalKeys.ENTER); + }); + await waitUntilReady(); + + // j and k should be typed into the field + await waitFor(() => { + expect(mockOnEditCommit).toHaveBeenCalledWith( + 'string-setting', + 'test-valuejk', // entered value + j and k + expect.objectContaining({ type: 'string' }), + ); + }); + unmount(); + }); }); describe('custom key handling', () => { diff --git a/packages/cli/src/ui/components/shared/BaseSettingsDialog.tsx b/packages/cli/src/ui/components/shared/BaseSettingsDialog.tsx index 1434a28c52..d96646e8a5 100644 --- a/packages/cli/src/ui/components/shared/BaseSettingsDialog.tsx +++ b/packages/cli/src/ui/components/shared/BaseSettingsDialog.tsx @@ -325,13 +325,18 @@ export function BaseSettingsDialog({ return; } - // Up/Down in edit mode - commit and navigate - if (keyMatchers[Command.DIALOG_NAVIGATION_UP](key)) { + // Up/Down in edit mode - commit and navigate. + // Only trigger on non-insertable keys (arrow keys) so that typing + // j/k characters into the edit buffer is not intercepted. + if (keyMatchers[Command.DIALOG_NAVIGATION_UP](key) && !key.insertable) { commitEdit(); moveUp(); return; } - if (keyMatchers[Command.DIALOG_NAVIGATION_DOWN](key)) { + if ( + keyMatchers[Command.DIALOG_NAVIGATION_DOWN](key) && + !key.insertable + ) { commitEdit(); moveDown(); return;