Choreo.Theme (Choreo v0.6.0)

Copy Markdown View Source

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

t()

@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

color(theme, type)

@spec color(t(), atom()) :: String.t()

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"

custom(opts \\ [])

@spec custom(keyword()) :: t()

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

dark()

@spec dark() :: t()

Dark theme — dark background, neon accents.

Examples

iex> theme = Choreo.Theme.dark()
iex> theme.name
:dark
iex> theme.graph_bgcolor
"#0f172a"

default()

@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

default_colors()

@spec default_colors() :: %{required(atom()) => String.t()}

Returns the default colour palette.

Examples

iex> colors = Choreo.Theme.default_colors()
iex> colors[:database]
"#3b82f6"
iex> colors[:service]
"#10b981"

default_shapes()

@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

minimal()

@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

shape(theme, type)

@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