Visual themes for Choreo architecture diagrams.
A theme controls node shapes, colours, fonts, edge styling, graph layout,
and cluster defaults. Use custom/1 to build your own, or use the built-in
atom shortcuts (:default, :dark, :minimal).
Built-in themes
# Warm, top-down layout with type-coloured nodes (default)
Choreo.to_dot(system, theme: :default)
# Dark background with neon accents
Choreo.to_dot(system, theme: :dark)
# Wireframe look — monochrome, no fills
Choreo.to_dot(system, theme: :minimal)Custom themes
theme =
Choreo.Theme.custom(
name: "brand",
colors: [database: "#1e3a8a", service: "#047857"],
graph_bgcolor: "#f8fafc",
graph_rankdir: :lr
)
Choreo.to_dot(system, theme: theme)Per-type overrides
The shapes and colors maps accept any node :type as a key. Missing
types fall back to the built-in defaults (:box shape, "#9ca3af" colour).
Cluster theming
You can set default cluster styling so every add_cluster/3 inherits a
look unless it provides its own :fillcolor, :style, or :color.
Choreo.Theme.custom(
cluster_fillcolor: "#e2e8f0",
cluster_style: :rounded,
cluster_color: "#64748b"
)
Summary
Functions
Resolves the effective colour for a node type, falling back to defaults.
Builds a custom theme from keyword options.
Dark theme — dark background, neon accents.
The default theme — type-coloured nodes, top-down layout.
Returns the default colour palette.
Returns the default shape palette.
Minimal theme — monochrome wireframe, thin edges, no fills.
Resolves the effective shape for a node type, falling back to defaults.
Types
@type t() :: %Choreo.Theme{ cluster_color: String.t() | nil, cluster_fillcolor: String.t() | nil, cluster_style: Yog.Render.DOT.style() | nil, colors: %{required(atom()) => String.t()}, edge_color: String.t(), edge_fontname: String.t(), edge_fontsize: integer(), edge_penwidth: float(), graph_bgcolor: String.t() | nil, graph_nodesep: float(), graph_rankdir: Yog.Render.DOT.rank_dir(), graph_ranksep: float(), graph_splines: Yog.Render.DOT.splines(), name: atom() | String.t(), node_fontcolor: String.t(), node_fontname: String.t(), node_fontsize: integer(), shapes: %{required(atom()) => Yog.Render.DOT.node_shape()} }
Functions
Resolves the effective colour for a node type, falling back to defaults.
Examples
iex> theme = Choreo.Theme.custom(colors: %{database: "#ff0000"})
iex> Choreo.Theme.color(theme, :database)
"#ff0000"
iex> Choreo.Theme.color(theme, :service)
"#10b981"
Builds a custom theme from keyword options.
Only the fields you specify are overridden; everything else falls back to the default theme values.
Examples
iex> theme = Choreo.Theme.custom(name: :brand, graph_rankdir: :lr)
iex> theme.name
:brand
iex> theme.graph_rankdir
:lr
@spec dark() :: t()
Dark theme — dark background, neon accents.
Examples
iex> theme = Choreo.Theme.dark()
iex> theme.name
:dark
iex> theme.graph_bgcolor
"#0f172a"
@spec default() :: t()
The default theme — type-coloured nodes, top-down layout.
Examples
iex> theme = Choreo.Theme.default()
iex> theme.name
:default
iex> theme.graph_rankdir
:tb
Returns the default colour palette.
Examples
iex> colors = Choreo.Theme.default_colors()
iex> colors[:database]
"#3b82f6"
iex> colors[:service]
"#10b981"
@spec default_shapes() :: %{required(atom()) => Yog.Render.DOT.node_shape()}
Returns the default shape palette.
Examples
iex> shapes = Choreo.Theme.default_shapes()
iex> shapes[:database]
:cylinder
iex> shapes[:service]
:box3d
@spec minimal() :: t()
Minimal theme — monochrome wireframe, thin edges, no fills.
Examples
iex> theme = Choreo.Theme.minimal()
iex> theme.name
:minimal
iex> theme.colors[:database]
"#ffffff"
iex> theme.shapes[:service]
:box
@spec shape(t(), atom()) :: Yog.Render.DOT.node_shape()
Resolves the effective shape for a node type, falling back to defaults.
Examples
iex> theme = Choreo.Theme.custom(shapes: %{database: :box})
iex> Choreo.Theme.shape(theme, :database)
:box
iex> Choreo.Theme.shape(theme, :service)
:box3d