Loading...

Postulate is the best way to take and share notes for classes, research, and other learning.

More info

How to Add Custom Keyboard Shortcuts in Slate-Plugins

Profile picture of Samson ZhangSamson Zhang
Apr 14, 2021Last updated Apr 15, 20212 min read

While building the editor for Postulate, I wanted users to be able to add links with the shortcut Ctrl+K. Unlike marks, for some reason this fairly standard shortcut is not built into the default link plugin, so I went about implementing it myself.

I looked into createBoldPlugin to see how it creates a Ctrl+B shortcut for adding bold marks. Turns out, all that createBoldPlugin does is return an object of the type SlatePlugin:

export const createBoldPlugin = (): SlatePlugin => ({ pluginKeys: MARK_BOLD, renderLeaf: getRenderLeaf(MARK_BOLD), deserialize: getBoldDeserialize(), onKeyDown: getToggleMarkOnKeyDown(MARK_BOLD), });

And right at the bottom is onKeyDown! getToggleMarkOnKeyDown looks like this:

export const getToggleMarkOnKeyDown = (pluginKey: string): OnKeyDown => ( editor ) => (e) => { const { hotkey, type, clear } = getSlatePluginOptions(editor, pluginKey); if (!hotkey) return; if (isHotkey(hotkey, e)) { e.preventDefault(); toggleMark(editor, type, clear); } };

There's a little more going on here, but what's returned is a function editor => e => { ...whatever you want }, where e => { ...whatever you want } is added to Slate's onKeyDown handler.

To add your own keyboard shortcut, then, all you need to do is add a new object with an onKeyDown function to your plugins list:

const plugins = [ ... { onKeydown: editor => e => { if (isHotkey("YOUR HOTKEY", e)) { // WHATEVER YOU WANT } } } ];

Use this for whatever shortcut, with whatever functionality, you want! For my Ctrl+K to link shortcut, the custom mini-plugin looks like this:

const plugins = [ ... { onKeydown: editor => e => { if (isHotkey("mod+k", e)) { e.preventDefault(); const type = getSlatePluginType(editor, ELEMENT_LINK); const isLink = someNode(editor, { match: { type } }); // if there is a link at the cursor, get rid of the link if (isLink) unwrapNodes(editor, {at: editor.selection, match: {type: getSlatePluginType(editor, ELEMENT_LINK)}}); // else if there is a selection, not just a point, create a link on that selection else if (editor.selection.anchor !== editor.selection.focus) { // taken from ToolbarLink.tsx with modifications const url = normalizeUrl(window.prompt(`Enter the URL of the link:`)); if (url) { upsertLinkAtSelection(editor, { url, wrap: true }); } } } } } ];


Comments (loading...)

Sign in to comment

Postulate

Founder and dev notes from building Postulate