Theming Overview
Customize the appearance of your node flow editor
Theming Overview
Vyuh Node Flow provides a comprehensive theming system that allows you to customize every visual aspect of your node flow editor.
Theme Structure
The NodeFlowTheme is the main configuration object:
class NodeFlowTheme {
final NodeTheme nodeTheme;
final ConnectionStyle connectionStyle;
final ConnectionStyle temporaryConnectionStyle;
final ConnectionTheme connectionTheme;
final ConnectionTheme temporaryConnectionTheme;
final PortTheme portTheme;
final LabelTheme labelTheme;
final Color backgroundColor;
final GridStyle gridStyle;
final Color gridColor;
final double gridSize;
}Quick Start
Light Theme (Default)
NodeFlowEditor<MyData>(
controller: controller,
theme: NodeFlowTheme(
nodeTheme: NodeTheme.light,
connectionStyle: ConnectionStyles.smoothstep,
backgroundColor: Colors.white,
gridStyle: GridStyle.dots,
),
// ...
)Dark Theme
NodeFlowEditor<MyData>(
controller: controller,
theme: NodeFlowTheme(
nodeTheme: NodeTheme.dark,
connectionStyle: ConnectionStyles.smoothstep,
connectionTheme: ConnectionTheme.dark,
backgroundColor: Colors.grey[900]!,
gridColor: Colors.grey[800]!,
portTheme: PortTheme.dark,
),
// ...
)Theme Components
1. Node Theme
Controls the appearance of nodes:
nodeTheme: NodeTheme(
selectedBorderColor: Colors.blue,
selectedBorderWidth: 3,
defaultBorderColor: Colors.grey,
defaultBorderWidth: 1,
hoverBorderColor: Colors.blue.shade200,
)Note: The node widget itself is fully customizable via nodeBuilder. The theme primarily controls selection/hover borders.
2. Connection Style
Choose how connections are drawn:
// Smooth curved connections
connectionStyle: ConnectionStyles.smoothstep
// Bezier curves
connectionStyle: ConnectionStyles.bezier
// Step connections
connectionStyle: ConnectionStyles.step
// Straight lines
connectionStyle: ConnectionStyles.straight3. Connection Theme
Customize connection appearance:
connectionTheme: ConnectionTheme(
color: Colors.blue,
strokeWidth: 2,
selectedColor: Colors.blue[700]!,
selectedStrokeWidth: 3,
startPoint: ConnectionEndPoint.none,
endPoint: ConnectionEndPoint(
shape: EndpointShape.triangle,
size: 9,
),
)4. Port Theme
Customize port appearance:
portTheme: PortTheme(
size: 12,
color: Colors.blue,
hoverColor: Colors.blue[700]!,
borderColor: Colors.white,
borderWidth: 2,
)5. Background & Grid
backgroundColor: Colors.grey[50]!,
gridStyle: GridStyle.dots, // or GridStyle.lines
gridColor: Colors.grey[300]!,
gridSize: 20, // pixelsComplete Custom Theme
final customTheme = NodeFlowTheme(
// Nodes
nodeTheme: NodeTheme(
selectedBorderColor: Color(0xFF6366F1),
selectedBorderWidth: 3,
defaultBorderColor: Color(0xFFE5E7EB),
defaultBorderWidth: 1,
hoverBorderColor: Color(0xFFA5B4FC),
),
// Connections
connectionStyle: ConnectionStyles.smoothstep,
connectionTheme: ConnectionTheme(
color: Color(0xFF6366F1),
strokeWidth: 2,
selectedColor: Color(0xFF4F46E5),
selectedStrokeWidth: 3,
startPoint: ConnectionEndPoint.none,
endPoint: ConnectionEndPoint(
shape: EndpointShape.triangle,
size: 10,
color: Color(0xFF6366F1),
),
),
// Temporary connections (while dragging)
temporaryConnectionStyle: ConnectionStyles.smoothstep,
temporaryConnectionTheme: ConnectionTheme(
color: Color(0xFF6366F1).withOpacity(0.5),
strokeWidth: 2,
dashPattern: [8, 4],
startPoint: ConnectionEndPoint.none,
endPoint: ConnectionEndPoint(
shape: EndpointShape.triangle,
size: 10,
),
),
// Ports
portTheme: PortTheme(
size: 12,
color: Color(0xFF6366F1),
hoverColor: Color(0xFF4F46E5),
borderColor: Colors.white,
borderWidth: 2,
),
// Labels
labelTheme: LabelTheme(
fontSize: 12,
color: Color(0xFF1F2937),
backgroundColor: Colors.white,
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
borderRadius: 4,
),
// Background
backgroundColor: Color(0xFFFAFAFA),
gridStyle: GridStyle.dots,
gridColor: Color(0xFFE5E7EB),
gridSize: 20,
);Responsive Themes
Adapt theme based on context:
NodeFlowTheme getTheme(BuildContext context) {
final isDark = Theme.of(context).brightness == Brightness.dark;
return NodeFlowTheme(
nodeTheme: isDark ? NodeTheme.dark : NodeTheme.light,
connectionTheme: isDark
? ConnectionTheme.dark
: ConnectionTheme.light,
backgroundColor: isDark ? Colors.grey[900]! : Colors.white,
gridColor: isDark ? Colors.grey[800]! : Colors.grey[200]!,
portTheme: isDark ? PortTheme.dark : PortTheme.light,
);
}
// Usage
NodeFlowEditor<MyData>(
controller: controller,
theme: getTheme(context),
// ...
)Theme Presets
Create reusable theme presets:
class FlowThemes {
static NodeFlowTheme get blueprint => NodeFlowTheme(
nodeTheme: NodeTheme.light,
connectionStyle: ConnectionStyles.step,
connectionTheme: ConnectionTheme(
color: Colors.white,
strokeWidth: 2,
),
backgroundColor: Color(0xFF1E3A8A),
gridStyle: GridStyle.lines,
gridColor: Colors.white.withOpacity(0.1),
);
static NodeFlowTheme get minimal => NodeFlowTheme(
nodeTheme: NodeTheme(
selectedBorderColor: Colors.black,
selectedBorderWidth: 2,
defaultBorderColor: Colors.grey[300]!,
defaultBorderWidth: 1,
),
connectionStyle: ConnectionStyles.straight,
connectionTheme: ConnectionTheme(
color: Colors.black,
strokeWidth: 1,
),
backgroundColor: Colors.white,
gridStyle: GridStyle.none,
);
}Dynamic Theme Updates
Change theme at runtime:
class _MyEditorState extends State<MyEditor> {
NodeFlowTheme _currentTheme = NodeFlowTheme.light;
void _toggleTheme() {
setState(() {
_currentTheme = _currentTheme == NodeFlowTheme.light
? NodeFlowTheme.dark
: NodeFlowTheme.light;
});
}
@override
Widget build(BuildContext context) {
return Column(
children: [
ElevatedButton(
onPressed: _toggleTheme,
child: Text('Toggle Theme'),
),
Expanded(
child: NodeFlowEditor<MyData>(
controller: controller,
theme: _currentTheme,
// ...
),
),
],
);
}
}Best Practices
- Consistency: Keep theme consistent with your app's design system
- Contrast: Ensure sufficient contrast for accessibility
- Performance: Theme changes trigger full repaints, use sparingly
- Testing: Test themes in different lighting conditions
- Presets: Create reusable theme presets for common styles
Next Steps
- Node Theme - Detailed node theming
- Connection Theme - Connection customization
- Examples - See themes in action