Draw.io UML Diagram Implementation
Purpose
This skill enables correct generation of UML diagrams in Draw.io mxGraph XML. It covers the five most common UML diagram types: class, sequence, use case, state machine, and activity. The most common AI mistake is using generic arrows (endArrow=classic) instead of UML-specific connector styles (open diamond for aggregation, filled diamond for composition, hollow triangle for generalization).
Critical Rules (Memorize These)
- ALWAYS use
endArrow=block;endFill=0for generalization/inheritance — the hollow triangle. NEVER useendFill=1which produces a filled triangle (wrong UML semantics). - ALWAYS use
startArrow=diamond;startFill=0for aggregation — the open diamond. NEVER usestartFill=1which produces composition instead. - ALWAYS use
startArrow=diamond;startFill=1for composition — the filled diamond. The fill distinguishes composition from aggregation. - ALWAYS use
dashed=1for dependency and realization edges — solid lines are WRONG for these relationship types. - ALWAYS use
shape=umlLifeline;perimeter=lifelinePerimeterfor sequence diagram participants — NEVER use plain rectangles with manual dashed lines. - ALWAYS use
shape=umlActorfor UML actors — NEVER useshape=ellipseor stick-figure images. - ALWAYS use the 3-compartment swimlane pattern for UML classes — class name header, attributes compartment, operations compartment, separated by
linecells. - ALWAYS include both structural cells (
id="0"andid="1"withparent="0") in every diagram. - ALWAYS use
endArrow=open;endFill=0;dashed=1for return messages in sequence diagrams — NEVER use solid lines for returns. - ALWAYS place use cases inside the system boundary container — NEVER place them at
parent="1"when a system boundary exists.
UML Relationship Arrow Styles
The 6 Core Relationship Types
| Relationship | startArrow | endArrow | dashed | startFill | endFill | Visual |
|---|---|---|---|---|---|---|
| Association | none | none | 0 | — | — | Plain line |
| Directed Association | none | open | 0 | — | 1 | Line + open arrow |
| Generalization | none | block | 0 | — | 0 | Line + hollow triangle |
| Realization | none | block | 1 | — | 0 | Dashed + hollow triangle |
| Aggregation | diamond | none | 0 | 0 | — | Open diamond + line |
| Composition | diamond | none | 0 | 1 | — | Filled diamond + line |
| Dependency | none | open | 1 | — | 1 | Dashed + open arrow |
Edge Style Strings
Association (plain):
endArrow=none;html=1;edgeStyle=orthogonalEdgeStyle;
Directed Association:
endArrow=open;endFill=1;html=1;edgeStyle=orthogonalEdgeStyle;
Generalization (inheritance):
endArrow=block;endFill=0;html=1;edgeStyle=orthogonalEdgeStyle;
Realization (interface implementation):
endArrow=block;endFill=0;dashed=1;html=1;edgeStyle=orthogonalEdgeStyle;
Aggregation (has-a, shared):
startArrow=diamond;startFill=0;endArrow=none;html=1;edgeStyle=orthogonalEdgeStyle;
Composition (has-a, owned):
startArrow=diamond;startFill=1;endArrow=none;html=1;edgeStyle=orthogonalEdgeStyle;
Dependency (uses):
endArrow=open;endFill=1;dashed=1;html=1;edgeStyle=orthogonalEdgeStyle;
Class Diagram
3-Compartment Class Structure
A UML class uses swimlane with childLayout=stackLayout containing three child zones separated by line cells.
Container style (class header):
swimlane;fontStyle=1;align=center;startSize=26;container=1;collapsible=0;childLayout=stackLayout;
Attributes compartment:
text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;whiteSpace=wrap;html=0;
Separator line:
line;strokeWidth=1;fillColor=none;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=10;rotatable=0;labelPosition=left;points=[];portConstraint=eastwest;
Operations compartment:
text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;whiteSpace=wrap;html=0;
UML Visibility Prefixes
| Prefix | Meaning |
|---|---|
+ |
Public |
- |
Private |
# |
Protected |
~ |
Package |
Attribute Format
visibility name: Type
Example: - id: int or + getName(): String
Class Dimensions
| Component | Width | Height | Notes |
|---|---|---|---|
| Class container | 200 | Calculated | startSize + attr_height + sep + ops_height |
| Header band | 200 | 26 (startSize) | Bold class name |
| Attributes cell | 200 | attr_count * 18 | ~18px per attribute line |
| Separator | 200 | 8 | Fixed thin line |
| Operations cell | 200 | ops_count * 18 | ~18px per operation line |
Use 
 for newlines within attribute/operation text values (html=0 mode).
