Skip to main content
AppFlowy Editor provides a powerful shortcut system that allows you to define custom keyboard shortcuts and character-triggered events. You can create shortcuts for text formatting, block transformations, and custom behaviors.

Overview

There are two types of shortcut events:
  • CharacterShortcutEvent - Triggered when specific characters are typed
  • CommandShortcutEvent - Triggered by keyboard combinations (Ctrl/Cmd + key)

Character shortcut events

CharacterShortcutEvent allows you to trigger actions when users type specific characters. This is perfect for markdown-style formatting.

Basic example: Underscore to italic

Here’s an example that converts _text_ to italic formatting:
import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:flutter/material.dart';

CharacterShortcutEvent underscoreToItalicEvent = CharacterShortcutEvent(
  key: 'Underscore to italic',
  character: '_',
  handler: (editorState) async => handleFormatByWrappingWithSingleCharacter(
    editorState: editorState,
    character: '_',
    formatStyle: FormatStyleByWrappingWithSingleChar.italic,
  ),
);
Source: documentation/customizing.md:44-52

Applying character shortcuts

Inject your custom shortcuts into the editor:
class UnderScoreToItalic extends StatelessWidget {
  const UnderScoreToItalic({super.key});

  @override
  Widget build(BuildContext context) {
    return AppFlowyEditor.custom(
      editorState: EditorState.blank(withInitialText: true),
      blockComponentBuilders: standardBlockComponentBuilderMap,
      characterShortcutEvents: [
        underScoreToItalicEvent,
        // Add more character shortcuts here
      ],
    );
  }
}
Source: documentation/customizing.md:61-74

Built-in character shortcuts

AppFlowy Editor includes many built-in character shortcuts:
  • # - Convert to heading 1
  • ## - Convert to heading 2
  • ### - Convert to heading 3
  • * or - - Convert to bulleted list
  • 1. - Convert to numbered list
  • > - Convert to quote
  • **text** - Bold formatting
  • *text* - Italic formatting
  • `code` - Code formatting
  • --- - Insert divider
See the CharacterShortcutEvent API for more examples.

Command shortcut events

CommandShortcutEvent handles keyboard combinations like Ctrl+B for bold or Cmd+Z for undo.

Creating command shortcuts

import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

CommandShortcutEvent customBoldShortcut = CommandShortcutEvent(
  key: 'Toggle bold',
  command: 'ctrl+b',
  macOSCommand: 'cmd+b',
  handler: (editorState) {
    final selection = editorState.selection;
    if (selection == null || selection.isCollapsed) {
      return KeyEventResult.ignored;
    }

    editorState.toggleAttribute(
      AppFlowyRichTextKeys.bold,
    );

    return KeyEventResult.handled;
  },
);

Platform-specific shortcuts

Define different shortcuts for different platforms:
CommandShortcutEvent(
  key: 'Save document',
  command: 'ctrl+s',        // Windows/Linux
  macOSCommand: 'cmd+s',    // macOS
  handler: (editorState) {
    // Save logic here
    return KeyEventResult.handled;
  },
)

Applying command shortcuts

AppFlowyEditor.custom(
  editorState: editorState,
  blockComponentBuilders: standardBlockComponentBuilderMap,
  commandShortcutEvents: [
    customBoldShortcut,
    // Add more command shortcuts
  ],
)

Advanced patterns

Multi-character triggers

You can create shortcuts that trigger on multiple characters:
CharacterShortcutEvent(
  key: 'Smart quotes',
  character: '"',
  handler: (editorState) async {
    // Replace straight quotes with smart quotes
    final selection = editorState.selection;
    if (selection == null) {
      return false;
    }
    // Implementation here
    return true;
  },
)

Conditional shortcuts

Make shortcuts context-aware:
CommandShortcutEvent(
  key: 'Indent list item',
  command: 'tab',
  handler: (editorState) {
    final selection = editorState.selection;
    if (selection == null) {
      return KeyEventResult.ignored;
    }

    final node = editorState.getNodeAtPath(selection.start.path);
    if (node == null) {
      return KeyEventResult.ignored;
    }

    // Only indent if it's a list item
    if (node.type == BulletedListBlockKeys.type ||
        node.type == NumberedListBlockKeys.type) {
      // Indent logic
      return KeyEventResult.handled;
    }

    return KeyEventResult.ignored;
  },
)
Shortcut events are evaluated in the order they’re added to the list. If a handler returns true or KeyEventResult.handled, subsequent shortcuts won’t be evaluated.

Combining with standard shortcuts

You can combine your custom shortcuts with the built-in ones:
final customShortcuts = [
  underscoreToItalicEvent,
  customBoldShortcut,
];

AppFlowyEditor.custom(
  editorState: editorState,
  blockComponentBuilders: standardBlockComponentBuilderMap,
  characterShortcutEvents: [
    ...standardCharacterShortcutEvents,
    ...customShortcuts,
  ],
  commandShortcutEvents: [
    ...standardCommandShortcutEvents,
    customBoldShortcut,
  ],
)
Be careful not to override important system shortcuts (like Ctrl+C for copy) unless you have a specific reason to do so.

CharacterShortcutEvent API

Complete API reference for character shortcuts

CommandShortcutEvent API

Complete API reference for command shortcuts

Build docs developers (and LLMs) love