DocMosaicdocs
Concepts

Keybindings

The built-in keyboard layer - undo/redo, nudge, delete, deselect. Fully overridable.

Editor.Root ships a built-in keyboard layer. Cmd/Ctrl+Z for undo, arrows to nudge the selected section, Delete to remove it, Escape to deselect - the conventions consumers expect from Figma, Notion, and every other doc-editing tool. The layer is fully overridable: tweak a single action, register alternates, or turn the whole thing off.

Default keymap

mod resolves to Cmd on macOS, Ctrl elsewhere - prefer it over hard-coded cmd/ctrl. Bindings are skipped while focus is inside an <input>, <textarea>, <select>, or anything contenteditable, so text fields like the document-name input stay typeable.

ActionDefault binding
Undomod+z
Redomod+shift+z, mod+y
Delete sectionDelete, Backspace
DeselectEscape
Nudge by 1ptArrowUp/Down/Left/Right
Nudge by 10ptShift+ArrowUp/Down/Left/Right
Show shortcutsmod+/

Nudge values are in points - see Unit system for why.

Show the active keymap with Editor.KeybindingHelp

Drop Editor.KeybindingHelp anywhere inside Editor.Root and mod+/ opens a Radix dialog listing every active binding, grouped by category (Edit, Selection, Movement, View) and rendered as <kbd> chips. The chips are platform-aware - on macOS, Ctrl elsewhere.

<Editor.Root>
    <Editor.Properties />
    <Editor.Toolbar />
    <Editor.Canvas>
        <Editor.Section />
    </Editor.Canvas>
    <Editor.KeybindingHelp />
</Editor.Root>

If you customise the keymap via Editor.Root keybindings, pass the same partial map to Editor.KeybindingHelp so the chips match the active runtime:

const myKeymap = { redo: 'mod+r' };

<Editor.Root keybindings={myKeymap}>
    <Editor.KeybindingHelp keymap={myKeymap} />
</Editor.Root>;

Override individual bindings

Pass a Partial<EditorKeymap> - anything omitted keeps its default. Use an array of strings to register alternates:

import { Editor } from '@docmosaic/react';

<Editor.Root
    keybindings={{
        redo: 'mod+r',
        deleteSection: ['Delete', 'Backspace', 'x'],
    }}
>
    {/* … */}
</Editor.Root>;

The matcher checks every binding for each action; first match wins. The shift-nudge variants (nudgeUpLarge, etc.) are matched before the plain arrow bindings so Shift+ArrowUp doesn't accidentally fire nudgeUp.

Disable all shortcuts

Pass false to skip mounting the window listener entirely:

<Editor.Root keybindings={false}>{/* … */}</Editor.Root>

Useful when your app already owns its own shortcut layer and you don't want two listeners fighting over the same events.

Building a custom keymap

Every field on EditorKeymap is optional. Combine multiple actions in one map:

import { Editor, type EditorKeymap } from '@docmosaic/react';

const myKeymap: Partial<EditorKeymap> = {
    undo: ['mod+z', 'mod+u'],
    redo: ['mod+shift+z', 'mod+y'],
    deselect: ['Escape', 'mod+d'],
    nudgeUpLarge: 'shift+ArrowUp',
};

<Editor.Root keybindings={myKeymap}>{/* … */}</Editor.Root>;

Token rules:

  • Modifiers: mod, shift, alt (or option), ctrl (or control), cmd/meta/command.
  • Non-modifier tokens are matched case-insensitively against KeyboardEvent.key - 'z', 'Escape', 'ArrowRight', 'Delete', 'Backspace'.
  • Tokens are joined with +: 'mod+shift+z'.

Standalone usage with useEditorKeybindings

The hook is exported separately for "BYO-UI" trees that mount their own provider. Render it anywhere inside an EditorProvider:

import { useEditorKeybindings, DEFAULT_KEYMAP } from '@docmosaic/react';

function MyShortcuts() {
    useEditorKeybindings({ redo: 'mod+r' });
    return null;
}

<Editor.Root>
    <MyShortcuts />
    <Editor.Properties />
    <Editor.Canvas>
        <Editor.Section />
    </Editor.Canvas>
</Editor.Root>;

DEFAULT_KEYMAP is exported too - useful when you want to spread the defaults into a derived keymap of your own.

Best practices

  • Don't fight the browser. mod+t, mod+w, mod+r and mod+l are common browser shortcuts; users react badly when an editor steals them.
  • Don't fight the OS. mod+Q, mod+H, mod+Tab belong to the platform.
  • Stay inside the conventions. mod+z/mod+shift+z for undo/redo. Escape for cancel. Arrows for nudge. Users have muscle memory - match it before inventing.
  • Register alternates rather than overriding. Adding 'x' to deleteSection keeps Delete and Backspace working - strictly safer than replacing them.

See also

  • Designer - selection model that nudge / delete operate on
  • Layers - z-index actions that could be bound to shortcuts in the future