diff --git a/src/ui/signinBanner/signinBanner.components.ts b/src/ui/signinBanner/signinBanner.components.ts
index 86d4ea70180a3ebfe0c76b2e4ddd093da0ce9aa3..524c174d1cdfe97166337266eef2359783c9786f 100644
--- a/src/ui/signinBanner/signinBanner.components.ts
+++ b/src/ui/signinBanner/signinBanner.components.ts
@@ -103,15 +103,16 @@ export class SigninBanner {
   private keyListenerConfigBase = {
     type: 'keydown',
     stop: true,
-    prevent: true,
     target: 'document',
   }
 
   public keyListenerConfig = [{
     key: 'h',
+    capture: true,
     ...this.keyListenerConfigBase,
   }, {
     key: 'H',
+    capture: true,
     ...this.keyListenerConfigBase,
   }, {
     key: '?',
diff --git a/src/util/directives/keyDownListener.directive.ts b/src/util/directives/keyDownListener.directive.ts
index 9cae5845bcbb408312d9bed42b70cfd0dcf1f571..f3fc055d1ffbb171c5ae2b9a72fa6af3ef12bb80 100644
--- a/src/util/directives/keyDownListener.directive.ts
+++ b/src/util/directives/keyDownListener.directive.ts
@@ -1,12 +1,12 @@
-import { Directive, EventEmitter, HostListener, Input, Output } from "@angular/core";
-
-const getFilterFn = (ev: KeyboardEvent, isDocument: boolean) => ({ type, key, target }: KeyListenerConfig): boolean => type === ev.type && ev.key === key && (target === 'document') === isDocument
+import { Directive, ElementRef, EventEmitter, Inject, Input, OnChanges, OnDestroy, Output } from "@angular/core";
+import { DOCUMENT } from '@angular/common'
+import { fromEvent, merge, Subscription } from "rxjs";
 
 @Directive({
   selector: '[iav-key-listener]',
 })
 
-export class KeyListner {
+export class KeyListner implements OnChanges, OnDestroy{
 
   @Input('iav-key-listener')
   public keydownConfig: KeyListenerConfig[] = []
@@ -19,64 +19,72 @@ export class KeyListner {
     return (tagName === 'SELECT' || tagName === 'INPUT' || tagName === 'TEXTAREA')
   }
 
-  @HostListener('keydown', ['$event'])
-  public keydown(ev: KeyboardEvent) {
-    this.handleSelfListener(ev)
-  }
-
-  @HostListener('document:keydown', ['$event'])
-  public documentKeydown(ev: KeyboardEvent) {
-    this.handleDocumentListener(ev)
+  private subs: Subscription[] = []
+
+  ngOnChanges(){
+    if (this.keydownConfig) {
+      this.ngOnDestroy()
+
+      const documentEv = this.keydownConfig.filter(c => c.target === 'document')
+      const documentCaptureEv = documentEv.filter(c => c.capture)
+      const documentBubbleEv = documentEv.filter(c => !c.capture)
+
+      const selfEv = this.keydownConfig.filter(c => c.target !== 'document')
+      const selfCaptureEv = selfEv.filter(c => c.capture)
+      const selfBubbleEv = selfEv.filter(c => !c.capture)
+
+      this.subs.push(
+        merge(
+          fromEvent(this.document, 'keydown', { capture: true }),
+          fromEvent(this.document, 'keyup', { capture: true })
+        ).subscribe(this.getEvHandler(documentCaptureEv).bind(this)),
+
+        merge(
+          fromEvent(this.document, 'keydown'),
+          fromEvent(this.document, 'keyup')
+        ).subscribe(this.getEvHandler(documentBubbleEv).bind(this)),
+
+        merge(
+          fromEvent(this.el.nativeElement, 'keydown', { capture: true }),
+          fromEvent(this.el.nativeElement, 'keyup', { capture: true })
+        ).subscribe(this.getEvHandler(selfCaptureEv).bind(this)),
+
+        merge(
+          fromEvent(this.el.nativeElement, 'keydown'),
+          fromEvent(this.el.nativeElement, 'keyup')
+        ).subscribe(this.getEvHandler(selfBubbleEv).bind(this)),
+      )
+    }
   }
 
-  @HostListener('keyup', ['$event'])
-  public keyup(ev: KeyboardEvent) {
-    this.handleSelfListener(ev)
+  ngOnDestroy(){
+    while(this.subs.length > 0) this.subs.pop().unsubscribe()
   }
 
-  @HostListener('document:keyup', ['$event'])
-  public documentKeyup(ev: KeyboardEvent) {
-    this.handleDocumentListener(ev)
-  }
+  constructor(
+    private el: ElementRef,
+    @Inject(DOCUMENT) private document
+  ){
 
-  private handleSelfListener(ev: KeyboardEvent) {
-    if (!this.keydownConfig) { return }
-    if (this.isTextField(ev)) { return }
-
-    const filteredConfig = this.keydownConfig
-      .filter(getFilterFn(ev, false))
-      .map(config => {
-        return {
-          config,
-          ev,
-        }
-      })
-    this.emitEv(filteredConfig)
   }
 
-  private handleDocumentListener(ev: KeyboardEvent) {
-    if (!this.keydownConfig) { return }
-    if (this.isTextField(ev)) { return }
-
-    const filteredConfig = this.keydownConfig
-      .filter(getFilterFn(ev, true))
-      .map(config => {
-        return {
-          config,
-          ev,
-        }
-      })
-    this.emitEv(filteredConfig)
+  private getEvHandler(cfgs: KeyListenerConfig[]){
+    return (ev: KeyboardEvent) => {
+      if (this.isTextField(ev)) return
+      const filteredCfgs = cfgs.filter(c => c.key === ev.key && c.type === ev.type)
+      for (const cfg of filteredCfgs) {
+        if (cfg.stop) ev.stopPropagation()
+      }
+      this.emitEv(filteredCfgs.map(cfg => ({
+        config: cfg,
+        ev
+      })))
+    }
   }
 
   private emitEv(items: Array<{config: KeyListenerConfig, ev: KeyboardEvent}>) {
     for (const item of items) {
       const { config, ev } = item as {config: KeyListenerConfig, ev: KeyboardEvent}
-
-      const { stop, prevent } = config
-      if (stop) { ev.stopPropagation() }
-      if (prevent) { ev.preventDefault() }
-
       this.keyEvent.emit({
         config, ev,
       })
@@ -91,6 +99,8 @@ export interface KeyListenerConfig {
   type: 'keydown' | 'keyup'
   key: string
   target?: 'document'
+  capture?: boolean
   stop: boolean
-  prevent: boolean
+  // fromEvent seems to be a passive listener, wheather or not { passive: false } flag is set or not
+  // so preventDefault cannot be called anyway
 }