Actions and shortcuts
One declaration per command feeds the keyboard, the menus, the command palette and the shortcuts sheet. Add your own, rebind keys, and find conflicts.
An action is a command with a name, an optional shortcut, and a function to run. Every command in CanvasFlow is one: undo, duplicate, align left, zoom to fit, switch to the arrow tool.
The point of declaring commands this way is that you write each one once. The same declaration drives:
- the keyboard shortcut,
- the item in the main and context menus,
- the entry in the ⌘K command palette,
- the tooltip that teaches the shortcut,
- the shortcuts help sheet,
- and a conflict check that tells you when two actions claim the same keys.
Run an action#
editor.actions.run('align-left')
editor.actions.isEnabled('group') // false when fewer than two shapes are selected
editor.actions.shortcutText('duplicate') // '⌘D' on a Mac, 'Ctrl+D' elsewhere
Add your own#
const off = editor.actions.register({
id: 'insert-timestamp',
label: 'Insert timestamp',
kbd: 'mod+shift+t',
group: 'edit',
keywords: ['date', 'time', 'now'],
run(editor) {
const center = editor.screenToPage({ x: editor.state.viewport.w / 2, y: editor.state.viewport.h / 2 })
editor.createShape({ type: 'text', x: center.x, y: center.y, props: { text: new Date().toLocaleString() } })
},
})
It's immediately in the palette (search "time"), and ⇧⌘T works. off() removes it.
The fields#
| Field | What it does |
|---|---|
id |
Stable id, used by run, rebind and menus |
label |
What people read in menus and the palette |
kbd |
Shortcuts, comma separated: 'mod+z', 'v,1', 'mod+shift+z,mod+y' |
group |
Where it appears in the help sheet (edit, arrange, align, view…) |
icon |
Icon name for UI kits |
keywords |
Extra words the palette matches |
enabled(editor) |
Return false to disable it (and let its keys pass through to tools) |
checked(editor) |
For toggles: shows a check mark in menus |
readonlyOk |
Allow it in view mode |
hidden |
Keep it out of the palette |
run(editor, source) |
Do the work. source says where it came from: kbd, menu, context-menu, toolbar, palette or api |
Shortcut syntax#
modis ⌘ on Apple devices and Ctrl everywhere else. Use it instead of hard-coding either.- Combine with
+:mod+shift+g,alt+h. - Separate alternatives with
,:delete,backspace. - Keys match by their position on the keyboard when it makes sense, so shortcuts keep working on non-US layouts.
Rebind keys#
editor.actions.rebind('tool.draw', 'b') // B for brush
editor.actions.rebind('toggle-grid', undefined) // remove a shortcut
Check for conflicts#
for (const [keys, a, b] of editor.actions.conflicts()) {
console.warn(`${keys} is claimed by both ${a} and ${b}`)
}
CanvasFlow's own test suite runs this check on the defaults, so a release never ships two commands on one key.
Ship actions in a plugin#
Plugins can bring actions along with shapes and tools:
editor.use({
name: 'timestamps',
actions: [
{ id: 'insert-timestamp', label: 'Insert timestamp', kbd: 'mod+shift+t', run: (editor) => editor.selectAll() },
],
})
Default actions#
The full list, with every shortcut, is on the Keyboard shortcuts page.