Harlock.Theme (harlock v0.4.0)

Copy Markdown View Source

Visual theme tokens used by the renderer.

v0.2 shipped the minimum surface the renderer actually reads (:header, :focus, :selection, :border). v0.4 adds the general-purpose tokens app authors reach for — :primary, :accent, :muted, :error — and ships three built-in themes plus caps-aware color downgrade so the same theme renders reasonably on truecolor, 256-color, 16-color, and monochrome terminals.

Tokens (each a Harlock.Render.Style.t()):

  • :header — table column headers. Default: bold: true.
  • :focus — active focus indicator. Default: reverse: true.
  • :selection — selected rows / cells. Default: bg: :cyan.
  • :border — default box border style. Default: %Style{} (no fg/bg).
  • :primary — primary brand / accent surface. Default: fg: :cyan.
  • :accent — secondary accent. Default: fg: :magenta.
  • :muted — de-emphasised text. Default: dim: true.
  • :error — error / destructive surface. Default: fg: :red.

Setting a theme

Harlock.run(MyApp, init_arg, theme: %Harlock.Theme{
  focus:     %Style{reverse: true, fg: :yellow},
  selection: %Style{bg: :blue, fg: :white}
})

# Or use a built-in:
Harlock.run(MyApp, init_arg, theme: Harlock.Theme.builtin(:dark))

Omitting the option uses Harlock.Theme.default/0, which matches the pre-theming hard-coded values byte-for-byte. The default theme is intentionally minimal — apps that want a visible identity pick a built-in or build their own.

Built-in themes

  • :default — what v0.3 produced. Minimal, terminal-native colors.
  • :dark — opinionated dark palette suitable for cave-dwellers.
  • :high_contrast — bright primaries / strong borders, biased for readability over aesthetics.

Look up with Harlock.Theme.builtin/1.

Reading inside a callback

def view(model) do
  accent = Harlock.Theme.get(:primary)
  text("hello", style: accent)
end

The runtime stashes the theme in the process dictionary before invoking update/2 and view/1, mirroring the Harlock.Focus pattern. Don't call get/1 outside a Harlock callback — there's nothing in the dictionary.

Summary

Types

t()

A theme is the bag of styled tokens the renderer looks up.

Functions

Build a theme from a keyword list or a map. Unspecified tokens take their default values.

Return one of the built-in themes by name. Available: :default, :dark, :high_contrast.

The default theme. Matches the pre-theming hard-coded values exactly so apps without a custom theme render byte-identically across v0.3 and v0.4. New v0.4 tokens (:primary/:accent/:muted/:error) carry sensible defaults but are not read by the renderer itself — they're available only to apps that explicitly opt in via get/1.

Look up a theme token. Returns the value from the theme installed by the runtime, or the default if no theme is in scope.

Types

t()

@type t() :: %Harlock.Theme{
  accent: Harlock.Render.Style.t(),
  border: Harlock.Render.Style.t(),
  error: Harlock.Render.Style.t(),
  focus: Harlock.Render.Style.t(),
  header: Harlock.Render.Style.t(),
  muted: Harlock.Render.Style.t(),
  primary: Harlock.Render.Style.t(),
  selection: Harlock.Render.Style.t()
}

token()

@type token() ::
  :header | :focus | :selection | :border | :primary | :accent | :muted | :error

A theme is the bag of styled tokens the renderer looks up.

Functions

build(theme)

@spec build(keyword() | map() | t()) :: t()

Build a theme from a keyword list or a map. Unspecified tokens take their default values.

builtin(atom)

@spec builtin(:default | :dark | :high_contrast) :: t()

Return one of the built-in themes by name. Available: :default, :dark, :high_contrast.

default()

@spec default() :: t()

The default theme. Matches the pre-theming hard-coded values exactly so apps without a custom theme render byte-identically across v0.3 and v0.4. New v0.4 tokens (:primary/:accent/:muted/:error) carry sensible defaults but are not read by the renderer itself — they're available only to apps that explicitly opt in via get/1.

get(token)

@spec get(token()) :: Harlock.Render.Style.t()

Look up a theme token. Returns the value from the theme installed by the runtime, or the default if no theme is in scope.