Skip to content

Commit 4e48c40

Browse files
Fix #1292
1 parent 34fc0e0 commit 4e48c40

File tree

2 files changed

+33
-3
lines changed

2 files changed

+33
-3
lines changed

packages/react-hotkeys-hook/src/lib/validators.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -132,13 +132,19 @@ export const isHotkeyMatchingKeyboardEvent = (e: KeyboardEvent, hotkey: Hotkey,
132132
return true
133133
}
134134

135-
if (keys) {
135+
if (keys && keys.length > 0) {
136+
// For multi-key combinations, the pressed key must be one of the expected keys
137+
// This prevents triggering when a modifier is pressed while holding an unrelated key
138+
if (!keys.includes(mappedCode)) {
139+
return false
140+
}
136141
// Check if all keys are present in pressedDownKeys set
137142
return isHotkeyPressed(keys)
138143
}
139144

140-
if (!keys) {
141-
// If the key is not set, we only listen for modifiers, that check went alright, so we return true
145+
if (!keys || keys.length === 0) {
146+
// If no keys are set (modifier-only hotkey like 'shift'), we only listen for modifiers.
147+
// The modifier checks above passed, so we return true.
142148
return true
143149
}
144150

packages/react-hotkeys-hook/src/test/useHotkeys.test.tsx

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1470,6 +1470,30 @@ test('Should ignore modifiers if option is set', async () => {
14701470
expect(callback).toHaveBeenCalledTimes(2)
14711471
})
14721472

1473+
test('should not trigger callback twice when pressing a key and then a modifier', async () => {
1474+
const user = userEvent.setup()
1475+
const callback = vi.fn()
1476+
1477+
renderHook(() => useHotkeys('a', callback))
1478+
1479+
// Press 'a' and hold it, then press shift while still holding 'a'
1480+
// The callback should only fire once (when 'a' is pressed)
1481+
await user.keyboard('{a>}{Shift>}{/Shift}{/a}')
1482+
1483+
expect(callback).toHaveBeenCalledTimes(1)
1484+
})
1485+
1486+
test('should not trigger callback when modifier is pressed while holding unrelated key', async () => {
1487+
const user = userEvent.setup()
1488+
const callback = vi.fn()
1489+
1490+
renderHook(() => useHotkeys('b', callback))
1491+
1492+
// Press 'a' and hold it, then press shift - should not trigger 'b' callback
1493+
await user.keyboard('{a>}{Shift>}{/Shift}{/a}')
1494+
1495+
expect(callback).toHaveBeenCalledTimes(0)
1496+
})
14731497

14741498
test('should respect dependencies array if they are passed', async () => {
14751499
function Fixture() {

0 commit comments

Comments
 (0)