# `Mob.Theme`
[🔗](https://github.com/genericjam/mob/blob/main/lib/mob/theme.ex#L1)

Design token system for Mob apps.

A theme is a compiled `%Mob.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 Mob.App`:

    use Mob.App, theme: Mob.Theme.Obsidian

Override individual tokens without leaving the theme:

    use Mob.App, theme: {Mob.Theme.Obsidian, primary: :rose_500}

Anyone can publish a theme as a Hex package — any module with `theme/0`
returning a `Mob.Theme.t()` works:

    use Mob.App, theme: AcmeCorp.BrandTheme

## Building a theme from scratch

Pass a keyword list of overrides against the neutral base:

    use Mob.App, theme: [primary: :emerald_500, type_scale: 1.1]

Or change the theme at runtime (e.g. for accessibility or user preference):

    Mob.Theme.set(Mob.Theme.Obsidian)
    Mob.Theme.set({Mob.Theme.Obsidian, type_scale: 1.2})
    Mob.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 × scale

### Radius 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)

### Scale factors

    type_scale:  1.0  # multiply all text sizes by this
    space_scale: 1.0  # multiply all spacing tokens by this

# `color_value`

```elixir
@type color_value() :: atom() | non_neg_integer()
```

# `t`

```elixir
@type t() :: %Mob.Theme{
  background: term(),
  border: term(),
  error: 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()
}
```

# `build`

```elixir
@spec build(keyword()) :: t()
```

Build a theme from a keyword list of overrides against the neutral base.

    Mob.Theme.build(primary: :emerald_500, type_scale: 1.1)

# `current`

```elixir
@spec current() :: t()
```

Return the currently active theme (or the neutral base if none is set).

# `default`

```elixir
@spec default() :: t()
```

Return the neutral base theme.

# `set`

```elixir
@spec set(t() | module() | {module(), keyword()} | keyword()) :: :ok
```

Set the active theme. Accepts:

- A compiled `%Mob.Theme{}` struct
- A theme module (`Mob.Theme.Obsidian`)
- A `{module, overrides}` tuple
- A keyword list of overrides against the neutral base

---

*Consult [api-reference.md](api-reference.md) for complete listing*
