Design token system for Dala apps.
A theme is a compiled %Dala.Theme{} struct — a flat map of semantic tokens
for colors, spacing, radii, and scale factors. The renderer resolves these
tokens at render time so every component picks up the active theme
automatically.
Using a named theme
Named themes are plain modules that export theme/0. Pass the module to
use Dala.App:
use Dala.App, theme: Dala.Theme.ObsidianOverride individual tokens without leaving the theme:
use Dala.App, theme: {Dala.Theme.Obsidian, primary: :rose_500}Anyone can publish a theme as a Hex package — any module with theme/0
returning a Dala.Theme.t() works:
use Dala.App, theme: AcmeCorp.BrandThemeBuilding a theme from scratch
Pass a keyword list of overrides against the neutral base:
use Dala.App, theme: [primary: :emerald_500, type_scale: 1.1]Or change the theme at runtime (e.g. for accessibility or user preference):
Dala.Theme.set(Dala.Theme.Obsidian)
Dala.Theme.set({Dala.Theme.Obsidian, type_scale: 1.2})
Dala.Theme.set(primary: :pink_500)Base theme
When no theme is set the renderer uses the neutral base — plain dark grays with a standard blue primary. Functional, not opinionated. Good enough for hello world; swap in a named theme when you want personality.
Token reference
Semantic color tokens
:primary — main action colour (default :blue_500)
:on_primary — text/icons on primary (default :white)
:secondary — secondary action colour (default :gray_600)
:on_secondary — text/icons on secondary (default :white)
:background — page/screen background (default :gray_900)
:on_background — text on background (default :gray_100)
:surface — card / sheet background (default :gray_800)
:surface_raised — elevated card background (default :gray_700)
:on_surface — text/icons on surface (default :gray_100)
:muted — secondary/placeholder text (default :gray_500)
:error — error state colour (default :red_500)
:on_error — text/icons on error (default :white)
:border — dividers and outlines (default :gray_700)Spacing tokens (scaled by space_scale)
:space_xs → 4 × scale
:space_sm → 8 × scale
:space_md → 16 × scale
:space_lg → 24 × scale
:space_xl → 32 × scaleRadius tokens
:radius_sm → theme.radius_sm (default 6)
:radius_md → theme.radius_md (default 10)
:radius_lg → theme.radius_lg (default 16)
:radius_pill → theme.radius_pill (default 100)Line-height tokens (scaled by type_scale)
:line_height_tight → 1.25
:line_height_normal → 1.5
:line_height_relaxed → 1.75Scale factors
type_scale: 1.0 # multiply all text sizes by this
space_scale: 1.0 # multiply all spacing tokens by this
Summary
Functions
Build a theme from a keyword list of overrides against the neutral base.
Returns the current OS appearance: :light or :dark.
Return the currently active theme (or the neutral base if none is set).
Return the neutral base theme.
Returns true if the OS accessibility setting "Reduce Motion" is enabled.
Resolve a design token to its current value.
Set the active theme. Accepts
Override the accent (primary) color of the current theme.
Types
@type color_value() :: atom() | non_neg_integer()
@type t() :: %Dala.Theme.Theme{ background: term(), border: term(), error: term(), line_height_normal: term(), line_height_relaxed: term(), line_height_tight: term(), muted: term(), on_background: term(), on_error: term(), on_primary: term(), on_secondary: term(), on_surface: term(), primary: term(), radius_lg: term(), radius_md: term(), radius_pill: term(), radius_sm: term(), secondary: term(), space_scale: term(), surface: term(), surface_raised: term(), type_scale: term() }
Functions
Build a theme from a keyword list of overrides against the neutral base.
Dala.Theme.build(primary: :emerald_500, type_scale: 1.1)
@spec color_scheme() :: :light | :dark
Returns the current OS appearance: :light or :dark.
Reads from the platform NIF (UITraitCollection.userInterfaceStyle on
iOS, Configuration.uiMode & UI_MODE_NIGHT_MASK on Android). Falls back
to :light when running on the host BEAM (no NIF loaded), on platforms
that don't expose appearance, or on legacy Android apps that haven't
added dalaBridge.getColorScheme() yet.
@spec current() :: t()
Return the currently active theme (or the neutral base if none is set).
@spec default() :: t()
Return the neutral base theme.
@spec prefers_reduced_motion() :: boolean()
Returns true if the OS accessibility setting "Reduce Motion" is enabled.
Reads from the platform NIF. Falls back to false when running on the
host BEAM (no NIF loaded) or on platforms that don't expose the setting.
@spec resolve(atom()) :: non_neg_integer()
Resolve a design token to its current value.
Color tokens return ARGB integers, spacing/radius tokens return integers.
Dala.Theme.resolve(:primary) #=> 0xFF3B82F6
Dala.Theme.resolve(:space_md) #=> 16
Dala.Theme.resolve(:radius_pill) #=> 100
Set the active theme. Accepts:
- A compiled
%Dala.Theme{}struct - A theme module (
Dala.Theme.Obsidian) - A
{module, overrides}tuple - A keyword list of overrides against the neutral base
@spec set_accent(atom() | non_neg_integer()) :: :ok
Override the accent (primary) color of the current theme.
Accepts any color value — raw ARGB integer or named color token.
:on_primary is automatically chosen for WCAG contrast (white for dark
colors, near-black for light colors).
Dala.Theme.set_accent(:violet_500)
Dala.Theme.set_accent(0xFF8B5CF6)