Skip to content

Show assigned keyboard shortcuts consistently in desktop action tooltips - #334

Merged
matej21 merged 4 commits into
contember:mainfrom
bohacf:fix/terminal-shortcut-tooltips
Nov 14, 2026
Merged

matej21 merged 4 commits into
contember:mainfrom
bohacf:fix/terminal-shortcut-tooltips

Conversation

@bohacf

@bohacf bohacf commented Nov 12, 2026 •

Copy link
Copy Markdown
Contributor

Desktop action tooltips inconsistently displayed keyboard shortcuts, and a shortcut for the focused pane could be misleading on a different hovered target. Tooltips now resolve effective bindings from the live keymap and focused dispatch context, using the same native shortcut formatter as the keybindings editor. Shortcut labels follow the current operating system: macOS uses native symbols such as ⌘, ⌥ and ⇧, Windows uses labels such as Ctrl, Alt and Win, and Linux uses Ctrl, Alt and Super. The displayed shortcut comes from the active keymap, including user remappings.

Applies to terminal actions, sidebar/project controls, and file/diff navigation. Target and dismissal-state guards show a shortcut only when it performs the same operation as the hovered control. Controls without an equivalent command retain their text; informational tooltips, hover behavior and keyboard defaults are unchanged.

Validation:

  • All 5 shortcut helper tests passed (cargo test --locked --offline -p okena-ui --lib shortcuts::tests).
  • Windows desktop build passed (cargo build --locked --offline -p okena --bin okena --features rust-embed/debug-embed); existing unrelated Windows warnings remain.
  • Scoped rustfmt and whitespace checks passed.
  • Independent Claude Code source review completed; confirmed findings resolved.
  • Owner tested and accepted the Windows build.

bohacf and others added 4 commits November 14, 2026 14:33
The default keymap registers a cmd-* and a ctrl-shift-* variant of most
terminal actions on every platform, ctrl last. Picking the last effective
binding showed the Ctrl variant on macOS. Prefer bindings whose first
stroke uses Cmd on macOS and avoids Win/Super elsewhere; among those the
last registered still wins, and other bindings remain the fallback.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@matej21
matej21 force-pushed the fix/terminal-shortcut-tooltips branch from 915052a to 84caca9 Compare November 14, 2026 13:35
@matej21

matej21 commented Nov 14, 2026

Copy link
Copy Markdown
Member

Review — round 1

Reviewer: review agent (Claude Opus 5.5) · Commit reviewed: 915052a5 · Verdict: approve (one minor item fixed on top, see below)

Thanks for this, it is a careful piece of work. Resolving the shortcut from the live keymap on the focused dispatch path, and only showing it when the key would hit the same target as the hovered control, is exactly the right model. The bindings_for_input check against the real context stack handles shadowing, NoAction and !Context predicates correctly, and the tests cover the cases that matter. I checked the Back/Close guards in the file viewer and diff viewer against their Cancel handlers: they mirror the dismissal order exactly.

Findings

  1. Minor — macOS tooltips show the Ctrl variant instead of ⌘ (crates/okena-ui/src/shortcuts.rs, shortcut_for_action).
    The default keymap registers both variants on every platform, Cmd first and Ctrl second (cmd-d + ctrl-shift-d for Split Vertical, cmd-w + ctrl-shift-w for Close, and so on; see keybindings/config.rs). Taking the last effective binding therefore shows ⌃⇧D on macOS rather than ⌘D. Both work, but it is not the native shortcut and it differs from the title-bar tooltips.
    Fixed on top in 84caca9f: among the effective bindings, prefer those whose first stroke uses Cmd on macOS, and those without Win/Super elsewhere; among those the last registered still wins, and anything else stays the fallback (so a custom Ctrl binding on macOS still shows). Added a platform-parameterised unit test and made the two remap assertions platform-aware.

  2. Nit — two shortcut resolvers now coexist. The title bar (views/chrome/title_bar.rs) and tips (views/tips.rs) still use the config-based keybindings::shortcut_for_action(&str). With the fix above both pick the same binding for the defaults, so this is just a candidate for a follow-up that moves them to the keymap-based resolver.

  3. Nit — the Cancel guards duplicate the handlers' dismissal order (file_viewer/render.rs cancel_navigates, diff_viewer/render.rs). If someone adds a new dismissable overlay to the handler and forgets the guard, the tooltip would advertise Esc while Esc only closes the overlay. A shared fn cancel_navigates() used by both the handler and the tooltip would remove the drift risk. Not blocking.

  4. Nit — Expand active projects (Terminals) would become … (Terminals) (Ctrl+…) if a user binds ExpandActiveProjects (no default binding today). Cosmetic.

Next

Rebased onto current main (clean, no conflicts) together with the fix. I will merge once CI on 84caca9f is green.

— review agent (Claude Opus 5.5)

@matej21

matej21 commented Nov 14, 2026

Copy link
Copy Markdown
Member

Review response — round 1

  1. Minor, macOS shows the Ctrl variant: fixed in 84caca9f (prefer the native binding, last-registered still wins among those, added a unit test).
  2. Nit, two shortcut resolvers: won't fix here. Both now pick the same default binding; moving the title bar and tips to the keymap resolver can be a follow-up.
  3. Nit, Cancel guard duplication: won't fix here. The guards match the handlers today; not blocking.
  4. Nit, double parentheses on Expand/Collapse: won't fix. Only shows if a user binds the action, which has no default binding.

Rebased onto main with no conflicts; CI on 84caca9f is green (check, check-windows, mobile-rn). Merging.

— review agent (Claude Opus 5.5)

@matej21
matej21 merged commit 17835a7 into contember:main Nov 14, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants