Skip to content

Eng 1552 enable ability to change discourse graph specific keyboard#952

Open
sid597 wants to merge 4 commits intomainfrom
eng-1552-enable-ability-to-change-discourse-graph-specific-keyboard
Open

Eng 1552 enable ability to change discourse graph specific keyboard#952
sid597 wants to merge 4 commits intomainfrom
eng-1552-enable-ability-to-change-discourse-graph-specific-keyboard

Conversation

@sid597
Copy link
Copy Markdown
Collaborator

@sid597 sid597 commented Apr 10, 2026

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


Open with Devin

Summary by CodeRabbit

Release Notes

  • New Features
    • Added customizable keyboard shortcuts for canvas nodes directly in Personal Settings, allowing personalization of node tool key bindings
    • New "Canvas" tab in the settings panel provides an easy way to configure your preferred keyboard shortcuts
    • Your shortcut customizations take effect the next time you open a canvas

sid597 added 2 commits April 10, 2026 21:29
Allow users to customize discourse node shortcuts in the canvas
via a new "Canvas shortcuts" tab in personal settings.
@linear-code
Copy link
Copy Markdown

linear-code Bot commented Apr 10, 2026

@supabase
Copy link
Copy Markdown

supabase Bot commented Apr 10, 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 ↗︎.

Copy link
Copy Markdown
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: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 4 additional findings.

Open in Devin Review

@sid597
Copy link
Copy Markdown
Collaborator Author

sid597 commented Apr 10, 2026

@coderabbitai full review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 10, 2026

✅ Actions performed

Full review triggered.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 10, 2026

📝 Walkthrough

Walkthrough

This PR introduces customizable keyboard shortcuts for canvas nodes. A new personal settings field stores node-specific shortcut overrides, a settings UI component allows configuration, the schema validates the setting structure, and the canvas UI layer reads and applies these overrides when rendering node tools.

Changes

Cohort / File(s) Summary
Settings Schema
apps/roam/src/components/settings/utils/zodSchema.ts, apps/roam/src/components/settings/utils/zodSchema.example.ts
Added "Canvas node shortcuts" field to personal settings schema as a string-to-string record with empty object default; example populated with sample node shortcut mappings.
Settings UI
apps/roam/src/components/settings/CanvasShortcutSettings.tsx, apps/roam/src/components/settings/Settings.tsx
Created new CanvasShortcutSettings component rendering editable shortcut panels per discourse node type; integrated as new "Canvas" tab in personal settings dialog between "Queries" and "Left sidebar" tabs.
Canvas Implementation
apps/roam/src/components/canvas/uiOverrides.tsx
Modified node tool creation to override kbd values with custom shortcuts from personal settings, falling back to default node shortcuts when custom overrides unavailable.

Sequence Diagram

