Skip to main content
The selection menu (also known as the slash command menu) appears when you type / in the editor. It provides quick access to block transformations and insertions.

Overview

The selection menu provides:
  • Quick block insertion (headings, lists, quotes, etc.)
  • Block transformations
  • Custom menu items
  • Keyboard navigation

Default selection menu

By default, the selection menu includes:
  • Text blocks: Paragraph, Headings (H1-H3)
  • Lists: Bulleted list, Numbered list, Todo list
  • Media: Image
  • Advanced: Quote, Divider, Code block, Table

Customizing menu items

You can customize which items appear in the selection menu:
import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:flutter/material.dart';

final customSelectionMenuItems = [
  // Headings
  SelectionMenuItem.node(
    name: 'Heading 1',
    iconData: Icons.h_mobiledata,
    keywords: ['heading', 'h1'],
    nodeBuilder: (editorState, _) => headingNode(level: 1),
    replace: true,
  ),
  
  // Lists
  SelectionMenuItem.node(
    name: 'Bulleted List',
    iconData: Icons.list,
    keywords: ['bulleted', 'list', 'ul'],
    nodeBuilder: (editorState, _) => bulletedListNode(),
    replace: true,
  ),
  
  // Custom item
  SelectionMenuItem.node(
    name: 'Callout',
    iconData: Icons.info,
    keywords: ['callout', 'info'],
    nodeBuilder: (editorState, _) => calloutNode(),
    replace: true,
  ),
];

Creating custom menu items

Create custom menu items for your block types:
import 'package:appflowy_editor/appflowy_editor.dart';

final customBlockMenuItem = SelectionMenuItem(
  name: 'Custom Block',
  icon: (editorState, isSelected, style) => SelectionMenuIcon(
    icon: Icons.extension,
    isSelected: isSelected,
    style: style,
  ),
  keywords: ['custom', 'block'],
  handler: (editorState, menuService, context) {
    final selection = editorState.selection;
    if (selection == null) {
      return;
    }

    // Create and insert your custom block
    final node = Node(
      type: 'custom_block',
      attributes: {
        'content': '',
      },
    );

    final transaction = editorState.transaction;
    transaction.insertNode(selection.start.path, node);
    transaction.afterSelection = Selection.collapsed(
      Position(path: selection.start.path.next),
    );
    editorState.apply(transaction);

    menuService.dismiss();
  },
);
There are different types of selection menu items:

Node-based items

Insert or replace with a new node:
SelectionMenuItem.node(
  name: 'Quote',
  iconData: Icons.format_quote,
  keywords: ['quote', 'blockquote'],
  nodeBuilder: (editorState, _) => quoteNode(),
  replace: true,  // Replace current block
)

Action-based items

Execute custom actions:
SelectionMenuItem(
  name: 'Insert Date',
  icon: (editorState, isSelected, style) => SelectionMenuIcon(
    icon: Icons.calendar_today,
    isSelected: isSelected,
    style: style,
  ),
  keywords: ['date', 'today'],
  handler: (editorState, menuService, context) {
    final selection = editorState.selection;
    if (selection == null) return;

    final now = DateTime.now();
    final dateText = '${now.year}-${now.month}-${now.day}';

    editorState.insertTextAtCurrentSelection(dateText);
    menuService.dismiss();
  },
)

Applying custom menu

Apply your custom selection menu to the editor:
import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:flutter/material.dart';

class EditorWithCustomMenu extends StatelessWidget {
  const EditorWithCustomMenu({super.key});

  @override
  Widget build(BuildContext context) {
    return AppFlowyEditor(
      editorState: EditorState.blank(),
      // Custom selection menu items will be used
    );
  }
}
Customize the appearance of the selection menu:
final menuStyle = SelectionMenuStyle(
  backgroundColor: Colors.white,
  borderRadius: BorderRadius.circular(8.0),
  itemHeight: 40.0,
  itemIconSize: 18.0,
  itemIconPadding: const EdgeInsets.only(right: 8.0),
);

Keyboard navigation

The selection menu supports keyboard navigation:
  • ↑/↓ Arrow keys: Navigate menu items
  • Enter: Select highlighted item
  • Escape: Close menu
  • Type to filter: Items are filtered as you type

Filtering items

Menu items are automatically filtered based on:
  • Item name
  • Keywords
  • User input after /
For example, typing /h1 will show heading-related items.

Custom slash trigger

You can customize the trigger character:
// Use a different character to trigger the menu
CharacterShortcutEvent(
  key: 'Show selection menu',
  character: '@',  // Use @ instead of /
  handler: (editorState) async {
    // Show selection menu
    return true;
  },
)
The selection menu is triggered by the / character by default. Users can type to filter menu items and use arrow keys to navigate.

Disabling selection menu

To disable the selection menu:
AppFlowyEditor.custom(
  editorState: editorState,
  blockComponentBuilders: standardBlockComponentBuilderMap,
  characterShortcutEvents: [
    // Remove slash menu shortcut from the list
    ...standardCharacterShortcutEvents.where(
      (event) => event.key != 'Show selection menu',
    ),
  ],
)

Shortcut Events

Create custom keyboard shortcuts

Custom Blocks

Build custom block components

Build docs developers (and LLMs) love