Domphy

Class & State Diagrams

Class diagrams

Class diagrams model the static structure of a system: its types, members, and the relationships between them.

Basic class syntax

<div class="dp-mermaid language-mermaid">classDiagram class Animal { +String name +int age +makeSound() void +move(distance int) bool }</div>

Members are listed inside { }. Fields list type then name; methods add parentheses and an optional return type.

Member visibility

SymbolVisibility
+Public
-Private
#Protected
~Package / internal

Append $ to mark a member as static, or * to mark it as abstract:

<div class="dp-mermaid language-mermaid">classDiagram class Repository { -String connectionString +$getInstance() Repository +*findById(id int) Entity #validate(entity Entity) bool }</div>

Relationships

<div class="dp-mermaid language-mermaid">classDiagram Animal &lt;|-- Dog : Inheritance Car *-- Engine : Composition Car o-- Wheel : Aggregation Driver --&gt; Car : Association Order ..&gt; Product : Dependency Service ..|&gt; IService : Realization</div>
SyntaxRelationship
A <|-- BB inherits from A (generalization)
A *-- BA is composed of B (composition)
A o-- BA aggregates B (aggregation)
A --> BA has an association to B
A -- BLink (undirected)
A ..> BA depends on B
A ..*Composition via dotted
A ..|> BA realizes interface B

All relationships can be reversed by swapping the symbols.

Cardinality labels

Add cardinality to either end of a relationship:

<div class="dp-mermaid language-mermaid">classDiagram class Customer { +String name } class Order { +Date placedAt } class LineItem { +int quantity } Customer &quot;1&quot; --&gt; &quot;0..*&quot; Order : places Order &quot;1&quot; *-- &quot;1..*&quot; LineItem : contains</div>

Common cardinality strings: 1, 0..*, 1..*, 0..1, n, 1..n.

Relationship labels

Add a label after the relationship using : with a quoted or unquoted string:

<div class="dp-mermaid language-mermaid">classDiagram User &quot;1&quot; --&gt; &quot;0..*&quot; Session : has Session --&gt; Token : carries</div>

Annotations

Annotations mark the stereotype of a class. Place them inside the class body with <<...>>:

<div class="dp-mermaid language-mermaid">classDiagram class IRepository { &lt;&lt;Interface&gt;&gt; +findById(id int) Entity +save(entity Entity) void } class BaseService { &lt;&lt;Abstract&gt;&gt; +#validate() bool } class Status { &lt;&lt;Enumeration&gt;&gt; PENDING ACTIVE CLOSED } class UserService { &lt;&lt;Service&gt;&gt; }</div>

Common annotations: <<Interface>>, <<Abstract>>, <<Enumeration>>, <<Service>>, <<Repository>>, <<Component>>.

Namespaces

Group related classes inside a named namespace:

<div class="dp-mermaid language-mermaid">classDiagram namespace Domain { class User { +String email } class Order { +Date createdAt } } namespace Infrastructure { class UserRepository { +findByEmail(email String) User } } UserRepository --&gt; User : returns</div>

Class diagram direction

Control layout with a leading direction declaration:

<div class="dp-mermaid language-mermaid">classDiagram direction LR class A class B A --&gt; B</div>

Accepted values: TB, BT, LR, RL.


State diagrams

State diagrams model the lifecycle of an object — which states it can be in and the transitions between them.

Basic transitions

<div class="dp-mermaid language-mermaid">stateDiagram-v2 [*] --&gt; Idle Idle --&gt; Loading : fetch() Loading --&gt; Success : ok Loading --&gt; Error : fail Error --&gt; Idle : reset() Success --&gt; [*]</div>

[*] is the special initial / final state marker. A transition out of [*] is the entry; a transition into [*] is the exit.

State descriptions

Add a description to a state using state_id : description:

<div class="dp-mermaid language-mermaid">stateDiagram-v2 Idle : Waiting for user input Loading : Request in flight Success : Data received Error : Render error boundary [*] --&gt; Idle Idle --&gt; Loading Loading --&gt; Success Loading --&gt; Error</div>

Named states

Give a long-form display name to a state using state "label" as id:

<div class="dp-mermaid language-mermaid">stateDiagram-v2 state &quot;Fetching data&quot; as loading state &quot;Render complete&quot; as done [*] --&gt; loading loading --&gt; done : ok loading --&gt; [*] : error</div>

Composite (nested) states

A composite state groups sub-states inside state id { ... }:

<div class="dp-mermaid language-mermaid">stateDiagram-v2 [*] --&gt; Auth state Auth { [*] --&gt; Unauthenticated Unauthenticated --&gt; Authenticating : login() Authenticating --&gt; Authenticated : success Authenticating --&gt; Unauthenticated : failure Authenticated --&gt; [*] } Auth --&gt; App</div>

Fork and join

Model parallel execution with <<fork>> and <<join>>:

<div class="dp-mermaid language-mermaid">stateDiagram-v2 [*] --&gt; fork state fork &lt;&lt;fork&gt;&gt; fork --&gt; Logging fork --&gt; Notifying Logging --&gt; join Notifying --&gt; join state join &lt;&lt;join&gt;&gt; join --&gt; [*]</div>

Choice (conditional)

Branch based on a condition with <<choice>>:

<div class="dp-mermaid language-mermaid">stateDiagram-v2 [*] --&gt; Validate Validate --&gt; check state check &lt;&lt;choice&gt;&gt; check --&gt; Success : valid check --&gt; Error : invalid Success --&gt; [*] Error --&gt; [*]</div>

Concurrency

Split a composite state into concurrent regions with --:

<div class="dp-mermaid language-mermaid">stateDiagram-v2 [*] --&gt; Active state Active { [*] --&gt; UI UI --&gt; UI : interaction -- [*] --&gt; Sync Sync --&gt; Syncing : timer Syncing --&gt; Sync : done } Active --&gt; [*] : logout</div>

Notes

Annotate a state with a free-form note:

<div class="dp-mermaid language-mermaid">stateDiagram-v2 [*] --&gt; Idle note right of Idle Default state on startup. Re-entered after any reset. end note Idle --&gt; Running</div>

Direction

<div class="dp-mermaid language-mermaid">stateDiagram-v2 direction LR [*] --&gt; A --&gt; B --&gt; [*]</div>

Rendering with @domphy/mermaid

import { renderMermaidToSvg } from "@domphy/mermaid"

const classSvg = await renderMermaidToSvg(`classDiagram
  class IStore {
    <<Interface>>
    +get(key String) T
    +set(key String, value T) void
  }
  class RecordState {
    +get(key String) T
    +set(key String, value T) void
  }
  IStore <|.. RecordState : implements`, { theme: "neutral" })

const stateSvg = await renderMermaidToSvg(`stateDiagram-v2
  [*] --> Idle
  Idle --> Loading : query.fetch()
  Loading --> Success : data received
  Loading --> Error : network fail
  Error --> Idle : retry()
  Success --> [*]`, { theme: "neutral" })