From 8dd0a793ad371d937539d053c82d8834b2121726 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 17 Apr 2026 18:52:21 +0000 Subject: [PATCH] Fix keybind conflicts: remove HJKL movement and fix shortcut shadowing - Remove h/j/k/l as movement aliases from world map (HJKL conflicts) - Remove j/k from Menu, charCreate list/skills navigation (HJKL; j also globally intercepted to open Jukebox in most game states) - Remove k/K from Jukebox up-navigation (HJKL) - Reorder Menu.handleKey so explicit opt.key shortcuts are checked before WASD navigation keys, fixing s="Save Game" being shadowed by s=move-down https://claude.ai/code/session_01PEoMNt9CCkZeuBTjYM9Y9y --- js/ui/menu.ts | 25 +++++++++++++++---------- js/ui/screens/charCreate.ts | 8 ++++---- js/ui/screens/jukebox.ts | 2 +- js/ui/screens/worldmap.ts | 1 - 4 files changed, 20 insertions(+), 16 deletions(-) diff --git a/js/ui/menu.ts b/js/ui/menu.ts index f3554da..5496a40 100644 --- a/js/ui/menu.ts +++ b/js/ui/menu.ts @@ -34,24 +34,29 @@ export class Menu { } handleKey(e) { - if (e.key === 'ArrowUp' || e.key === 'w' || e.key === 'k') { e.preventDefault(); this.moveUp(); return true; } - if (e.key === 'ArrowDown' || e.key === 's' || e.key === 'j') { e.preventDefault(); this.moveDown(); return true; } - if (e.key === 'Enter' || e.key === ' ') { - e.preventDefault(); - this.activate(); - return true; - } - // Key shortcuts: match first char of option label + // Explicit option shortcuts take priority so they aren't shadowed by navigation keys for (let i = 0; i < this.options.length; i++) { const opt = this.options[i]; if (opt.disabled) continue; if (opt.key && e.key.toLowerCase() === opt.key.toLowerCase()) { + e.preventDefault(); this.selected = i; this.activate(); return true; } - // Auto-shortcut: first letter - if (!opt.key && opt.label && e.key.toLowerCase() === opt.label[0]?.toLowerCase()) { + } + if (e.key === 'ArrowUp' || e.key === 'w') { e.preventDefault(); this.moveUp(); return true; } + if (e.key === 'ArrowDown' || e.key === 's') { e.preventDefault(); this.moveDown(); return true; } + if (e.key === 'Enter' || e.key === ' ') { + e.preventDefault(); + this.activate(); + return true; + } + // Auto-shortcut: first letter of option label (for options without an explicit key) + for (let i = 0; i < this.options.length; i++) { + const opt = this.options[i]; + if (opt.disabled || opt.key) continue; + if (opt.label && e.key.toLowerCase() === opt.label[0]?.toLowerCase()) { this.selected = i; this.activate(); return true; diff --git a/js/ui/screens/charCreate.ts b/js/ui/screens/charCreate.ts index d46b70b..1e49b18 100644 --- a/js/ui/screens/charCreate.ts +++ b/js/ui/screens/charCreate.ts @@ -305,15 +305,15 @@ export class CharCreateScreen { _handleListKey(event, list) { const key = event.key; - if (key === 'ArrowUp' || key === 'k' || key === 'w') { event.preventDefault(); list.moveUp(); return; } - if (key === 'ArrowDown' || key === 'j' || key === 's') { event.preventDefault(); list.moveDown(); return; } + if (key === 'ArrowUp' || key === 'w') { event.preventDefault(); list.moveUp(); return; } + if (key === 'ArrowDown' || key === 's') { event.preventDefault(); list.moveDown(); return; } if (key === 'Enter' || key === 'Tab') { event.preventDefault(); this._nextStep(); return; } } _handleSkillsKey(event) { const key = event.key; - if (key === 'ArrowUp' || key === 'k') { event.preventDefault(); this.skillList.moveUp(); return; } - if (key === 'ArrowDown' || key === 'j') { event.preventDefault(); this.skillList.moveDown(); return; } + if (key === 'ArrowUp') { event.preventDefault(); this.skillList.moveUp(); return; } + if (key === 'ArrowDown') { event.preventDefault(); this.skillList.moveDown(); return; } if (key === ' ') { event.preventDefault(); this._toggleSkill(this.skillList.selected); diff --git a/js/ui/screens/jukebox.ts b/js/ui/screens/jukebox.ts index b7618bc..2e5e82c 100644 --- a/js/ui/screens/jukebox.ts +++ b/js/ui/screens/jukebox.ts @@ -78,7 +78,7 @@ export class JukeboxScreen { } // Arrow keys and Page Up/Down handled by ScrollList - if (k === 'ArrowUp' || k === 'w' || k === 'W' || k === 'k' || k === 'K') { + if (k === 'ArrowUp' || k === 'w' || k === 'W') { event.preventDefault(); this.list.moveUp(); return; diff --git a/js/ui/screens/worldmap.ts b/js/ui/screens/worldmap.ts index 1c9344d..2ac1df4 100644 --- a/js/ui/screens/worldmap.ts +++ b/js/ui/screens/worldmap.ts @@ -50,7 +50,6 @@ export class WorldMapScreen { const moves = { 'ArrowUp': [0,-1], 'ArrowDown': [0,1], 'ArrowLeft': [-1,0], 'ArrowRight': [1,0], 'w': [0,-1], 's': [0,1], 'a': [-1,0], 'd': [1,0], - 'k': [0,-1], 'j': [0,1], 'h': [-1,0], 'l': [1,0], }; if (e.key in moves) {