Skip's keyboard hotkeys were inherited wholesale from upstream Kip, where they were built around a swipe-in Actions sidenav and Notification sidenav. The navigation-chrome redesign (#183) removed those sidenavs, so several bindings are now dead, inconsistent, or documented but unbound. Audit the full set, decide the keymap we actually want, and reconcile code + docs against it.
This is an audit/decision issue — the deliverable is a decided keymap plus the code/doc changes to match it, not a specific pre-chosen fix.
Current state
Global hotkeys are registered via uiEventService.addHotkeyListener (a raw document keydown listener; see src/app/core/services/uiEvent.service.ts).
| Keys |
Action |
Registered in |
Status |
Ctrl + ← / → |
Previous / next dashboard page |
app.component.ts (ngAfterViewInit) |
Live. Only fires when a dashboard is visible and locked (isDashboardStatic). Shift is ignored — the listener filters on ctrlKey only. |
Ctrl + Shift + E |
Toggle edit/layout mode |
menu-actions.component.ts |
Dead — see below |
Ctrl + Shift + F |
Toggle fullscreen |
menu-actions.component.ts |
Dead |
Ctrl + Shift + N |
Toggle night mode |
menu-actions.component.ts |
Dead |
Separately, iframe-inputs-inject.utils.ts injects a keydown forwarder into embed/iframe widgets (freeboardsk, generic iframe, anchor-alarm) that postMessages Ctrl+Shift+{ArrowLeft,ArrowRight,ArrowUp,ArrowDown,E,F,N} up to the parent, which re-dispatches them on document. This is the mechanism that lets hotkeys work while focus is inside an iframe.
Problems found
-
Ctrl+Shift+E/F/N are dead. MenuActionsComponent is the only registrant, and it is no longer mounted in any template (grep for menu-actions / MenuActionsComponent outside its own files returns nothing — it went away with the sidenav). Fullscreen, night-mode, and edit-mode hotkeys currently do nothing. (In-flight feat/navigation-chrome work plans to consolidate registration into app.component; ToolbarComponent has the handler methods but no E/F/N registration yet.)
-
The iframe injector forwards a stale key set. It still forwards Ctrl+Shift+{Arrows,E,F,N} — the old Kip contract. Against today's handlers: ArrowUp/ArrowDown are unbound, and E/F/N hit the dead handler, so those forwards are no-ops. Only ArrowLeft/ArrowRight still do anything.
-
Modifier mismatch on arrows. Docs and the iframe injector assume Ctrl+Shift+Arrow; the live page-nav handler binds Ctrl+Arrow and ignores Shift. It happens to work (Shift is permitted, not required), but the intended combo is ambiguous and inconsistent across the three places it appears.
-
Ctrl+Shift+↑/↓ are documented but unbound. welcome.md lists Up/Down for "cycle through dashboards"; nothing in the code listens for them.
-
Help docs describe the removed sidenav model. src/assets/help-docs/welcome.md (the shortcuts table), embedwidget.md, upgrade-config.component.html, and widget-tutorial.component.html still describe Ctrl+Shift+←/→ as "open Actions / Notification sidenav" — sidenavs that no longer exist.
Questions to settle in the review
- Are
Ctrl+Shift+E/F/N and Ctrl+arrow the right choices at all, or artifacts of Kip's UI? Do any conflict with browser/OS shortcuts (e.g. Ctrl+Shift+N = new incognito window, Ctrl+arrow = word-jump)?
- Which actions genuinely warrant a hotkey on a marine MFD that's mostly touch-operated? What's the real keyboard-user story here?
- Should the modifier be
Ctrl+Shift, Ctrl alone, or bare keys (with focus guards)? Pick one and apply it consistently across handler, injector, and docs.
- Whatever set survives: reconcile
iframe-inputs-inject.utils.ts, the registration site(s), and all four help docs so the three no longer disagree.
Coordination
This overlaps the active navigation UX redesign (tracking #183, PR-1 #185), which already touches hotkey registration (consolidating into app.component post-sidenav-removal). Do this audit alongside or right after that work so the keymap is rationalized once rather than twice.
Skip's keyboard hotkeys were inherited wholesale from upstream Kip, where they were built around a swipe-in Actions sidenav and Notification sidenav. The navigation-chrome redesign (#183) removed those sidenavs, so several bindings are now dead, inconsistent, or documented but unbound. Audit the full set, decide the keymap we actually want, and reconcile code + docs against it.
This is an audit/decision issue — the deliverable is a decided keymap plus the code/doc changes to match it, not a specific pre-chosen fix.
Current state
Global hotkeys are registered via
uiEventService.addHotkeyListener(a rawdocumentkeydownlistener; seesrc/app/core/services/uiEvent.service.ts).Ctrl+←/→app.component.ts(ngAfterViewInit)isDashboardStatic). Shift is ignored — the listener filters onctrlKeyonly.Ctrl+Shift+Emenu-actions.component.tsCtrl+Shift+Fmenu-actions.component.tsCtrl+Shift+Nmenu-actions.component.tsSeparately,
iframe-inputs-inject.utils.tsinjects akeydownforwarder into embed/iframe widgets (freeboardsk, generic iframe, anchor-alarm) thatpostMessagesCtrl+Shift+{ArrowLeft,ArrowRight,ArrowUp,ArrowDown,E,F,N}up to the parent, which re-dispatches them ondocument. This is the mechanism that lets hotkeys work while focus is inside an iframe.Problems found
Ctrl+Shift+E/F/Nare dead.MenuActionsComponentis the only registrant, and it is no longer mounted in any template (grep formenu-actions/MenuActionsComponentoutside its own files returns nothing — it went away with the sidenav). Fullscreen, night-mode, and edit-mode hotkeys currently do nothing. (In-flightfeat/navigation-chromework plans to consolidate registration intoapp.component;ToolbarComponenthas the handler methods but no E/F/N registration yet.)The iframe injector forwards a stale key set. It still forwards
Ctrl+Shift+{Arrows,E,F,N}— the old Kip contract. Against today's handlers:ArrowUp/ArrowDownare unbound, andE/F/Nhit the dead handler, so those forwards are no-ops. OnlyArrowLeft/ArrowRightstill do anything.Modifier mismatch on arrows. Docs and the iframe injector assume
Ctrl+Shift+Arrow; the live page-nav handler bindsCtrl+Arrowand ignores Shift. It happens to work (Shift is permitted, not required), but the intended combo is ambiguous and inconsistent across the three places it appears.Ctrl+Shift+↑/↓are documented but unbound.welcome.mdlists Up/Down for "cycle through dashboards"; nothing in the code listens for them.Help docs describe the removed sidenav model.
src/assets/help-docs/welcome.md(the shortcuts table),embedwidget.md,upgrade-config.component.html, andwidget-tutorial.component.htmlstill describeCtrl+Shift+←/→as "open Actions / Notification sidenav" — sidenavs that no longer exist.Questions to settle in the review
Ctrl+Shift+E/F/NandCtrl+arrow the right choices at all, or artifacts of Kip's UI? Do any conflict with browser/OS shortcuts (e.g.Ctrl+Shift+N= new incognito window,Ctrl+arrow = word-jump)?Ctrl+Shift,Ctrlalone, or bare keys (with focus guards)? Pick one and apply it consistently across handler, injector, and docs.iframe-inputs-inject.utils.ts, the registration site(s), and all four help docs so the three no longer disagree.Coordination
This overlaps the active navigation UX redesign (tracking #183, PR-1 #185), which already touches hotkey registration (consolidating into
app.componentpost-sidenav-removal). Do this audit alongside or right after that work so the keymap is rationalized once rather than twice.