Skip to content

Comments

ENG-1438: Port Keyboard shortcut keys/triggers settings#794

Merged
sid597 merged 1 commit intoeng-1217-page-groups-left-sidebarfrom
eng-1438-keyboard-quick-shortcut-keystriggers
Feb 23, 2026
Merged

ENG-1438: Port Keyboard shortcut keys/triggers settings#794
sid597 merged 1 commit intoeng-1217-page-groups-left-sidebarfrom
eng-1438-keyboard-quick-shortcut-keystriggers

Conversation

@sid597
Copy link
Collaborator

@sid597 sid597 commented Feb 17, 2026

https://www.loom.com/share/c49cc82577c847368c521e0a7680fc5e


Open with Devin

Summary by CodeRabbit

  • Refactor
    • Enhanced keyboard shortcut handling and persistence for menu and tool triggers.
    • Restructured keyboard shortcut configuration storage format for improved consistency and validation.
    • Streamlined shortcut input components to use normalized key combination representations.

@linear
Copy link

linear bot commented Feb 17, 2026

@supabase
Copy link

supabase bot commented Feb 17, 2026

This pull request has been ignored for the connected project zytfjzqyijgagqxrzbmz because there are no changes detected in packages/database/supabase directory. You can change this behaviour in Project Integrations Settings ↗︎.


Preview Branches by Supabase.
Learn more about Supabase Branching ↗︎.

devin-ai-integration[bot]

This comment was marked as resolved.

@sid597 sid597 changed the base branch from eng-1217-page-groups-left-sidebar to graphite-base/794 February 17, 2026 14:56
@sid597 sid597 changed the base branch from graphite-base/794 to eng-1440-port-page-groups-settings-in-suggestive-mode February 17, 2026 14:56
@sid597 sid597 force-pushed the eng-1438-keyboard-quick-shortcut-keystriggers branch from 6272ec7 to fdb14fe Compare February 17, 2026 15:07
Copy link
Contributor

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 new potential issue.

View 11 additional findings in Devin Review.

Open in Devin Review

@sid597 sid597 changed the base branch from eng-1440-port-page-groups-settings-in-suggestive-mode to graphite-base/794 February 17, 2026 15:16
@sid597 sid597 force-pushed the eng-1438-keyboard-quick-shortcut-keystriggers branch from fdb14fe to 179b9e3 Compare February 17, 2026 15:16
@sid597 sid597 changed the base branch from graphite-base/794 to eng-1217-page-groups-left-sidebar February 17, 2026 15:17
@sid597 sid597 force-pushed the eng-1217-page-groups-left-sidebar branch from ac0a069 to 547a44d Compare February 17, 2026 15:37
@sid597 sid597 force-pushed the eng-1438-keyboard-quick-shortcut-keystriggers branch 2 times, most recently from 1be546e to f4cc95b Compare February 17, 2026 15:47
@sid597 sid597 force-pushed the eng-1217-page-groups-left-sidebar branch from 01ef4ec to 8c85845 Compare February 17, 2026 16:04
@sid597 sid597 force-pushed the eng-1438-keyboard-quick-shortcut-keystriggers branch from f4cc95b to 75bb8c1 Compare February 17, 2026 16:04
@sid597
Copy link
Collaborator Author

sid597 commented Feb 17, 2026

@coderabbitai full review

@sid597 sid597 requested a review from mdroidian February 17, 2026 16:11
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 17, 2026

✅ Actions performed

Full review triggered.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 17, 2026

📝 Walkthrough

Walkthrough

The pull request refactors keyboard shortcut handling to use a structured data format with modifiers and key properties instead of plain strings, adds persistence of shortcuts via personal settings storage, and centralizes shortcut string generation through a new comboToString() utility function.

Changes

Cohort / File(s) Summary
Keyboard Shortcut Utilities
apps/roam/src/components/DiscourseNodeMenu.tsx
Added comboToString() utility function to normalize key combo objects into readable shortcut strings; refactored shortcut generation and state management to use this utility.
Node Menu Persistence
apps/roam/src/components/DiscourseNodeMenu.tsx
Extended onKeyDown handler to store combo in state and persist via both extensionAPI.settings.set() and setPersonalSetting() calls; updated clear button to persist empty values.
Node Search Menu Persistence
apps/roam/src/components/DiscourseNodeSearchMenu.tsx
Added setPersonalSetting() call in NodeSearchMenuTriggerSetting onChange handler to persist trigger changes alongside extension settings updates.
Keyboard Shortcut Input Refactor
apps/roam/src/components/settings/KeyboardShortcutInput.tsx
Introduced blockPropKey prop to enable per-setting persistence; replaced custom normalization logic with comboToString() utility; added setPersonalSetting() calls in all modification paths (set, clear, keydown).
Shortcut Settings Configuration
apps/roam/src/components/settings/HomePersonalSettings.tsx
Added blockPropKey prop assignment to KeyboardShortcutInput component during rendering.
Schema Type Updates
apps/roam/src/components/settings/utils/zodSchema.ts, apps/roam/src/components/settings/utils/zodSchema.example.ts
Changed structure of shortcut fields (Personal node menu trigger, Discourse tool shortcut) from plain strings to objects with { modifiers: number; key: string } shape; updated schema validation and default values to match new structure.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main objective of the PR: porting keyboard shortcut keys/triggers settings. This directly aligns with the comprehensive changes across multiple components and schema files.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
apps/roam/src/components/settings/utils/zodSchema.ts (1)

233-242: Asymmetric schema for the two shortcut fields — is the union on "Personal node menu trigger" intentional?

