Search documentation of Plushie

# Plushie.Type.Theme (Plushie v0.7.2)

Copy Markdown View Source

Built-in iced themes and custom palette support.

Each built-in theme is an atom that maps to the corresponding `iced::Theme` variant on the Rust side. Custom themes are plain maps that the renderer parses into an `iced::Theme::custom()` palette.

## Extended palette shade overrides

Custom themes automatically generate shade variants (strong, weak, etc.) from the six core palette colors using iced's Oklch-based algorithm. If you need precise control over specific shades, you can override them with flat keys in the theme map. Shade overrides only apply to custom themes -- built-in themes are not affected.

Each shade key targets a specific `Pair` (background color + text color) in the extended palette. Append `_text` to any shade key to override the text color for that shade.

### Color families (base, weak, strong)

`primary`, `success`, `warning`, `danger` are core palette seeds (set via `custom/2`). `secondary` is auto-derived from `background` and `text` by iced's palette generator.

All five families support shade overrides: `{family}_base`, `{family}_weak`, `{family}_strong`, plus `_text` variants.

### Background family (8 levels)

`background_base`, `background_weakest`, `background_weaker`, `background_weak`, `background_neutral`, `background_strong`, `background_stronger`, `background_strongest`, plus `_text` variants.

### Example

    # Custom theme with shade overrides
    theme = %{
      name: "my-theme",
      background: "#1a1a2e",
      text: "#e0e0e0",
      primary: "#0f3460",
      primary_strong: "#1a5276",
      primary_strong_text: "#ffffff",
      background_weakest: "#0d0d1a"
    }

Any shade key you omit keeps the auto-generated value.

## Widget chrome colour tokens

Custom themes can also carry theme-level colour tokens for cursor and scrollbar styling:

- `cursor_color`
- `scrollbar_color`
- `scroller_color`

These values are cast as colours and sent in the custom theme map. The renderer uses scrollbar tokens as scrollable defaults. The cursor token applies to focused text entry widgets through iced's focused text style, and explicit widget text styling still wins.

## Summary

### Types

builtin()
t()

### Functions

builtin_themes()

Returns the list of all known built-in theme atoms.

cast(v)

Validates a theme value.

custom(name, opts \\ [])

Build a custom theme palette map.

valid_custom_keys()

Returns the set of valid keys for `custom/2` (excluding `:base`, which is handled separately).

## Types

# builtin()

    @type builtin() ::
      :ferra
      | :oxocarbon
      | :nightfly
      | :moonfly
      | :kanagawa_lotus
      | :kanagawa_dragon
      | :kanagawa_wave
      | :tokyo_night_light
      | :tokyo_night_storm
      | :tokyo_night
      | :catppuccin_mocha
      | :catppuccin_macchiato
      | :catppuccin_frappe
      | :catppuccin_latte
      | :gruvbox_dark
      | :gruvbox_light
      | :solarized_dark
      | :solarized_light
      | :nord
      | :dracula
      | :dark
      | :light

# t()

    @type t() :: builtin() | :system | map()

## Functions

# builtin_themes()

    @spec builtin_themes() :: [atom()]

Returns the list of all known built-in theme atoms.

# cast(v)

    @spec cast(term()) :: {:ok, t()} | :error

Validates a theme value.

Accepts built-in theme atoms, `:system`, or a custom theme map (a map with at least a `:name` key).

## Examples

    iex> Plushie.Type.Theme.cast(:dark)
    {:ok, :dark}

    iex> Plushie.Type.Theme.cast(:system)
    {:ok, :system}

    iex> Plushie.Type.Theme.cast(%{name: "custom"})
    {:ok, %{name: "custom"}}

    iex> Plushie.Type.Theme.cast(:bogus)
    :error

# custom(name, opts \\ [])

    @spec custom(name :: String.t(), opts :: keyword()) :: map()

Build a custom theme palette map.

The returned map is passed through to the Rust renderer, which uses it to construct an `iced::Theme::custom()` with a modified `Palette`.

## Options

- `:base` - built-in theme atom to use as the palette starting point
- `:background` - page background color
- `:text` - default text color
- `:primary` - primary accent color
- `:success` - success color
- `:danger` - danger color
- `:warning` - warning color
- `:cursor_color` - text cursor color
- `:scrollbar_color` - scrollbar track color
- `:scroller_color` - scrollbar handle color

All color values accept any form `Color.cast/1` supports (hex strings or named atoms). Shade override keys (e.g. `primary_strong`, `background_weakest`, `primary_strong_text`) are also accepted and cast as colors.

Note: `:secondary` is not a core seed. It is auto-derived from `:background` and `:text` by iced's palette generator. To customize the secondary palette, use shade overrides: `secondary_base`, `secondary_weak`, `secondary_strong` (plus `_text` variants).

Unknown keys raise `ArgumentError`. Use `valid_custom_keys/0` for the complete set.

## Examples

    iex> Plushie.Type.Theme.custom("Tokyo Remix", primary: "#7aa2f7", danger: "#f7768e")
    %{name: "Tokyo Remix", primary: "#7aa2f7", danger: "#f7768e"}

    iex> Plushie.Type.Theme.custom("Nord+", base: :nord, primary: "#88c0d0")
    %{name: "Nord+", base: "nord", primary: "#88c0d0"}

# valid_custom_keys()

    @spec valid_custom_keys() :: MapSet.t(atom())

Returns the set of valid keys for `custom/2` (excluding `:base`, which is handled separately).