berrypod/lib/simpleshop_theme/theme/presets.ex
Jamey Greenwood a8c0e150c8 feat: enhance theme customization with layout controls and real product images
Add comprehensive layout and styling controls including header layout options (standard, centered, left), content width settings (contained, wide, full), and card shadow levels. Update all theme presets with these new settings. Replace placeholder images with real Unsplash product and category images for more realistic previews. Add announcement bar and sticky header toggle options for enhanced header customization.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-01 16:16:05 +00:00

227 lines
5.0 KiB
Elixir

defmodule SimpleshopTheme.Theme.Presets do
@moduledoc """
Defines the 8 curated theme presets for SimpleShop.
"""
@presets %{
gallery: %{
mood: "warm",
typography: "editorial",
shape: "soft",
density: "spacious",
grid_columns: "3",
header_layout: "centered",
accent_color: "#e85d04",
layout_width: "wide",
card_shadow: "sm",
announcement_bar: true
},
studio: %{
mood: "neutral",
typography: "clean",
shape: "soft",
density: "balanced",
grid_columns: "4",
header_layout: "standard",
accent_color: "#3b82f6",
layout_width: "wide",
card_shadow: "sm",
announcement_bar: true
},
boutique: %{
mood: "warm",
typography: "classic",
shape: "soft",
density: "balanced",
grid_columns: "3",
header_layout: "left",
accent_color: "#b45309",
layout_width: "contained",
card_shadow: "md",
announcement_bar: true
},
bold: %{
mood: "neutral",
typography: "modern",
shape: "sharp",
density: "compact",
grid_columns: "4",
header_layout: "standard",
accent_color: "#dc2626",
layout_width: "full",
card_shadow: "none",
announcement_bar: true
},
playful: %{
mood: "neutral",
typography: "friendly",
shape: "pill",
density: "balanced",
grid_columns: "4",
header_layout: "standard",
accent_color: "#8b5cf6",
layout_width: "wide",
card_shadow: "md",
announcement_bar: true
},
minimal: %{
mood: "neutral",
typography: "impulse",
shape: "sharp",
density: "spacious",
grid_columns: "2",
header_layout: "standard",
accent_color: "#171717",
layout_width: "full",
card_shadow: "none",
announcement_bar: false
},
night: %{
mood: "dark",
typography: "modern",
shape: "soft",
density: "balanced",
grid_columns: "4",
header_layout: "standard",
accent_color: "#f97316",
layout_width: "wide",
card_shadow: "lg",
announcement_bar: true
},
classic: %{
mood: "warm",
typography: "classic",
shape: "soft",
density: "spacious",
grid_columns: "3",
header_layout: "standard",
accent_color: "#166534",
layout_width: "contained",
card_shadow: "sm",
announcement_bar: true
}
}
@descriptions %{
gallery: "Elegant & editorial",
studio: "Clean & professional",
boutique: "Warm & sophisticated",
bold: "High contrast, strong",
playful: "Fun & approachable",
minimal: "Light & airy",
night: "Dark & dramatic",
classic: "Traditional & refined"
}
# Core keys used to match presets (excludes branding-specific settings)
@core_keys ~w(mood typography shape density grid_columns header_layout accent_color layout_width card_shadow announcement_bar)a
@doc """
Returns all available presets.
## Examples
iex> all()
%{gallery: %{...}, studio: %{...}, ...}
"""
def all, do: @presets
@doc """
Gets a preset by name.
## Examples
iex> get(:gallery)
%{mood: "warm", typography: "editorial", ...}
iex> get(:nonexistent)
nil
"""
def get(preset_name) when is_atom(preset_name) do
Map.get(@presets, preset_name)
end
@doc """
Lists all preset names.
## Examples
iex> list_names()
[:gallery, :studio, :boutique, :bold, :playful, :minimal, :night, :classic]
"""
def list_names do
Map.keys(@presets)
end
@doc """
Gets the description for a preset.
## Examples
iex> get_description(:gallery)
"Elegant & editorial"
"""
def get_description(preset_name) when is_atom(preset_name) do
Map.get(@descriptions, preset_name, "")
end
@doc """
Returns all presets with their descriptions.
## Examples
iex> all_with_descriptions()
[{:bold, "High contrast, strong"}, ...]
"""
def all_with_descriptions do
@presets
|> Map.keys()
|> Enum.sort()
|> Enum.map(fn name -> {name, Map.get(@descriptions, name, "")} end)
end
@doc """
Detects which preset matches the current theme settings, if any.
Only compares core theme keys, ignoring branding-specific settings.
## Examples
iex> detect_preset(%ThemeSettings{mood: "warm", typography: "editorial", ...})
:gallery
iex> detect_preset(%ThemeSettings{...customized...})
nil
"""
def detect_preset(theme_settings) do
current_core = extract_core_values(theme_settings)
Enum.find_value(@presets, fn {name, preset} ->
preset_core = Map.take(preset, @core_keys)
if maps_match?(current_core, preset_core) do
name
else
nil
end
end)
end
defp extract_core_values(theme_settings) do
theme_settings
|> Map.from_struct()
|> Map.take(@core_keys)
end
defp maps_match?(map1, map2) do
Enum.all?(@core_keys, fn key ->
Map.get(map1, key) == Map.get(map2, key)
end)
end
end