"Personal node menu trigger" accepts z.union([object, z.literal("")]) while "Discourse tool shortcut" only accepts the object shape. This means consumers of "Personal node menu trigger" must do a type-narrowing check (typeof value === "string") before accessing .modifiers / .key, which is easy to miss and could cause runtime errors.

If the empty-string variant is for backward compatibility with previously stored string values, consider using .transform() to normalize "" into { modifiers: 0, key: "" } at parse time so the output type is always uniform. If this asymmetry is intentional (the two fields genuinely have different semantics), a brief comment explaining why would help future readers.

Example normalization
   "Personal node menu trigger": z
     .union([
       z.object({ modifiers: z.number(), key: z.string() }),
       z.literal(""),
     ])
-    .default({ modifiers: 0, key: "" }),
+    .default({ modifiers: 0, key: "" })
+    .transform((val) => (val === "" ? { modifiers: 0, key: "" } : val)),

This way the inferred type is always { modifiers: number; key: string }, matching "Discourse tool shortcut".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/roam/src/components/settings/utils/zodSchema.ts` around lines 233 - 242,
The "Personal node menu trigger" schema currently uses z.union([z.object(...),
z.literal("")]) which produces an inconsistent output type vs the "Discourse
tool shortcut" object; change the schema so the parsed output is always the
object shape (matching "Discourse tool shortcut") by handling the empty-string
legacy case with a transform or preprocess: accept the union but .transform()
(or z.preprocess) to map "" to { modifiers: 0, key: "" } so downstream consumers
of "Personal node menu trigger" can safely access .modifiers and .key without
type-narrowing; alternatively make both schemas identical objects if no legacy
string values must be supported, and add a short comment explaining the chosen
approach.
apps/roam/src/components/DiscourseNodeMenu.tsx (1)

410-415: Consider extracting comboToString (and related helpers) to a shared utility file.

comboToString, getModifiersFromCombo, normalizeKeyCombo, and the modifier/alias constants are pure utility logic with no component dependencies. Exporting them from DiscourseNodeMenu.tsx forces KeyboardShortcutInput.tsx (a settings component) to import from a menu component, creating an awkward cross-concern coupling.

Moving these to e.g. ~/utils/keyComboUtils.ts would improve module boundaries and make it easier to reuse across additional settings components.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/roam/src/components/DiscourseNodeMenu.tsx` around lines 410 - 415,
Extract the pure utility logic from DiscourseNodeMenu.tsx into a shared module
(e.g., create ~/utils/keyComboUtils.ts): move comboToString,
getModifiersFromCombo, normalizeKeyCombo and the modifier/alias constants into
that file and export them, then update DiscourseNodeMenu.tsx and
KeyboardShortcutInput.tsx to import these helpers from the new utils module;
ensure exports keep the same names/signatures so no other call sites need
changes.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/roam/src/components/DiscourseNodeMenu.tsx`:
- Around line 460-464: The onClick clear handler uses an empty string "" for
extensionAPI.settings.set and setPersonalSetting but elsewhere
(KeyboardShortcutInput.handleClear) clears with the structured object {
modifiers: 0, key: "" }, causing validation and type inconsistencies; update the
onClick handler to persist the same structured object ({ modifiers: 0, key: ""
}) to extensionAPI.settings.set and setPersonalSetting and keep setComboKey({
modifiers: 0, key: "" }) so the clear behavior is consistent with
KeyboardShortcutInput.handleClear.

In `@apps/roam/src/components/DiscourseNodeSearchMenu.tsx`:
- Around line 631-632: The code writes the trigger to two different keys
(extensionAPI.settings.set("node-search-trigger", ...) and
setPersonalSetting(["Node search menu trigger"], ...)) while reads only use
getSetting("node-search-trigger", "@"), risking divergence; fix by consolidating
to a single canonical store: remove the redundant setPersonalSetting call and
persist only via extensionAPI.settings.set("node-search-trigger", trigger), or
if you must keep both, update read logic (where
getSetting("node-search-trigger", "@") is used) to also read and merge the
personal setting with a clear precedence. Ensure references to
setPersonalSetting and extensionAPI.settings.set are consistent and update any
docs/tests accordingly.

---

Nitpick comments:
In `@apps/roam/src/components/DiscourseNodeMenu.tsx`:
- Around line 410-415: Extract the pure utility logic from DiscourseNodeMenu.tsx
into a shared module (e.g., create ~/utils/keyComboUtils.ts): move
comboToString, getModifiersFromCombo, normalizeKeyCombo and the modifier/alias
constants into that file and export them, then update DiscourseNodeMenu.tsx and
KeyboardShortcutInput.tsx to import these helpers from the new utils module;
ensure exports keep the same names/signatures so no other call sites need
changes.

In `@apps/roam/src/components/settings/utils/zodSchema.ts`:
- Around line 233-242: The "Personal node menu trigger" schema currently uses
z.union([z.object(...), z.literal("")]) which produces an inconsistent output
type vs the "Discourse tool shortcut" object; change the schema so the parsed
output is always the object shape (matching "Discourse tool shortcut") by
handling the empty-string legacy case with a transform or preprocess: accept the
union but .transform() (or z.preprocess) to map "" to { modifiers: 0, key: "" }
so downstream consumers of "Personal node menu trigger" can safely access
.modifiers and .key without type-narrowing; alternatively make both schemas
identical objects if no legacy string values must be supported, and add a short
comment explaining the chosen approach.

Copy link
Contributor

@mdroidian mdroidian left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's go!

One devin comment worth looking into. Can defer, not blocking.

@sid597 sid597 merged commit d9a05d4 into eng-1217-page-groups-left-sidebar Feb 23, 2026
10 of 11 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