# `PhiaUi.Theme`
[🔗](https://github.com/charlenopires/PhiaUI/blob/v0.1.17/lib/phia_ui/theme.ex#L1)

Theme definition struct and API for PhiaUI.

A `%PhiaUi.Theme{}` describes a complete visual design system: color palettes
for light and dark modes, typographic scale, border radius, and shadow
definitions.

## Color format

All color values use **OKLCH** notation (CSS Color Level 4), for example:

    "oklch(0.546 0.245 262.881)"

OKLCH is a perceptually uniform color space that provides:

- **Wider gamut** — can express P3 and Rec2020 colors beyond sRGB.
- **Perceptual uniformity** — equal numeric steps produce equal perceptual
  differences, making it easy to construct accessible color ramps.
- **Predictable lightness** — the `L` channel maps directly to human-perceived
  lightness, so dark-mode pairs are straightforward to reason about.

## Color token mapping

Each theme defines the following semantic tokens (both light and dark variants):

| Token                  | Usage                                              |
|------------------------|----------------------------------------------------|
| `background`           | Page / panel background                            |
| `foreground`           | Default text color                                 |
| `card`                 | Card surface background                            |
| `card_foreground`      | Text on cards                                      |
| `popover`              | Popover / dropdown background                      |
| `popover_foreground`   | Text in popovers                                   |
| `primary`              | Primary action color (buttons, links)              |
| `primary_foreground`   | Text on primary-colored surfaces                   |
| `secondary`            | Secondary / subtle surface                         |
| `secondary_foreground` | Text on secondary surfaces                         |
| `muted`                | Muted / disabled surface                           |
| `muted_foreground`     | Muted / placeholder text                           |
| `accent`               | Hover / focus highlight surface                    |
| `accent_foreground`    | Text on accent surfaces                            |
| `destructive`          | Error / delete action color                        |
| `destructive_foreground` | Text on destructive surfaces                     |
| `border`               | Default border color                               |
| `input`                | Form input border color                            |
| `ring`                 | Focus ring color                                   |
| `sidebar_background`   | Sidebar / navigation rail background               |

Token keys with underscores (e.g., `card_foreground`) are converted to
hyphenated CSS custom properties (e.g., `--color-card-foreground`) by
`PhiaUi.ThemeCSS`.

## Built-in presets

Use `PhiaUi.Theme.get/1` to retrieve a built-in preset by atom key:

    {:ok, theme} = PhiaUi.Theme.get(:blue)
    {:ok, theme} = PhiaUi.Theme.get(:zinc)

## Available presets

| Key        | Description                              |
|------------|------------------------------------------|
| `:zinc`    | Neutral dark — shadcn/ui default         |
| `:slate`   | Cool blue-grey, slightly cooler than zinc|
| `:blue`    | Enterprise blue, vibrant primary         |
| `:rose`    | Modern rose/pink, warm and playful       |
| `:orange`  | Energetic orange, bold and attention-    |
| `:green`   | Success green, calm and natural          |
| `:violet`  | Premium violet, creative and distinctive |
| `:neutral` | Pure achromatic grey, zero chroma        |

## JSON schema

Themes can be serialised to / deserialised from JSON via `PhiaUi.ThemeCSS`:

    %{
      "name"  => "my-brand",
      "label" => "My Brand",
      "colors" => %{
        "light" => %{"background" => "oklch(1 0 0)", ...},
        "dark"  => %{"background" => "oklch(0.145 0 0)", ...}
      },
      "radius"     => "0.5rem",
      "typography" => %{"font_sans" => "Inter, system-ui, sans-serif"},
      "shadows"    => %{}
    }

## Custom themes

You can construct a `%PhiaUi.Theme{}` directly and pass it to
`PhiaUi.ThemeCSS.generate/2`:

    theme = %PhiaUi.Theme{
      name: "brand",
      label: "Acme Brand",
      radius: "0.25rem",
      colors: %{
        light: %{background: "oklch(1 0 0)", primary: "oklch(0.6 0.2 30)", ...},
        dark:  %{background: "oklch(0.1 0 0)", primary: "oklch(0.6 0.2 30)", ...}
      }
    }

    css = PhiaUi.ThemeCSS.generate(theme)

# `color_map`

```elixir
@type color_map() :: %{required(atom()) =&gt; String.t()}
```

# `t`

```elixir
@type t() :: %PhiaUi.Theme{
  colors: %{light: color_map(), dark: color_map()},
  label: String.t(),
  name: String.t(),
  radius: String.t(),
  shadows: map(),
  typography: map()
}
```

# `from_map`

```elixir
@spec from_map(map()) :: t()
```

Creates a `%PhiaUi.Theme{}` struct from a JSON-decoded map.

Accepts string keys as produced by `Jason.decode/1`. Both light and dark
color maps are converted to atom-keyed maps internally (e.g.,
`"card_foreground"` becomes `:card_foreground`).

Falls back to sensible defaults when optional fields (`radius`, `typography`,
`shadows`) are absent from the map.

## Example

    iex> map = %{
    ...>   "name" => "custom",
    ...>   "label" => "Custom",
    ...>   "colors" => %{
    ...>     "light" => %{"background" => "oklch(1 0 0)"},
    ...>     "dark"  => %{"background" => "oklch(0.1 0 0)"}
    ...>   }
    ...> }
    iex> theme = PhiaUi.Theme.from_map(map)
    iex> theme.name
    "custom"

# `get`

```elixir
@spec get(atom()) :: {:ok, t()} | {:error, :not_found}
```

Retrieves a built-in preset theme by its atom key.

Returns `{:ok, %PhiaUi.Theme{}}` on success or `{:error, :not_found}` when
the key is not a known preset.

## Examples

    iex> {:ok, theme} = PhiaUi.Theme.get(:blue)
    iex> theme.name
    "blue"
    iex> theme.label
    "Blue"

    iex> PhiaUi.Theme.get(:unknown)
    {:error, :not_found}

# `get!`

```elixir
@spec get!(atom()) :: t()
```

Retrieves a built-in preset theme by its atom key, raising on failure.

Prefer `get/1` in application code. Use this variant in scripts or tests
where a missing theme is a programming error.

## Examples

    iex> theme = PhiaUi.Theme.get!(:zinc)
    iex> theme.name
    "zinc"

Raises `ArgumentError` for unknown keys:

    iex> PhiaUi.Theme.get!(:unknown)
    ** (ArgumentError) Unknown theme preset: :unknown

# `list`

```elixir
@spec list() :: [atom()]
```

Returns all available built-in preset theme names as a list of atoms.

The order is not guaranteed; sort the result if you need stable ordering.

## Example

    iex> themes = PhiaUi.Theme.list()
    iex> :zinc in themes
    true
    iex> :blue in themes
    true

# `to_map`

```elixir
@spec to_map(t()) :: map()
```

Converts a `%PhiaUi.Theme{}` to a JSON-serialisable map with string keys.

The output map is suitable for passing to `Jason.encode!/1` or for storing
in a database. Atom keys in `colors`, `typography`, and `shadows` are
stringified.

## Example

    iex> theme = PhiaUi.Theme.get!(:zinc)
    iex> map = PhiaUi.Theme.to_map(theme)
    iex> map["name"]
    "zinc"
    iex> is_map(map["colors"]["light"])
    true

---

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