feat(agor-ui): global keyboard shortcuts + command palette#1794
Open
preset-ce wants to merge 1 commit into
Open
feat(agor-ui): global keyboard shortcuts + command palette#1794preset-ce wants to merge 1 commit into
preset-ce wants to merge 1 commit into
Conversation
Add an extensible keyboard-shortcut system driven by a single registry (src/keyboard) that powers both key matching and a discoverable help overlay, so the two can never drift. Shortcuts (single-key, GitHub/Linear style — suppressed while typing in inputs/textareas/contenteditable, and exact-modifier matching so they never collide with browser chords like Cmd/Ctrl+C): - c → start a new session (opens the create dialog) - b → board switcher command palette (filter + ↑/↓ + Enter) - a → authenticate MCP servers (bulk silent token refresh) - ? or Cmd/Ctrl+/ → show the keyboard-shortcuts help overlay - Cmd/Ctrl+K → documented in the overlay; still owned by GlobalSearch The provider installs one global keydown listener and dispatches by id; components attach handlers via useKeyboardShortcut() so bindings are mount-scoped for free. MCP auth re-authenticates every OAuth server whose token is missing or expired via the refresh endpoint (no popups). Servers needing an interactive sign-in can't be batched (browsers block bulk OAuth popups) and are reported so the user can sign in per-server from Settings. Tests cover the matcher (mod mapping, exact-modifier rules, `?` implicit shift, editable-target detection, platform key formatting). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a small, extensible keyboard-shortcut system so common actions can be driven from the keyboard, per the request in #agor (Juliann / Evan / Daniel).
Everything is driven by a single registry (
apps/agor-ui/src/keyboard/shortcuts.ts) that powers both key matching and the discoverable help overlay, so they can never drift out of sync.Shortcuts
cba?or⌘/Ctrl + /⌘/Ctrl + KGlobalSearch)Key-choice rationale: single-key shortcuts follow the GitHub / Linear convention. They're memorable, and because the system suppresses shortcuts while the user is typing in an
input/textarea/contenteditable/ textbox-role element, single keys never collide with browser or OS chords (which are all modifier-based). Matching is exact on modifiers, so barecdoes not fire on⌘/Ctrl+C.⌘is used on macOS andCtrlelsewhere (modin the combo DSL).Design
src/keyboard/shortcuts.ts/types.ts— the registry (single source of truth).matchShortcut.ts— pure combo parser + matcher,isEditableTarget()guard, platform-awareformatCombo(). Unit-tested.KeyboardShortcutsProvider.tsx— installs one globalkeydownlistener and dispatches by id. Components attach handlers withuseKeyboardShortcut(id, handler), so bindings are mount-scoped for free. Owns the help-overlay state.KeyboardShortcutsHelp.tsx— the?overlay, generated entirely from the registry and grouped (General / Navigation / Actions).components/BoardSwitcherPalette/— keyboard-first board switcher modal (complements the existing click-driven headerBoardSwitcherdropdown rather than replacing it).src/App.tsx(aroundAppContent); a smallGlobalShortcutscomponent insideAppbinds the app-level handlers and owns the palette. The new-session handler reuses the same create-dialog flow as the existing "New session" button.MCP authentication — what's implemented vs. deferred
Implemented (
a): re-authenticates every OAuth MCP server whose token is missing or expired by calling the existingmcp-servers/oauth-refreshendpoint for each, in parallel, with a summary toast. No popups, no new backend.Deferred / noted: servers that need an interactive sign-in (no refresh token / revoked grant) can't be batched — browsers block bulk OAuth popups, and each flow needs a user gesture. Rather than half-wire that (and get popups blocked), those servers are reported by name in a warning toast so the user can sign in per-server from Settings → MCP servers (the existing per-pill flow). A true one-click "authenticate all" would need either a bulk backend endpoint or a dedicated multi-step consent surface.
Tests
matchShortcut.test.ts(10 cases):mod→Cmd/Ctrl mapping, exact-modifier matching (barecvs⌘C), case-insensitivity,?implicit-shift handling, editable-target detection, and platform key formatting.pnpm typecheckandbiome cipass.Screenshots
Not captured — this branch's worktree has no running dev environment. The help overlay is a standard AntD
Modalrendering styled<kbd>caps; the palette mirrors the existing global-search dropdown patterns.🤖 Generated with Claude Code