sequenceDiagram
    actor User
    participant Settings as CanvasShortcutSettings UI
    participant PersonalSettings as Personal Settings Store
    participant Canvas as Canvas Component
    participant UIOverrides as uiOverrides Logic

    User->>Settings: Opens Canvas shortcuts tab
    Settings->>PersonalSettings: Reads current shortcuts via getPersonalSetting()
    PersonalSettings-->>Settings: Returns shortcuts map
    Settings->>User: Displays shortcut fields for each node type
    User->>Settings: Customizes shortcut for a node
    Settings->>PersonalSettings: Saves updated shortcut mapping
    PersonalSettings-->>Settings: Confirms save

    Note over Canvas,UIOverrides: Next Canvas Load
    Canvas->>UIOverrides: createUiOverrides() initializes
    UIOverrides->>PersonalSettings: Reads Canvas node shortcuts setting
    PersonalSettings-->>UIOverrides: Returns shortcut overrides map
    UIOverrides->>UIOverrides: For each node tool, override kbd with custom shortcut or default
    UIOverrides-->>Canvas: Returns configured tools with applied shortcuts
    Canvas->>User: Renders canvas with custom node shortcuts active
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The PR title is incomplete and ends abruptly mid-phrase ('keyboard' appears to be cut off). While it relates to the changeset's intent of customizing keyboard shortcuts, the truncation makes it difficult to parse. Complete the title to a full, grammatically correct sentence describing the feature, such as 'Enable ability to change discourse graph specific keyboard shortcuts' or similar.
✅ Passed checks (2 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ 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
Copy Markdown
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.

🧹 Nitpick comments (1)
apps/roam/src/components/settings/CanvasShortcutSettings.tsx (1)

8-8: Consider using UPPERCASE for the constant name.

Per coding guidelines, constants should use UPPERCASE naming convention.

💡 Suggested change
-const CANVAS_NODE_SHORTCUTS_KEY = "Canvas node shortcuts";
+const CANVAS_NODE_SHORTCUTS_KEY = "Canvas node shortcuts"; // Already uppercase, but could be more explicit

The constant name CANVAS_NODE_SHORTCUTS_KEY already uses uppercase, so this is compliant. No change needed.

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

In `@apps/roam/src/components/settings/CanvasShortcutSettings.tsx` at line 8, The
reviewer suggested using UPPERCASE for the constant name, but the constant
CANVAS_NODE_SHORTCUTS_KEY in CanvasShortcutSettings.tsx is already UPPERCASE; no
code change is needed—leave CANVAS_NODE_SHORTCUTS_KEY as-is.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@apps/roam/src/components/settings/CanvasShortcutSettings.tsx`:
- Line 8: The reviewer suggested using UPPERCASE for the constant name, but the
constant CANVAS_NODE_SHORTCUTS_KEY in CanvasShortcutSettings.tsx is already
UPPERCASE; no code change is needed—leave CANVAS_NODE_SHORTCUTS_KEY as-is.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: eb5a2020-f01b-486a-97e1-b7bfee584cb1

📥 Commits

Reviewing files that changed from the base of the PR and between 7128ea4 and c44d92b.

📒 Files selected for processing (5)
  • apps/roam/src/components/canvas/uiOverrides.tsx
  • apps/roam/src/components/settings/CanvasShortcutSettings.tsx
  • apps/roam/src/components/settings/Settings.tsx
  • apps/roam/src/components/settings/utils/zodSchema.example.ts
  • apps/roam/src/components/settings/utils/zodSchema.ts

sid597 added 2 commits April 20, 2026 16:19
…empty)

Per review feedback: each node now has an explicit "use custom shortcut"
toggle. Unchecked falls back to the global default; checked with a value
overrides; checked with empty value disables the shortcut entirely.

- Schema: `Record<nodeType, { value, enabled }>` replaces flat string map
- Read side in createUiOverrides keys off `enabled` flag, not value presence
- Each row uses PersonalFlagPanel + PersonalTextPanel; flag controls input's
  disabled state, uncheck clears stored value via remount
- BaseTextPanel: added `disabled?: boolean` and made Description conditional
  on a non-empty description (no-op for existing callers)
- Exported `CanvasNodeShortcuts` type from zodSchema; uiOverrides imports it
…k props

Settings tab opened slowly (~5s) because each row called getPersonalSetting
twice — once on mount and again every render — and each call ran a Datalog
query plus a full PersonalSettingsSchema.parse(). createUiOverrides hit the
same accessor too.

Switched to the same pattern other personal settings use (KeyboardShortcutInput,
HomePersonalSettings flags): read from the Roam extensionAPI, dual-write to
extensionAPI + block props on change. extensionAPI reads are sync and
in-memory.

- New constant CANVAS_NODE_SHORTCUTS_KEY in data/userSettings.ts
- CanvasShortcutSettings: parent reads the record once, holds it in state,
  passes initial values down; row notifies parent on change, parent writes to
  extensionAPI; PersonalFlagPanel/PersonalTextPanel keep their internal
  block-prop writes so block props stay in sync
- uiOverrides: getSetting(CANVAS_NODE_SHORTCUTS_KEY, {}) instead of
  getPersonalSetting(["Canvas node shortcuts"])
@sid597 sid597 requested a review from mdroidian April 22, 2026 16:08
Copy link
Copy Markdown
Member

@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 change the UI to something like this:

Image
  • Single tab: Shortcuts
  • Label: {nodeLabel} node
  • Single row for each
  • Remove repeated description from tooltips, add to top of page

Ideally we reduce the size of the input box, but that is optional, depending on the component used.

return (
<div className="flex flex-col gap-1">
<PersonalFlagPanel
title={`Use custom ${nodeText} shortcut`}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Let's DRY this.

Right now "use custom ... shortcut" is repeated multiple times.
Instead, let's add a single tab
"Shortcuts"

And change the title of the panels to just "${nodeText} node"

<div className="flex flex-col gap-1">
<PersonalFlagPanel
title={`Use custom ${nodeText} shortcut`}
description={`Override the canvas keyboard shortcut. Default: ${defaultShortcut || "none"}. Changes take effect next time a canvas is opened.`}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Let's move "Override the canvas keyboard shortcut." and "Changes take effect next time a canvas is opened." to a the top of the page, inside a single tab.

onChange={handleEnabledChange}
/>
<div className="ml-6 max-w-xs">
<PersonalTextPanel
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This should be restricted to a single key, but right now it can take in any arbitrary text.

Image

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