Skip to main content
Block components in AppFlowy Editor are highly customizable. You can modify their appearance, behavior, and add custom functionality through the BlockComponentConfiguration class and custom builders.

Overview

Each block component can be customized through:
  • BlockComponentConfiguration - Controls padding, text styles, and placeholders
  • Custom builders - Replace default block components with custom implementations
  • Icon builders - Customize icons for list items, quotes, and other blocks

BlockComponentConfiguration

The BlockComponentConfiguration class provides common configuration options for block components:
final configuration = BlockComponentConfiguration(
  padding: (node) {
    if (HeadingBlockKeys.type == node.type) {
      return const EdgeInsets.symmetric(vertical: 30);
    }
    return const EdgeInsets.symmetric(vertical: 10);
  },
  textStyle: (node) {
    if (HeadingBlockKeys.type == node.type) {
      return const TextStyle(color: Colors.yellow);
    }
    return const TextStyle();
  },
  placeholderText: (node) {
    return 'Type something...';
  },
);
Source: documentation/customizing.md:168-182

Configuration options

padding
EdgeInsets Function(Node)
Controls the padding around the block component. Can be customized per node type.
textStyle
TextStyle Function(Node)
Defines the text style for the block. Can vary based on node type.
placeholderText
String Function(Node)
Sets the placeholder text when the block is empty.
placeholderTextStyle
TextStyle Function(Node)
Defines the style for placeholder text.
indentPadding
EdgeInsets Function(Node, TextDirection)
Controls padding for indented blocks, respecting text direction.
textAlign
TextAlign Function(Node)
Sets text alignment for blocks with text content.
Source: lib/src/editor/block_component/base_component/block_component_configuration.dart:10-73

Customizing specific block types

You can apply different configurations to different block types:
Map<String, BlockComponentBuilder> customBuilder() {
  final configuration = BlockComponentConfiguration(
    padding: (node) {
      if (HeadingBlockKeys.type == node.type) {
        return const EdgeInsets.symmetric(vertical: 30);
      }
      return const EdgeInsets.symmetric(vertical: 10);
    },
    textStyle: (node) {
      if (HeadingBlockKeys.type == node.type) {
        return const TextStyle(color: Colors.yellow);
      }
      return const TextStyle();
    },
  );

  return {
    ...standardBlockComponentBuilderMap,
    HeadingBlockKeys.type: HeadingBlockComponentBuilder(
      configuration: configuration,
    ),
    TodoListBlockKeys.type: TodoListBlockComponentBuilder(
      configuration: configuration,
      iconBuilder: (context, node) {
        final checked = node.attributes[TodoListBlockKeys.checked] as bool;
        return Icon(
          checked ? Icons.check_box : Icons.check_box_outline_blank,
          size: 20,
          color: Colors.white,
        );
      },
    ),
  };
}
Source: documentation/customizing.md:184-202

Customizing icons

Many block components support custom icon builders:

Bulleted lists

BulletedListBlockKeys.type: BulletedListBlockComponentBuilder(
  configuration: configuration,
  iconBuilder: (context, node) {
    return const Icon(
      Icons.circle,
      size: 20,
      color: Colors.green,
    );
  },
)
Source: documentation/customizing.md:204-213

Quote blocks

QuoteBlockKeys.type: QuoteBlockComponentBuilder(
  configuration: configuration,
  iconBuilder: (context, node) {
    return const EditorSvg(
      width: 20,
      height: 20,
      padding: EdgeInsets.only(right: 5.0),
      name: 'quote',
      color: Colors.pink,
    );
  },
)
Source: documentation/customizing.md:215-226

Todo lists

TodoListBlockKeys.type: TodoListBlockComponentBuilder(
  configuration: configuration,
  iconBuilder: (context, node) {
    final checked = node.attributes[TodoListBlockKeys.checked] as bool;
    return Icon(
      checked ? Icons.check_box : Icons.check_box_outline_blank,
      size: 20,
      color: Colors.white,
    );
  },
)
Source: documentation/customizing.md:192-202

Applying custom configuration

Once you’ve defined your custom builders, apply them to the editor:
@override
Widget build(BuildContext context) {
  return Scaffold(
    body: Container(
      alignment: Alignment.topCenter,
      child: AppFlowyEditor(
        editorState: EditorState.blank(),
        blockComponentBuilders: customBuilder(),
      ),
    ),
  );
}
Source: documentation/customizing.md:234-246
When customizing block components, always include the standardBlockComponentBuilderMap as a base and override only the components you want to customize. This ensures all standard block types remain functional.

Custom Blocks

Learn how to create entirely new block types

Block Component API

Complete API reference for BlockComponentConfiguration

Build docs developers (and LLMs) love