Skip to main content

Overview

Heading blocks provide hierarchical document structure with six levels (H1-H6). Each level has distinct styling and semantic meaning.

Block Keys

class HeadingBlockKeys {
  static const String type = 'heading';
  static const String level = 'level';  // 1-6
  static const String delta = blockComponentDelta;
  static const String backgroundColor = blockComponentBackgroundColor;
  static const String textDirection = blockComponentTextDirection;
}
Source: /lib/src/editor/block_component/heading_block_component/heading_block_component.dart:6

Creating Heading Nodes

Use the headingNode() helper function:
// H1 heading
final h1 = headingNode(
  level: 1,
  text: 'Main Title',
);

// H2 heading with rich text
final h2 = headingNode(
  level: 2,
  delta: Delta()
    ..insert('Chapter 1: ')
    ..insert('Introduction', attributes: {'italic': true}),
);

// H3 with RTL text
final h3 = headingNode(
  level: 3,
  text: 'عنوان',
  textDirection: 'rtl',
);

// H4 with custom attributes
final h4 = headingNode(
  level: 4,
  text: 'Section Title',
  attributes: {
    'backgroundColor': '0xFFF0F0F0',
  },
);
The level must be between 1 and 6. Values outside this range will be clamped.
Source: /lib/src/editor/block_component/heading_block_component/heading_block_component.dart:23

Component Builder

Create a heading component with custom styling:
final headingBuilder = HeadingBlockComponentBuilder(
  configuration: BlockComponentConfiguration(
    padding: (node) => const EdgeInsets.symmetric(
      vertical: 8.0,
    ),
    placeholderText: (node) {
      final level = node.attributes[HeadingBlockKeys.level] ?? 1;
      return 'Heading $level';
    },
  ),
  textStyleBuilder: (level) {
    // Custom text styles for each level
    final fontSizes = {
      1: 32.0,
      2: 28.0,
      3: 24.0,
      4: 20.0,
      5: 18.0,
      6: 16.0,
    };
    
    return TextStyle(
      fontSize: fontSizes[level] ?? 16.0,
      fontWeight: FontWeight.bold,
      height: 1.2,
    );
  },
);
Source: /lib/src/editor/block_component/heading_block_component/heading_block_component.dart:43

Default Text Styles

The default heading styles are:
TextStyle? defaultTextStyle(int level) {
  final fontSizes = [32.0, 28.0, 24.0, 18.0, 18.0, 18.0];
  final fontSize = fontSizes.elementAtOrNull(level) ?? 18.0;

  return TextStyle(
    fontSize: fontSize,
    fontWeight: FontWeight.bold,
  );
}
LevelFont SizeWeight
H132.0Bold
H228.0Bold
H324.0Bold
H418.0Bold
H518.0Bold
H618.0Bold
Source: /lib/src/editor/block_component/heading_block_component/heading_block_component.dart:209

Widget Structure

class HeadingBlockComponentWidget extends BlockComponentStatefulWidget {
  const HeadingBlockComponentWidget({
    super.key,
    required super.node,
    super.showActions,
    super.actionBuilder,
    super.actionTrailingBuilder,
    super.configuration = const BlockComponentConfiguration(),
    this.textStyleBuilder,
  });

  /// Custom text style builder for different heading levels
  final TextStyle Function(int level)? textStyleBuilder;
}
Source: /lib/src/editor/block_component/heading_block_component/heading_block_component.dart:74

Mixins Used

class _HeadingBlockComponentWidgetState
    extends State<HeadingBlockComponentWidget>
    with
        SelectableMixin,
        DefaultSelectableMixin,
        BlockComponentConfigurable,
        BlockComponentBackgroundColorMixin,
        BlockComponentTextDirectionMixin,
        BlockComponentAlignMixin
Functionality:
  • Text selection and editing
  • Background color support
  • Text direction (LTR/RTL)
  • Text alignment
Source: /lib/src/editor/block_component/heading_block_component/heading_block_component.dart:93

Text Rendering