Abstract and Interface Classes
Abstract class — add fontStyle=3; (bold + italic) to the container and prefix name with <<abstract>>:
swimlane;fontStyle=3;align=center;startSize=26;container=1;collapsible=0;childLayout=stackLayout;
Interface — prefix name with <<interface>> and use fontStyle=3;:
swimlane;fontStyle=3;align=center;startSize=26;container=1;collapsible=0;childLayout=stackLayout;
Sequence Diagram
Lifeline Shape
shape=umlLifeline;perimeter=lifelinePerimeter;whiteSpace=wrap;html=1;container=1;collapsible=0;recursiveResize=0;outlineConnect=0;size=40;
Key properties:
shape=umlLifeline— REQUIRED. Renders the rectangle header + dashed vertical line.perimeter=lifelinePerimeter— REQUIRED. Enables correct connection points along the lifeline.size=40— height of the participant header box in pixels.container=1— allows activation bars as children.- Total
heightof the mxGeometry determines how far the dashed line extends.
Lifeline Dimensions
| Property | Value | Notes |
|---|---|---|
| Width | 100 | Standard lifeline width |
| Height | 300-500 | Total lifeline length (adjust per diagram complexity) |
| size | 40 | Header box height |
| Horizontal spacing | 200 | Between lifeline centers |
Message Types
| Message Type | endArrow | endFill | dashed | Visual |
|---|---|---|---|---|
| Synchronous | block | 1 | 0 | Solid + filled arrow |
| Asynchronous | open | 1 | 0 | Solid + open arrow |
| Return | open | 0 | 1 | Dashed + open arrow |
| Create | open | 1 | 0 | Solid + open arrow (to new lifeline) |
| Destroy | none | — | 0 | Solid line + X at target |
Synchronous message style:
html=1;verticalAlign=bottom;endArrow=block;endFill=1;
Asynchronous message style:
html=1;verticalAlign=bottom;endArrow=open;endFill=1;
Return message style:
html=1;verticalAlign=bottom;endArrow=open;endFill=0;dashed=1;
Message Positioning
Messages use absolute sourcePoint and targetPoint coordinates (NOT source/target cell references):
<mxCell id="msg1" value="request()" style="html=1;verticalAlign=bottom;endArrow=block;endFill=1;" edge="1" parent="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="130" y="120" as="sourcePoint" />
<mxPoint x="330" y="120" as="targetPoint" />
</mxGeometry>
</mxCell>
sourcePoint.x= source lifeline center (lifeline x + width/2).targetPoint.x= target lifeline center.- Both points share the same
yvalue for horizontal messages. - Increment
yby 40-50px between consecutive messages.
Activation Bars
Activation bars are child cells of their lifeline:
<mxCell id="act1" value="" style="html=1;points=[];perimeter=orthogonalPerimeter;outlineConnect=0;targetShapes=umlLifeline;portConstraint=eastwest;newEdgeStyle={"curved":0,"rounded":0};" vertex="1" parent="ll1">
<mxGeometry x="45" y="80" width="10" height="80" as="geometry" />
</mxCell>
x=45centers the 10px-wide bar on a 100px-wide lifeline ((100-10)/2 = 45).yis relative to the lifeline top (NOT absolute).heightspans from first incoming message to last outgoing message.
Use Case Diagram
Actor Shape
shape=umlActor;verticalLabelPosition=bottom;verticalAlign=top;html=1;outlineConnect=0;
Dimensions: width=30, height=55. ALWAYS place actors outside the system boundary.
Use Case (Ellipse)
ellipse;whiteSpace=wrap;html=1;
Dimensions: width=180, height=60. ALWAYS place inside the system boundary container.
System Boundary
rounded=1;whiteSpace=wrap;html=1;container=1;collapsible=0;fillColor=none;strokeColor=#666666;strokeWidth=2;dashed=1;verticalAlign=top;fontStyle=1;fontSize=14;
The system boundary is a container=1 cell. Use cases MUST be children of this container (parent="<system_id>").
Use Case Relationships
| Relationship | Style | Notes |
|---|---|---|
| Actor-to-UseCase | endArrow=none;html=1; |
Plain line, no arrows |
| Include | endArrow=open;endFill=1;dashed=1;html=1; |
Dashed + label <<include>> |
| Extend | endArrow=open;endFill=1;dashed=1;html=1; |
Dashed + label <<extend>> |
| Generalization | endArrow=block;endFill=0;html=1; |
Hollow triangle |
State Machine Diagram
State Shapes
Initial state (filled circle):
ellipse;fillColor=#000000;strokeColor=#000000;
Dimensions: width=30, height=30.
Regular state (with actions):
rounded=1;whiteSpace=wrap;html=1;align=center;verticalAlign=top;arcSize=15;
Use HTML in the value for state compartments:
<b>StateName</b><hr>entry / action()<br>exit / action()
Final state (bullseye):
ellipse;html=1;shape=doubleCircle;fillColor=#000000;strokeColor=#000000;
Dimensions: width=30, height=30.
Transition Edge
endArrow=open;endFill=1;html=1;
Label format: event [guard] / action
Activity Diagram
Activity Shapes
Initial node: Same as state machine initial state.
Action node:
rounded=1;whiteSpace=wrap;html=1;
Decision node (diamond):
rhombus;whiteSpace=wrap;html=1;
Dimensions: width=40, height=40. Label outgoing edges with [guard].
Fork/Join bar (horizontal):
shape=line;html=1;strokeWidth=6;strokeColor=#000000;fillColor=#000000;
Dimensions: width=200, height=10.
Fork/Join bar (vertical):
shape=line;html=1;strokeWidth=6;strokeColor=#000000;fillColor=#000000;direction=south;
Dimensions: width=10, height=200.
Final node: Same as state machine final state.
Activity Edge
endArrow=open;endFill=1;html=1;edgeStyle=orthogonalEdgeStyle;
Color Conventions
| Element | Fill Color | Stroke Color |
|---|---|---|
| Primary class/lifeline | #dae8fc (light blue) |
#6c8ebf |
| Secondary class/lifeline | #d5e8d4 (light green) |
#82b366 |
| Tertiary class/lifeline | #fff2cc (light yellow) |
#d6b656 |
| Abstract/interface | #e1d5e7 (light purple) |
#9673a6 |
| System boundary | none |
#666666 |
| Initial/final state | #000000 |
#000000 |
Layout Strategy
Class Diagrams
- Horizontal spacing: 120-160px between classes.
- Vertical spacing: 100-140px for inheritance hierarchies.
- Place parent classes ABOVE child classes for generalization.
- Place associated classes side by side.
Sequence Diagrams
- Lifeline horizontal spacing: 200px center-to-center.
- Message vertical spacing: 40-50px between messages.
- Total lifeline height: 40 (header) + (message_count * 50) + 60 (margin).
Use Case Diagrams
- Actors 80-120px outside the system boundary.
- Use cases spaced 80px vertically within the boundary.
- System boundary sized to fit all use cases with 40px padding.
Checklist: Before Outputting a UML Diagram
- Every class uses
swimlane;container=1;childLayout=stackLayout;with 3 compartments. - Every class has a
lineseparator between attributes and operations. - Every generalization edge uses
endArrow=block;endFill=0(hollow triangle). - Every aggregation edge uses
startArrow=diamond;startFill=0(open diamond). - Every composition edge uses
startArrow=diamond;startFill=1(filled diamond). - Every dependency/realization edge uses
dashed=1. - Every sequence lifeline uses
shape=umlLifeline;perimeter=lifelinePerimeter. - Every return message uses
dashed=1;endArrow=open;endFill=0. - Every actor uses
shape=umlActor— NEVERshape=ellipse. - Every use case is a child of the system boundary container.
- Both structural cells (
id="0"andid="1") are present. - All cell IDs are unique across the entire diagram.
- All edge
source/targetattributes (or sourcePoint/targetPoint) are valid.
Cross-References
- XML fundamentals: See
drawio-core-xml-formatfor file structure and structural cells. - Style syntax: See
drawio-syntax-stylesfor the complete style property reference. - Connection details: See
drawio-syntax-connectionsfor edge routing and waypoints. - Geometry: See
drawio-core-geometryfor coordinate system and positioning. - Swimlanes: See
drawio-impl-swimlanesfor container and lane patterns.
Reference Links
- Complete Reference
- Working Examples
- Anti-Patterns