Repository navigation
fix(app-shell,i18n): the keyboard-shortcuts dialog lists only shortcuts a mounted handler advertises (objectui#11674) - #11708
Merged
objectstack-fleet[bot] merged 5 commits intoOct 6, 2026
Conversation
…ts a mounted handler advertises (objectui#11674) The dialog was a static list; N, Cmd/Ctrl+E, Cmd/Ctrl+/, Cmd/Ctrl+D and a bare B had no handler. Each handler now advertises its shortcut beside itself (advertisedShortcuts.ts) and the dialog lists what is advertised. The sidebar row reads its real chord, Cmd/Ctrl+B. The seven console.shortcuts keys only the dead rows read are retired from all ten packs. Claude-Session: https://claude.ai/code/session_01FngvPpdrnhHMdHHq6vwwju Co-authored-by: Claude <noreply@anthropic.com>
…es (objectui#11674) Claude-Session: https://claude.ai/code/session_01FngvPpdrnhHMdHHq6vwwju Co-authored-by: Claude <noreply@anthropic.com>
…alog (objectui#11674) Claude-Session: https://claude.ai/code/session_01FngvPpdrnhHMdHHq6vwwju Co-authored-by: Claude <noreply@anthropic.com>
…l; read the registry in the pin through the DOM (objectui#11674) Claude-Session: https://claude.ai/code/session_01FngvPpdrnhHMdHHq6vwwju Co-authored-by: Claude <noreply@anthropic.com>
…objectui#11674) Claude-Session: https://claude.ai/code/session_01FngvPpdrnhHMdHHq6vwwju Co-authored-by: Claude <noreply@anthropic.com>
Contributor
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
This was referenced Oct 6, 2026
objectstack-fleet
Bot
deleted the
claude/issue-11674-shortcuts-dialog-wired-only
branch
October 6, 2026 09:26
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.
Fixes #11674
Clause-②: no (narrowing)
The claim wrote
Clause-②: no, with the rule that it becomesno (narrowing)if publishedconsole.shortcuts.*locale keys retire. Seven do, so the line readsno (narrowing). No accept set widens, and@object-ui/app-shellexports nothing new.What was wrong (measured on
origin/mainatc3623eb)The dialog was a static list, kept apart from every key handler. Every row, by the handler it had:
main⌘KOpen command paletteCommandPaletteProviderkeydown (kwith ⌘ or Ctrl)?Show keyboard shortcutsEscClose dialog / panelDialogandSheetBToggle sidebarSidebarProviderlistener (synced Shadcn primitive) answersbwith ⌘ or Ctrl only. A bareBdoes nothing⌘/Focus searchNCreate new recorduseCrudShortcuts/useKeyboardShortcutshave no caller outside their moduleRRefresh datarlistener is the approvals inbox's reject key, on that page only⌘EEdit selected record⌘⇧ONew chat,⌘⇧SToggle conversations listAiChatPageonly (matchAiChatShortcut). The dialog mounts inAppContent(/apps/...) and/aiis not under it, so neither handler is mounted where the rows were shown⌘DToggle dark modeThe card named five of these. The order asked for every row to be measured, which added
Rand the AI pair.What changed
packages/app-shell/src/chrome/advertisedShortcuts.ts(new). A small module store, the same shape asassistantBus. The code that owns a handler callsuseAdvertiseShortcut(descriptor, enabled?)beside it, so the shortcut is advertised while the handler is mounted.useAdvertisedShortcuts()reads the current set. A descriptor is{ id, group, chord, label }. The keycaps come from the chord (shortcutKeycaps), andlabelis a literalt('…')call so the i18n gates read the key (see the probe below).KeyboardShortcutsDialoghas no list of its own any more. It renders the advertised shortcuts, grouped (general,navigation,aiChat) and sorted by their text, and each row carriesdata-shortcut-id. It advertises its own?, andEsc(Radix's dismiss) beside theDialogthatEsccloses.CommandPaletteProvideradvertises⌘Kbeside its keydown handler.ConsoleLayout's inner component, which sits insideSidebarProvider, advertises⌘B. The listener belongs to the primitive.packages/components/src/ui/sidebar.tsxwas read and not edited.AiChatPageadvertises⌘⇧Oand⌘⇧Sbeside the listener that callsmatchAiChatShortcut. So they are listed only where that page is mounted, and today the dialog is not mounted there.@object-ui/i18n. Seven keys were read only by the dead rows, and they are removed from all ten packs:console.shortcuts.focusSearch,createRecord,refreshData,editRecord,toggleDarkMode,groups.dataViews,groups.preferences. Two i18n test comments citedtoggleDarkModeas an example of ё, and they are reworded. One of them also carried a stale ё count, which is dropped, not re-counted..changeset/11674-shortcuts-dialog-wired-only.md,minorfor both packages, with the key removal spelled out as BREAKING atminorunder the repo's version policy.Inside an app, the dialog now lists
⌘K,?,Escand⌘B.Landing point: the order expected the static list in
KeyboardShortcutsDialog.tsx. That file is where the list was. The fix also touches three files that register handlers, and only to advertise them, as the claim's file surface allows.The pin
packages/app-shell/src/chrome/KeyboardShortcutsDialog.wiredOnly-11674.test.tsx:AppContentmounts it: inside the realConsoleLayout, with the realAppShell,SidebarProviderandCommandPaletteProvider. It opens the dialog with?shortcuts=1. For each row it fires the chord that the row's own advertisement declares, once with ⌘ and once with Ctrl, each on a fresh mount, and checks the real handler's effect: the palette opens, the dialog opens, the dialog closes, the sidebar collapses. The rows must equal the advertisements, keycaps included, and must equal the probe table's keys. So a listed row that nothing can fire fails, and the loop cannot pass by running nothing.matchAiChatShortcutreturns the right action for both chords.b, the old row, does not toggle the sidebar.Ablations (one-off, run from committed HEAD
05c1f48, restore proved by blob hash)b(chord: { key: 'b' }) withablation-replace(anchor 1 → 0, blobde7e99c048be→93c37705f9e4). The pin went red,Tests 1 failed | 4 passed (5), at the sidebar probe:data-sidebar-openstayed"true". Restored: blob == HEADde7e99c048be,git diff HEADempty.KeyboardShortcutsDialog.tsxwas swapped for itsc3623ebbytes (createRecordmarker 1,useAdvertiseShortcut0, blobad882b0dc950). The test went red,Tests 2 failed | 3 passed (5): the pin and the derivation case. Restored: blob == HEADf766b2845931.t('console.shortcuts.toggleSidebar')in the sidebar descriptor was renamed to a key no pack has.check:i18n-keysexited 1 with[missing-key] console.shortcuts.toggleSidebarProbeatConsoleLayout.tsx. Restored: blob == HEAD.Gates (objectui's own; derived by hand from
package.jsonand.github/workflows/)All at HEAD
05c1f48. Each exit code was captured before any pipe.pnpm exec vitest run --maxWorkers=2 packages/i18n/ packages/app-shell/src/chrome/ packages/app-shell/src/layout/ packages/app-shell/src/context/ packages/app-shell/src/console/__tests__/ packages/app-shell/src/console/ai/__tests__/(under the verify lock)Test Files 193 passed (193),Tests 2096 passed, 13 skippedpnpm --workspace-concurrency=2 --filter "@object-ui/app-shell^..." buildpnpm --filter @object-ui/app-shell type-check(bothtsclegs)tsconfig.test.json --listFilesOnlylists the new pinpnpm --filter @object-ui/i18n type-checkeslintover the 6 changed app-shell files,--format jsonc3623eb(read through--stdin). The +2 arereact-refresh/only-export-componentson the two exported AI-page descriptorseslintover the 12 changed i18n files,--format jsoncheck:i18n-keyscheck:i18n-driftenvalues changed; 7 keys removedcheck:i18n-dead-keys(report-only)console.shortcuts.*candidates; pack keys 3273check:i18n-designer-parity,check:control-bytes,check:new-line-citations(0 new),check:vi-mock-specifiers,check:vi-mock-inherit,check:vi-mock-override-shape,check:unreferenced-sources,check:test-path-roots,check:changeset-claims,check:pending-changeset-literalsnode scripts/check-changeset-no-major.mjs,check-changeset-presence.mjs(18 source files, 2 packages, 1 changeset),check-changeset-fixed.mjscheck:readme-exportsdist. No export moved, and the new README section has no fenced importcheck:eager-locale-cataloguesapps/console/dist/eager-closure.jsonWhy the lint narrowing holds:
lintscript,eslint ..eslint.config.jssets noparserOptions.projectorprojectService, so no lint is type-aware.eslint-rules/reads another file.So this diff cannot change the verdict on a file it did not touch. The full
pnpm test, repo-widepnpm lintand theapps/consolesuites are left to CI.Declared narrowing: the verify lock was held for about 26 minutes by a sibling's full-suite run. During that time the single pin file, and the ablations, ran without the lock (
--maxWorkers=1). The final runs in the table above went through the lock.Acceptance notes (observations, not filed)
⌘⇧I, the chat-dock toggle inConsoleLayout, is wired and not advertised. A row needs a newconsole.shortcuts.*key in ten packs. That is a widening, outside this claim'sClause-②: no. With this mechanism it costs oneuseAdvertiseShortcutcall and the key. Carrier: none.⌘⇧M, the resource editor's⌘S/⌘\/Esc, the approvals inbox's list keys, the performance panel'sCtrl+Shift+P, anduseDebugMode'sCtrl+Shift+D. Once advertised, each would be listed only on its own page. This PR reads "lists exactly the shortcuts that are wired" as "lists no shortcut that is not wired", plus the chrome layer that owned the old list.useKeyboardShortcuts,useCrudShortcutsandgetShortcutDescriptionsin@object-ui/reactare published and have zero callers. This is dead code, and wiring it is not this card's question.⌘on every platform, as before. Every advertised handler also accepts Ctrl./ai, and the/aiheader hides the Help-menu entry. So the AI pair is listed nowhere today. That is correct under the rule, and it is unchanged.SidebarProviderlistener does not skip editable targets, so⌘Binside a rich-text field may toggle the sidebar.Generated by Claude Code