BUG | `onKeyStroke()` | Registers a capture listener when `passive: true`
Describe the bug
Description
Passing passive: true to onKeyStroke() unexpectedly registers the event listener in the capture phase. Consequently, a descendant cannot prevent the handler from running with event.stopPropagation().
OnKeyStrokeOptions.passive indicates that it controls whether the listener is passive. The resulting listener should therefore be registered with {passive: true}, without changing its propagation phase.
Expected behavior
The input handler calls stopPropagation(), so the ancestor's onKeyStroke() handler should not run.
Actual behavior
The ancestor handler runs before the input handler: KeyboardEvent.eventPhase === 1 identifies the capturing phase.
Suspected cause
onKeyStroke() passes the passive boolean directly as the listener options:
return useEventListener(target, eventName, listener, passive);
useEventListener() correctly forwards that value to the native API:
el.addEventListener(event, listener, options);
In the native addEventListener() API, a boolean options argument represents useCapture. Thus, passive: true becomes a capture listener instead of a passive listener.
Passing an options object would preserve the documented meaning:
return useEventListener(target, eventName, listener, {passive});
Reproduction
System Info
System:
OS: macOS 26.6.2
CPU: (10) arm64 Apple M1 Pro
Memory: 119.45 MB / 16.00 GB
Shell: 5.9 - /bin/zsh
Binaries:
Node: 24.19.0
npm: 12.0.2
Browsers:
Firefox: 154.0.1
Safari: 26.6.2
npmPackages:
@vueuse/core: ^14.4.0 => 14.4.0
vue: ^3.5.40 => 3.5.42
Used Package Manager
npm
Validations
- Follow our Code of Conduct
- Read the Contributing Guidelines.
- Read the docs.
- Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.
- Make sure this is a VueUse issue and not a framework-specific issue. For example, if it's a Vue SFC related bug, it should likely be reported to https://github.com/vuejs/core instead.
- Check that this is a concrete bug. For Q&A open a GitHub Discussion.
- The provided reproduction is a minimal reproducible example of the bug.
Source: vueuse/vueuse