Headings use flexible layout to accommodate varying text lengths:
Widget child = Container(
  width: double.infinity,
  alignment: alignment,
  child: Row(
    mainAxisSize: MainAxisSize.min,
    crossAxisAlignment: CrossAxisAlignment.start,
    mainAxisAlignment: MainAxisAlignment.start,
    textDirection: textDirection,
    children: [
      Flexible(
        child: AppFlowyRichText(
          key: forwardKey,
          delegate: this,
          node: widget.node,
          editorState: editorState,
          textAlign: alignment?.toTextAlign ?? textAlign,
          textSpanDecorator: (textSpan) {
            var result = textSpan.updateTextStyle(
              textStyleWithTextSpan(textSpan: textSpan),
            );
            result = result.updateTextStyle(
              widget.textStyleBuilder?.call(level) ??
                  defaultTextStyle(level),
            );
            return result;
          },
          // ... more configuration
        ),
      ),
    ],
  ),
);
Source: /lib/src/editor/block_component/heading_block_component/heading_block_component.dart:130

Markdown Shortcuts

Headings support markdown-style shortcuts:
# Heading 1
## Heading 2
### Heading 3
#### Heading 4
##### Heading 5
###### Heading 6
Type # followed by a space to create headings:
  • # → H1
  • ## → H2
  • ### → H3
  • #### → H4
  • ##### → H5
  • ###### → H6

Keyboard Shortcuts

Toggle heading levels with shortcuts:
// Example: Ctrl+Alt+1 for H1, Ctrl+Alt+2 for H2, etc.
toggleHeadingCommands  // Part of standard command shortcuts

Using in Editor

Add heading support to your editor:
AppFlowyEditor(
  editorState: editorState,
  blockComponentBuilders: {
    HeadingBlockKeys.type: HeadingBlockComponentBuilder(
      configuration: standardBlockComponentConfiguration.copyWith(
        placeholderText: (node) {
          final level = node.attributes[HeadingBlockKeys.level];
          return 'Heading $level';
        },
      ),
    ),
    // ... other block types
  },
  characterShortcutEvents: [
    formatSignToHeading,  // Enable # shortcut
    // ... other shortcuts
  ],
);

Inserting Headings

// Insert H1 at beginning
final transaction = editorState.transaction;
transaction.insertNode(
  [0],
  headingNode(level: 1, text: 'Document Title'),
);
editorState.apply(transaction);

// Convert current paragraph to heading
final selection = editorState.selection;
if (selection != null) {
  final node = editorState.getNodeAtPath(selection.start.path);
  if (node != null) {
    final transaction = editorState.transaction;
    transaction.updateNode(node, {
      'type': HeadingBlockKeys.type,
      HeadingBlockKeys.level: 2,
    });
    editorState.apply(transaction);
  }
}

Changing Heading Level

// Update heading level
final node = editorState.getNodeAtPath(path);
if (node?.type == HeadingBlockKeys.type) {
  final transaction = editorState.transaction;
  transaction.updateNode(node!, {
    HeadingBlockKeys.level: 3, // Change to H3
  });
  editorState.apply(transaction);
}

Custom Styling Examples

Color-Coded Levels

HeadingBlockComponentBuilder(
  textStyleBuilder: (level) {
    final colors = {
      1: Colors.blue.shade900,
      2: Colors.blue.shade700,
      3: Colors.blue.shade500,
      4: Colors.grey.shade800,
      5: Colors.grey.shade700,
      6: Colors.grey.shade600,
    };
    
    return TextStyle(
      fontSize: [32.0, 28.0, 24.0, 20.0, 18.0, 16.0][level - 1],
      fontWeight: FontWeight.bold,
      color: colors[level],
    );
  },
)

Custom Font Families

HeadingBlockComponentBuilder(
  textStyleBuilder: (level) {
    return TextStyle(
      fontSize: [32.0, 28.0, 24.0, 20.0, 18.0, 16.0][level - 1],
      fontWeight: level <= 3 ? FontWeight.w800 : FontWeight.w600,
      fontFamily: 'Merriweather',
      letterSpacing: -0.5,
    );
  },
)

Key Features

  • Six Heading Levels - H1 through H6
  • Rich Text Support - Full Delta format with inline styling
  • Custom Text Styles - Per-level style customization
  • Text Direction - LTR and RTL support
  • Alignment - Left, center, right alignment
  • Background Color - Custom background colors
  • Markdown Shortcuts - # syntax support
  • Keyboard Shortcuts - Quick level toggling

Best Practices

  1. Use H1 sparingly - Typically one per document
  2. Maintain hierarchy - Don’t skip levels (H1 → H3)
  3. Keep headings concise - Brief, descriptive titles
  4. Use semantic meaning - Headings define document structure
  5. Consider accessibility - Proper heading hierarchy aids screen readers

Paragraph Blocks

Learn about paragraph blocks

Quote Blocks

Block quotes for emphasis

Build docs developers (and LLMs) love