Conversation
Nothing in the app answered "what shortcuts exist" in one place - Cmd/Ctrl+K was the only one documented anywhere in the UI, and Monaco's own bindings were discoverable only through its right-click menu. ShortcutsDialog lists every app-wide shortcut, Monaco's included, from a single registry (src/lib/shortcuts.ts). It opens on "?" (ignored while typing in an input, textarea or contentEditable element) and, in the standalone shell, from a new CommandPalette entry via an imperative ref. Mounted directly in both Studio.tsx and DataProfiler.tsx rather than threaded through props: DataProfiler is rendered by both the standalone shell and the embedded workspace, so mounting it there once covers both hosts, the same way its own Escape-to-close effect already does.
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
cevheri
left a comment
There was a problem hiding this comment.
Thanks @Asgabani, and apologies for the first item: the ground moved under you after you opened this.
main now has src/lib/keyboard-shortcuts.ts, a shared registry with SHORTCUTS, matchesShortcut, shortcutLabel and monacoKeybinding, already used by CommandPalette, QueryEditor and StudioTabBar, and the shortcut line in docs/FEATURES.md is generated from it by bun run shortcuts:sync. That is also your StudioTabBar conflict: main dropped NEW_TAB_SHORTCUT_LABEL for shortcutLabel(SHORTCUTS.newTab). Please rebase and render the dialog from that registry rather than a second one. Adding ? there is not purely mechanical, since every entry feeds the Monaco binding, so use your judgement on the display-only rows. You also get "Cmd/Ctrl+Enter", which your hand-written "Ctrl+Enter" gets wrong on macOS.
Two things I measured that survive the rebase.
? cannot be typed in the query editor. I typed SELECT, pressed ?, and the dialog opened while the character never reached the buffer. Monaco 0.56 focuses a div.native-edit-context, so the input/textarea/contentEditable check misses it, and ? is the positional parameter placeholder in SQLite and MySQL. Your guard tests mount a real textarea, which the editor is no longer.
Studio and DataProfiler each mount a dialog with its own listener, so with the profiler open ? gives you two, and one Escape closes one of them plus the profiler underneath.
A question rather than a change: the tab bar's arrows are listed, the object browser's whole tree pattern is not. Worth settling which side widget keys sit on.
Importing NEW_TAB_SHORTCUT_LABEL was the right instinct, by the way: retyping it and changing the binding does fail your test.
Closes #746.
What changed
src/lib/shortcuts.ts: a single registry (SHORTCUT_GROUPS) listing every app-wide shortcut — the command palette, Monaco's Run/Format bindings, tab navigation (including the new-tab shortcut, imported fromStudioTabBarrather than retyped so it can't drift), and the data profiler's Escape-to-close.ShortcutsDialog(src/components/ShortcutsDialog.tsx): a self-contained dialog, followingCommandPalette's own Cmd/Ctrl+K effect — it owns its open state and its?listener (guarded against firing while typing in an input, textarea, or contentEditable element). Exposes an imperativeopen()via ref, the same seamQueryEditorRefalready uses.Studio.tsxdirectly, plus a new "Keyboard Shortcuts"CommandPaletteentry that reaches it through the ref.DataProfiler.tsxdirectly rather than through props:DataProfileris rendered by both the standalone shell (Studio.tsx) and the embedded workspace (StudioWorkspace.tsx, which has noCommandPalette), so mountingShortcutsDialoginsideDataProfileronce — scoped to while the profiler is open, matching its own Escape effect's scoping — covers both hosts without threading state through either.Testing
Ran locally (
bun run format && bun run lint && bun run typecheck && bun run knip && bun run chart:check && bun run channels:showcase:check && bun run readme:check && bun run security:check && bun run test && bun run build, plusbun run build:lib && bun run attwsinceDataProfiler/Sidebarare reachable from the embeddable workspace export surface):git stash).bun run test:components: 44/44 groups pass. (Added the newShortcutsDialog.test.tsxtotests/run-components.sh's group list —tests/unit/component-runner-coverage.test.tscatches a file missing from it.)bun run test: same 13 pre-existing failures as a clean checkout (Helm binary not installed, missing built standalone zip). No live Postgres/MySQL in this sandbox.bun run test:coverage && bun run coverage:check: 100.00% line coverage on the merged lcov.bun run build,bun run build:lib,bun run attw: all succeed.If CI surfaces something this sandbox couldn't (Helm chart tests, live DB integration tests), happy to fix it up.