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,
);
}
| Level | Font Size | Weight |
|---|
| H1 | 32.0 | Bold |
| H2 | 28.0 | Bold |
| H3 | 24.0 | Bold |
| H4 | 18.0 | Bold |
| H5 | 18.0 | Bold |
| H6 | 18.0 | Bold |
Source: /lib/src/editor/block_component/heading_block_component/heading_block_component.dart:209
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
- Use H1 sparingly - Typically one per document
- Maintain hierarchy - Don’t skip levels (H1 → H3)
- Keep headings concise - Brief, descriptive titles
- Use semantic meaning - Headings define document structure
- Consider accessibility - Proper heading hierarchy aids screen readers
Paragraph Blocks
Learn about paragraph blocks
Quote Blocks
Block quotes for emphasis