From a8c0e150c8449a0bf4e7d3ac71574a7b5905746c Mon Sep 17 00:00:00 2001 From: Jamey Greenwood Date: Thu, 1 Jan 2026 16:16:05 +0000 Subject: [PATCH] feat: enhance theme customization with layout controls and real product images MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- assets/css/theme-layer2-attributes.css | 144 ++++++++++- assets/css/theme-semantic.css | 27 ++- .../settings/theme_settings.ex | 4 +- lib/simpleshop_theme/theme/presets.ex | 74 +++--- lib/simpleshop_theme/theme/preview_data.ex | 58 ++--- lib/simpleshop_theme_web.ex | 2 +- .../live/theme_live/index.ex | 24 ++ .../live/theme_live/index.html.heex | 92 +++++++- .../live/theme_live/preview_pages.ex | 223 ++++++++++++++++-- .../theme_live/preview_pages/about.html.heex | 116 +++++---- .../theme_live/preview_pages/cart.html.heex | 13 +- .../preview_pages/collection.html.heex | 39 ++- .../preview_pages/contact.html.heex | 13 +- .../theme_live/preview_pages/error.html.heex | 15 +- .../theme_live/preview_pages/home.html.heex | 223 +++++++++--------- .../theme_live/preview_pages/pdp.html.heex | 15 +- 16 files changed, 793 insertions(+), 289 deletions(-) diff --git a/assets/css/theme-layer2-attributes.css b/assets/css/theme-layer2-attributes.css index 8d18ee9..09eb997 100644 --- a/assets/css/theme-layer2-attributes.css +++ b/assets/css/theme-layer2-attributes.css @@ -63,7 +63,7 @@ .preview-frame[data-typography="editorial"] { --t-font-heading: var(--p-font-fraunces); --t-font-body: var(--p-font-source); - --t-heading-weight: 600; + --t-heading-weight: 700; --t-heading-tracking: -0.02em; } @@ -171,9 +171,23 @@ display: flex; } +/* Standard header - logo left, nav center, cart right */ +.preview-frame[data-header="standard"] .shop-header { + justify-content: space-between; +} + +/* Centered header - logo on top, nav and cart on same row below */ .preview-frame[data-header="centered"] .shop-header { - flex-direction: column; - gap: 0.75rem; + flex-wrap: wrap; + justify-content: center; + gap: 0.5rem 1.5rem; + padding-top: 1.5rem; + padding-bottom: 1.5rem; +} + +.preview-frame[data-header="centered"] .shop-logo { + width: 100%; + justify-content: center; text-align: center; } @@ -181,6 +195,126 @@ justify-content: center; } -.preview-frame[data-header="minimal"] .shop-nav { - display: none !important; +.preview-frame[data-header="centered"] .shop-cart { + /* Cart flows inline with nav, no absolute positioning */ +} + +/* Left header - logo and nav grouped left, cart right */ +.preview-frame[data-header="left"] .shop-header { + justify-content: flex-start; + gap: 2rem; +} + +.preview-frame[data-header="left"] .shop-cart { + margin-left: auto; +} + +/* Sticky header */ +.preview-frame[data-sticky="true"] .shop-header { + position: sticky; + top: 0; + z-index: 50; +} + +/* Layout Width */ +.preview-frame[data-layout="contained"] .max-w-7xl { + max-width: 1024px; +} + +.preview-frame[data-layout="wide"] .max-w-7xl { + max-width: 1280px; +} + +.preview-frame[data-layout="full"] .max-w-7xl { + max-width: 100%; + padding-left: 2rem; + padding-right: 2rem; +} + +/* Card Shadow */ +.preview-frame[data-shadow="none"] .product-card, +.preview-frame[data-shadow="none"] .category-card { + box-shadow: none; +} + +.preview-frame[data-shadow="sm"] .product-card, +.preview-frame[data-shadow="sm"] .category-card { + box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05); +} + +.preview-frame[data-shadow="md"] .product-card, +.preview-frame[data-shadow="md"] .category-card { + box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1); +} + +.preview-frame[data-shadow="lg"] .product-card, +.preview-frame[data-shadow="lg"] .category-card { + box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1); +} + +/* Product Badges */ +.product-badge { + position: absolute; + top: 0.5rem; + left: 0.5rem; + padding: 0.25rem 0.5rem; + font-size: 0.75rem; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.025em; + border-radius: var(--t-radius-sm, 4px); + z-index: 10; +} + +.badge-sale { + background-color: var(--t-sale-color, #dc2626); + color: #ffffff; +} + +.badge-new { + background-color: hsl(var(--t-accent-h) var(--t-accent-s) var(--t-accent-l)); + color: var(--t-text-inverse); +} + +/* Product Hover Image */ +.product-image-container { + position: relative; +} + +.product-image-hover { + position: absolute; + inset: 0; + opacity: 0; + transition: opacity 0.3s ease; +} + +.product-card:hover .product-image-hover { + opacity: 1; +} + +.product-card:hover .product-image-primary { + opacity: 0; +} + +/* Social Links */ +.social-link:hover { + background-color: var(--t-surface-sunken); + color: var(--t-text-primary); +} + +/* Header Icon Buttons */ +.header-icon-btn:hover { + background-color: var(--t-surface-sunken); + color: var(--t-text-primary); +} + +/* Search Modal Animation */ +.search-modal { + opacity: 1; + transition: opacity 0.2s ease; +} + +.search-modal-content { + transform: translateY(0); + transition: transform 0.2s ease; } diff --git a/assets/css/theme-semantic.css b/assets/css/theme-semantic.css index 2f436be..973eeeb 100644 --- a/assets/css/theme-semantic.css +++ b/assets/css/theme-semantic.css @@ -3,9 +3,12 @@ Semantic aliases for easy usage ======================================== */ -:root { +.preview-frame, .shop-root { /* Accent color - HSL components set dynamically by CSS generator */ - /* Derived accent colors use the dynamic HSL values */ + --t-accent-h: 24; + --t-accent-s: 95%; + --t-accent-l: 53%; + --t-accent: hsl(var(--t-accent-h) var(--t-accent-s) var(--t-accent-l)); --t-accent-hover: hsl(var(--t-accent-h) var(--t-accent-s) calc(var(--t-accent-l) - 8%)); --t-accent-subtle: hsl(var(--t-accent-h) 40% 95%); @@ -15,8 +18,9 @@ --t-secondary-accent: #ea580c; --t-sale-color: #dc2626; - /* Density multiplier */ - --t-density: 1; + /* Font size scale */ + --t-font-size-scale: 1; + --t-heading-weight: 600; /* Layout */ --t-layout-max-width: 1400px; @@ -48,6 +52,14 @@ --weight-heading: var(--t-heading-weight); --tracking-heading: var(--t-heading-tracking); + /* Density-aware spacing */ + --space-xs: calc(var(--p-space-2) * var(--t-density)); + --space-sm: calc(var(--p-space-3) * var(--t-density)); + --space-md: calc(var(--p-space-4) * var(--t-density)); + --space-lg: calc(var(--p-space-6) * var(--t-density)); + --space-xl: calc(var(--p-space-8) * var(--t-density)); + --space-2xl: calc(var(--p-space-12) * var(--t-density)); + /* Border radius */ --radius-button: var(--t-radius-button); --radius-card: var(--t-radius-card); @@ -59,7 +71,7 @@ 0 1px 2px hsl(var(--p-shadow-color) / calc(var(--p-shadow-strength) * 0.5)), 0 1px 3px hsl(var(--p-shadow-color) / var(--p-shadow-strength)); --shadow-md: - 0 2px 4px hsl(var(--p-shadow-color) / calc(--p-shadow-strength) * 0.5)), + 0 2px 4px hsl(var(--p-shadow-color) / calc(var(--p-shadow-strength) * 0.5)), 0 4px 8px hsl(var(--p-shadow-color) / var(--p-shadow-strength)), 0 8px 16px hsl(var(--p-shadow-color) / calc(var(--p-shadow-strength) * 0.5)); @@ -68,3 +80,8 @@ --transition-normal: var(--p-duration-normal) var(--p-ease-out); --transition-bounce: var(--p-duration-normal) var(--p-ease-out-back); } + +/* Dark mode accent-subtle override */ +.preview-frame[data-mood="dark"], .shop-root[data-mood="dark"] { + --t-accent-subtle: hsl(var(--t-accent-h) 30% 15%); +} diff --git a/lib/simpleshop_theme/settings/theme_settings.ex b/lib/simpleshop_theme/settings/theme_settings.ex index 9191b0a..ebc5086 100644 --- a/lib/simpleshop_theme/settings/theme_settings.ex +++ b/lib/simpleshop_theme/settings/theme_settings.ex @@ -97,11 +97,13 @@ defmodule SimpleshopTheme.Settings.ThemeSettings do |> validate_inclusion(:shape, ~w(sharp soft round pill)) |> validate_inclusion(:density, ~w(spacious balanced compact)) |> validate_inclusion(:grid_columns, ~w(2 3 4)) - |> validate_inclusion(:header_layout, ~w(standard centered minimal)) + |> validate_inclusion(:header_layout, ~w(standard centered left)) |> validate_inclusion(:logo_mode, ~w(text-only logo-text logo-only)) |> validate_number(:logo_size, greater_than_or_equal_to: 24, less_than_or_equal_to: 120) |> validate_number(:header_zoom, greater_than_or_equal_to: 100, less_than_or_equal_to: 200) |> validate_number(:header_position_x, greater_than_or_equal_to: 0, less_than_or_equal_to: 100) |> validate_number(:header_position_y, greater_than_or_equal_to: 0, less_than_or_equal_to: 100) + |> validate_inclusion(:layout_width, ~w(contained wide full)) + |> validate_inclusion(:card_shadow, ~w(none sm md lg)) end end diff --git a/lib/simpleshop_theme/theme/presets.ex b/lib/simpleshop_theme/theme/presets.ex index a5fb4f2..8e396de 100644 --- a/lib/simpleshop_theme/theme/presets.ex +++ b/lib/simpleshop_theme/theme/presets.ex @@ -1,6 +1,6 @@ defmodule SimpleshopTheme.Theme.Presets do @moduledoc """ - Defines the 9 curated theme presets for SimpleShop. + Defines the 8 curated theme presets for SimpleShop. """ @presets %{ @@ -11,7 +11,10 @@ defmodule SimpleshopTheme.Theme.Presets do density: "spacious", grid_columns: "3", header_layout: "centered", - accent_color: "#e85d04" + accent_color: "#e85d04", + layout_width: "wide", + card_shadow: "sm", + announcement_bar: true }, studio: %{ mood: "neutral", @@ -20,7 +23,10 @@ defmodule SimpleshopTheme.Theme.Presets do density: "balanced", grid_columns: "4", header_layout: "standard", - accent_color: "#3b82f6" + accent_color: "#3b82f6", + layout_width: "wide", + card_shadow: "sm", + announcement_bar: true }, boutique: %{ mood: "warm", @@ -28,8 +34,11 @@ defmodule SimpleshopTheme.Theme.Presets do shape: "soft", density: "balanced", grid_columns: "3", - header_layout: "centered", - accent_color: "#b45309" + header_layout: "left", + accent_color: "#b45309", + layout_width: "contained", + card_shadow: "md", + announcement_bar: true }, bold: %{ mood: "neutral", @@ -38,7 +47,10 @@ defmodule SimpleshopTheme.Theme.Presets do density: "compact", grid_columns: "4", header_layout: "standard", - accent_color: "#dc2626" + accent_color: "#dc2626", + layout_width: "full", + card_shadow: "none", + announcement_bar: true }, playful: %{ mood: "neutral", @@ -47,16 +59,22 @@ defmodule SimpleshopTheme.Theme.Presets do density: "balanced", grid_columns: "4", header_layout: "standard", - accent_color: "#8b5cf6" + accent_color: "#8b5cf6", + layout_width: "wide", + card_shadow: "md", + announcement_bar: true }, minimal: %{ - mood: "cool", - typography: "minimal", + mood: "neutral", + typography: "impulse", shape: "sharp", density: "spacious", grid_columns: "2", - header_layout: "minimal", - accent_color: "#171717" + header_layout: "standard", + accent_color: "#171717", + layout_width: "full", + card_shadow: "none", + announcement_bar: false }, night: %{ mood: "dark", @@ -65,7 +83,10 @@ defmodule SimpleshopTheme.Theme.Presets do density: "balanced", grid_columns: "4", header_layout: "standard", - accent_color: "#f97316" + accent_color: "#f97316", + layout_width: "wide", + card_shadow: "lg", + announcement_bar: true }, classic: %{ mood: "warm", @@ -74,22 +95,10 @@ defmodule SimpleshopTheme.Theme.Presets do density: "spacious", grid_columns: "3", header_layout: "standard", - accent_color: "#166534" - }, - impulse: %{ - mood: "neutral", - typography: "impulse", - shape: "sharp", - density: "spacious", - grid_columns: "3", - header_layout: "centered", - accent_color: "#000000", - font_size: "medium", - heading_weight: "regular", - layout_width: "full", - button_style: "filled", - card_shadow: "none", - product_text_align: "center" + accent_color: "#166534", + layout_width: "contained", + card_shadow: "sm", + announcement_bar: true } } @@ -99,14 +108,13 @@ defmodule SimpleshopTheme.Theme.Presets do boutique: "Warm & sophisticated", bold: "High contrast, strong", playful: "Fun & approachable", - minimal: "Understated & modern", + minimal: "Light & airy", night: "Dark & dramatic", - classic: "Traditional & refined", - impulse: "Light & airy" + 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)a + @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. @@ -141,7 +149,7 @@ defmodule SimpleshopTheme.Theme.Presets do ## Examples iex> list_names() - [:gallery, :studio, :boutique, :bold, :playful, :minimal, :night, :classic, :impulse] + [:gallery, :studio, :boutique, :bold, :playful, :minimal, :night, :classic] """ def list_names do diff --git a/lib/simpleshop_theme/theme/preview_data.ex b/lib/simpleshop_theme/theme/preview_data.ex index d4c4bf1..70d3054 100644 --- a/lib/simpleshop_theme/theme/preview_data.ex +++ b/lib/simpleshop_theme/theme/preview_data.ex @@ -79,8 +79,8 @@ defmodule SimpleshopTheme.Theme.PreviewData do description: "Soft, breathable cotton tee perfect for everyday wear", price: 2999, compare_at_price: nil, - image_url: "https://placehold.co/600x800/e5e5e5/525252?text=Cotton+Tee", - hover_image_url: "https://placehold.co/600x800/d4d4d4/525252?text=Cotton+Tee", + image_url: "https://images.unsplash.com/photo-1521572163474-6864f9cf17ab?w=600&h=800&fit=crop&q=80", + hover_image_url: "https://images.unsplash.com/photo-1622445275576-721325763afe?w=600&h=800&fit=crop&q=80", category: "Clothing", in_stock: true, on_sale: false @@ -91,8 +91,8 @@ defmodule SimpleshopTheme.Theme.PreviewData do description: "Handcrafted genuine leather bag with adjustable strap", price: 8999, compare_at_price: 11999, - image_url: "https://placehold.co/600x800/d4a574/1c1917?text=Leather+Bag", - hover_image_url: "https://placehold.co/600x800/c49563/1c1917?text=Leather+Bag", + image_url: "https://images.unsplash.com/photo-1548036328-c9fa89d128fa?w=600&h=800&fit=crop&q=80", + hover_image_url: "https://images.unsplash.com/photo-1590874103328-eac38a683ce7?w=600&h=800&fit=crop&q=80", category: "Accessories", in_stock: true, on_sale: true @@ -103,8 +103,8 @@ defmodule SimpleshopTheme.Theme.PreviewData do description: "Handmade ceramic mug with unique glaze finish", price: 2499, compare_at_price: nil, - image_url: "https://placehold.co/600x800/94a3b8/0f172a?text=Coffee+Mug", - hover_image_url: "https://placehold.co/600x800/64748b/0f172a?text=Coffee+Mug", + image_url: "https://images.unsplash.com/photo-1514228742587-6b1558fcca3d?w=600&h=800&fit=crop&q=80", + hover_image_url: "https://images.unsplash.com/photo-1481833761820-0509d3217039?w=600&h=800&fit=crop&q=80", category: "Home", in_stock: true, on_sale: false @@ -115,8 +115,8 @@ defmodule SimpleshopTheme.Theme.PreviewData do description: "Sleek design with Japanese quartz movement", price: 12999, compare_at_price: nil, - image_url: "https://placehold.co/600x800/171717/fafafa?text=Watch", - hover_image_url: "https://placehold.co/600x800/262626/fafafa?text=Watch", + image_url: "https://images.unsplash.com/photo-1523275335684-37898b6baf30?w=600&h=800&fit=crop&q=80", + hover_image_url: "https://images.unsplash.com/photo-1524592094714-0f0654e20314?w=600&h=800&fit=crop&q=80", category: "Accessories", in_stock: true, on_sale: false @@ -127,8 +127,8 @@ defmodule SimpleshopTheme.Theme.PreviewData do description: "Cozy merino wool blanket in herringbone pattern", price: 7999, compare_at_price: 9999, - image_url: "https://placehold.co/600x800/a3a3a3/171717?text=Blanket", - hover_image_url: "https://placehold.co/600x800/8a8a8a/171717?text=Blanket", + image_url: "https://images.unsplash.com/photo-1580301762395-21ce84d00bc6?w=600&h=800&fit=crop&q=80", + hover_image_url: "https://images.unsplash.com/photo-1600369671854-2d9f5db4a5e0?w=600&h=800&fit=crop&q=80", category: "Home", in_stock: false, on_sale: true @@ -139,8 +139,8 @@ defmodule SimpleshopTheme.Theme.PreviewData do description: "Natural handmade soaps with essential oils", price: 3499, compare_at_price: nil, - image_url: "https://placehold.co/600x800/fdf8f3/1c1917?text=Soap+Set", - hover_image_url: "https://placehold.co/600x800/f5ebe0/1c1917?text=Soap+Set", + image_url: "https://images.unsplash.com/photo-1607006344380-b6775a0824a7?w=600&h=800&fit=crop&q=80", + hover_image_url: "https://images.unsplash.com/photo-1600857544200-b2f666a9a2ec?w=600&h=800&fit=crop&q=80", category: "Beauty", in_stock: true, on_sale: false @@ -151,8 +151,8 @@ defmodule SimpleshopTheme.Theme.PreviewData do description: "Classic cut denim jacket with vintage wash", price: 8499, compare_at_price: nil, - image_url: "https://placehold.co/600x800/3b82f6/ffffff?text=Denim+Jacket", - hover_image_url: "https://placehold.co/600x800/2563eb/ffffff?text=Denim+Jacket", + image_url: "https://images.unsplash.com/photo-1576995853123-5a10305d93c0?w=600&h=800&fit=crop&q=80", + hover_image_url: "https://images.unsplash.com/photo-1601333144130-8cbb312386b6?w=600&h=800&fit=crop&q=80", category: "Clothing", in_stock: true, on_sale: false @@ -163,8 +163,8 @@ defmodule SimpleshopTheme.Theme.PreviewData do description: "Durable organic cotton canvas with reinforced handles", price: 2999, compare_at_price: nil, - image_url: "https://placehold.co/600x800/f5f5f5/171717?text=Tote+Bag", - hover_image_url: "https://placehold.co/600x800/e5e5e5/171717?text=Tote+Bag", + image_url: "https://images.unsplash.com/photo-1622560480605-d83c853bc5c3?w=600&h=800&fit=crop&q=80", + hover_image_url: "https://images.unsplash.com/photo-1597633125097-5a9ae3cb8a8f?w=600&h=800&fit=crop&q=80", category: "Accessories", in_stock: true, on_sale: false @@ -175,8 +175,8 @@ defmodule SimpleshopTheme.Theme.PreviewData do description: "Soy wax candle with cedar and vanilla notes", price: 3299, compare_at_price: 3999, - image_url: "https://placehold.co/600x800/fdf8f3/57534e?text=Candle", - hover_image_url: "https://placehold.co/600x800/f5ebe0/57534e?text=Candle", + image_url: "https://images.unsplash.com/photo-1602028915047-37269d1a73f7?w=600&h=800&fit=crop&q=80", + hover_image_url: "https://images.unsplash.com/photo-1603006905003-be475563bc59?w=600&h=800&fit=crop&q=80", category: "Home", in_stock: true, on_sale: true @@ -187,8 +187,8 @@ defmodule SimpleshopTheme.Theme.PreviewData do description: "Insulated bottle keeps drinks cold for 24 hours", price: 3999, compare_at_price: nil, - image_url: "https://placehold.co/600x800/0a0a0a/fafafa?text=Water+Bottle", - hover_image_url: "https://placehold.co/600x800/171717/fafafa?text=Water+Bottle", + image_url: "https://images.unsplash.com/photo-1602143407151-7111542de6e8?w=600&h=800&fit=crop&q=80", + hover_image_url: "https://images.unsplash.com/photo-1570831739435-6601aa3fa4fb?w=600&h=800&fit=crop&q=80", category: "Accessories", in_stock: true, on_sale: false @@ -199,8 +199,8 @@ defmodule SimpleshopTheme.Theme.PreviewData do description: "Comfortable crew socks in solid colors", price: 1499, compare_at_price: nil, - image_url: "https://placehold.co/600x800/e5e5e5/525252?text=Socks", - hover_image_url: "https://placehold.co/600x800/d4d4d4/525252?text=Socks", + image_url: "https://images.unsplash.com/photo-1586350977771-b3b0abd50c82?w=600&h=800&fit=crop&q=80", + hover_image_url: "https://images.unsplash.com/photo-1582966772680-860e372bb558?w=600&h=800&fit=crop&q=80", category: "Clothing", in_stock: true, on_sale: false @@ -211,8 +211,8 @@ defmodule SimpleshopTheme.Theme.PreviewData do description: "Sustainable bamboo with juice groove", price: 4499, compare_at_price: nil, - image_url: "https://placehold.co/600x800/d4a574/1c1917?text=Cutting+Board", - hover_image_url: "https://placehold.co/600x800/c49563/1c1917?text=Cutting+Board", + image_url: "https://images.unsplash.com/photo-1594226801341-41427b4e5c22?w=600&h=800&fit=crop&q=80", + hover_image_url: "https://images.unsplash.com/photo-1606760227091-3dd870d97f1d?w=600&h=800&fit=crop&q=80", category: "Kitchen", in_stock: true, on_sale: false @@ -296,35 +296,35 @@ defmodule SimpleshopTheme.Theme.PreviewData do name: "Clothing", slug: "clothing", product_count: 3, - image_url: "https://placehold.co/400x300/e5e5e5/525252?text=Clothing" + image_url: "https://images.unsplash.com/photo-1489987707025-afc232f7ea0f?w=400&h=300&fit=crop&q=80" }, %{ id: "2", name: "Accessories", slug: "accessories", product_count: 4, - image_url: "https://placehold.co/400x300/d4a574/1c1917?text=Accessories" + image_url: "https://images.unsplash.com/photo-1606760227091-3dd870d97f1d?w=400&h=300&fit=crop&q=80" }, %{ id: "3", name: "Home", slug: "home", product_count: 3, - image_url: "https://placehold.co/400x300/94a3b8/0f172a?text=Home" + image_url: "https://images.unsplash.com/photo-1616046229478-9901c5536a45?w=400&h=300&fit=crop&q=80" }, %{ id: "4", name: "Kitchen", slug: "kitchen", product_count: 1, - image_url: "https://placehold.co/400x300/fdf8f3/1c1917?text=Kitchen" + image_url: "https://images.unsplash.com/photo-1556909114-f6e7ad7d3136?w=400&h=300&fit=crop&q=80" }, %{ id: "5", name: "Beauty", slug: "beauty", product_count: 1, - image_url: "https://placehold.co/400x300/f5f5f5/171717?text=Beauty" + image_url: "https://images.unsplash.com/photo-1596462502278-27bfdc403348?w=400&h=300&fit=crop&q=80" } ] end diff --git a/lib/simpleshop_theme_web.ex b/lib/simpleshop_theme_web.ex index 8389413..018a115 100644 --- a/lib/simpleshop_theme_web.ex +++ b/lib/simpleshop_theme_web.ex @@ -17,7 +17,7 @@ defmodule SimpleshopThemeWeb do those modules here. """ - def static_paths, do: ~w(assets css fonts images favicon.ico robots.txt) + def static_paths, do: ~w(assets css fonts images favicon.ico robots.txt demo.html) def router do quote do diff --git a/lib/simpleshop_theme_web/live/theme_live/index.ex b/lib/simpleshop_theme_web/live/theme_live/index.ex index f0f5d56..740afec 100644 --- a/lib/simpleshop_theme_web/live/theme_live/index.ex +++ b/lib/simpleshop_theme_web/live/theme_live/index.ex @@ -201,6 +201,30 @@ defmodule SimpleshopThemeWeb.ThemeLive.Index do end end + @impl true + def handle_event("toggle_setting", %{"field" => field}, socket) do + field_atom = String.to_existing_atom(field) + current_value = Map.get(socket.assigns.theme_settings, field_atom) + attrs = %{field_atom => !current_value} + + case Settings.update_theme_settings(attrs) do + {:ok, theme_settings} -> + generated_css = CSSGenerator.generate(theme_settings) + active_preset = Presets.detect_preset(theme_settings) + + socket = + socket + |> assign(:theme_settings, theme_settings) + |> assign(:generated_css, generated_css) + |> assign(:active_preset, active_preset) + + {:noreply, socket} + + {:error, _} -> + {:noreply, socket} + end + end + @impl true def handle_event("save_theme", _params, socket) do socket = put_flash(socket, :info, "Theme saved successfully") diff --git a/lib/simpleshop_theme_web/live/theme_live/index.html.heex b/lib/simpleshop_theme_web/live/theme_live/index.html.heex index 2664ef9..071dd3d 100644 --- a/lib/simpleshop_theme_web/live/theme_live/index.html.heex +++ b/lib/simpleshop_theme_web/live/theme_live/index.html.heex @@ -466,7 +466,7 @@
- <%= for layout <- ["standard", "centered", "minimal"] do %> + <%= for layout <- ["standard", "centered", "left"] do %>
+ +
+ +
+ +
+ +
@@ -518,6 +544,65 @@ <% end %> + +
+ +
+ <%= for {value, label} <- [{"none", "None"}, {"sm", "Subtle"}, {"md", "Medium"}, {"lg", "Strong"}] do %> + + <% end %> +
+
+ + + +
+
+ + + + + + + Layout +
+ +
+ +
+ <%= for width <- ["contained", "wide", "full"] do %> + + <% end %> +
+
@@ -586,7 +671,10 @@ data-shape={@theme_settings.shape} data-density={@theme_settings.density} data-grid={@theme_settings.grid_columns} - data-header={@theme_settings.header_layout}> + data-header={@theme_settings.header_layout} + data-sticky={to_string(@theme_settings.sticky_header)} + data-layout={@theme_settings.layout_width} + data-shadow={@theme_settings.card_shadow}> diff --git a/lib/simpleshop_theme_web/live/theme_live/preview_pages.ex b/lib/simpleshop_theme_web/live/theme_live/preview_pages.ex index fe7f24f..53c133f 100644 --- a/lib/simpleshop_theme_web/live/theme_live/preview_pages.ex +++ b/lib/simpleshop_theme_web/live/theme_live/preview_pages.ex @@ -3,6 +3,22 @@ defmodule SimpleshopThemeWeb.ThemeLive.PreviewPages do embed_templates "preview_pages/*" + @doc """ + Renders the announcement bar. + """ + attr :theme_settings, :map, required: true + + def announcement_bar(assigns) do + ~H""" +
+

Free shipping on orders over $50

+
+ """ + end + @doc """ Renders the shop header with logo based on logo_mode setting. """ @@ -14,19 +30,12 @@ defmodule SimpleshopThemeWeb.ThemeLive.PreviewPages do ~H"""
<%= if @theme_settings.header_background_enabled && @header_image do %>
<% end %> - <%= if @theme_settings.header_layout == "centered" do %> - - <% end %> - - <%= if @theme_settings.header_layout != "minimal" do %> - - <% end %> + -
- +
+ +
""" end - defp header_justify("centered"), do: "justify-content: center; gap: 2rem;" - defp header_justify("minimal"), do: "justify-content: space-between;" - defp header_justify(_), do: "justify-content: space-between;" - defp logo_url(logo_image, %{logo_recolor: true, logo_color: color}) when logo_image.is_svg do clean_color = String.trim_leading(color, "#") "/images/#{logo_image.id}/recolored/#{clean_color}" @@ -101,4 +126,154 @@ defmodule SimpleshopThemeWeb.ThemeLive.PreviewPages do "background-position: #{settings.header_position_x}% #{settings.header_position_y}%; " <> "background-repeat: no-repeat; z-index: 0;" end + + @doc """ + Renders the shop footer with newsletter and links. + """ + attr :theme_settings, :map, required: true + + def shop_footer(assigns) do + ~H""" + + """ + end + + @doc """ + Renders the search modal overlay. + """ + def search_modal(assigns) do + ~H""" + + """ + end end diff --git a/lib/simpleshop_theme_web/live/theme_live/preview_pages/about.html.heex b/lib/simpleshop_theme_web/live/theme_live/preview_pages/about.html.heex index 01102b0..60478ab 100644 --- a/lib/simpleshop_theme_web/live/theme_live/preview_pages/about.html.heex +++ b/lib/simpleshop_theme_web/live/theme_live/preview_pages/about.html.heex @@ -1,70 +1,66 @@ -
+
+ + <%= if @theme_settings.announcement_bar do %> + + <% end %> + -
-

- About Us -

- -

- We're passionate about bringing you the finest products, handpicked with care and attention to detail. -

- -
- Our Story + +
+ +
+

+ About the studio +

+

+ Nature-inspired art, made with care +

-
-

- Our Story -

-

- Founded in 2020, our journey began with a simple mission: to curate and deliver exceptional products that enhance everyday life. We believe that quality shouldn't be compromised, and that's why every item in our collection is carefully selected for its craftsmanship, sustainability, and timeless appeal. -

-

- What started as a small passion project has grown into a community of like-minded individuals who appreciate the finer things in life. We work directly with artisans and makers who share our values of quality, authenticity, and ethical production. -

+ +
+ +
-

- Our Values -

-
-
-

Quality First

-

- Every product is vetted for exceptional quality and durability. -

-
-
-

Sustainability

-

- We prioritize eco-friendly materials and ethical production methods. -

-
-
-

Community

-

- Supporting local artisans and building lasting relationships. -

-
+ +
+

+ Botanical Studio was born from a love of the natural world and a desire to bring its beauty indoors. +

+ +

+ Every illustration starts as a pencil sketch, inspired by the plants and flowers found in British woodlands, meadows, and gardens. These sketches are then refined and printed on museum-quality archival paper using pigment-based inks that will last a lifetime. +

+ +

+ Based in the Yorkshire countryside, I work from a small garden studio surrounded by the very nature that inspires each piece. Every print is checked by hand before being carefully packaged and sent on its way. +

+ +

+ Sustainability +

+

+ I believe beautiful art shouldn't cost the earth. All prints are produced on FSC-certified paper, shipped in plastic-free packaging, and printed locally to reduce transport emissions. +

+ +

+ The process +

+

+ Each botanical illustration takes between 20-40 hours to complete, from initial field sketches through to the final digital refinement. I work primarily in graphite and watercolour, which are then scanned and carefully colour-corrected to ensure the prints match the original artwork. +

- -
-

- Ready to Explore? -

- -
+ + + + + +
diff --git a/lib/simpleshop_theme_web/live/theme_live/preview_pages/cart.html.heex b/lib/simpleshop_theme_web/live/theme_live/preview_pages/cart.html.heex index 114ce94..5142426 100644 --- a/lib/simpleshop_theme_web/live/theme_live/preview_pages/cart.html.heex +++ b/lib/simpleshop_theme_web/live/theme_live/preview_pages/cart.html.heex @@ -1,4 +1,9 @@ -
+
+ + <%= if @theme_settings.announcement_bar do %> + + <% end %> + @@ -109,4 +114,10 @@
+ + + + + +
diff --git a/lib/simpleshop_theme_web/live/theme_live/preview_pages/collection.html.heex b/lib/simpleshop_theme_web/live/theme_live/preview_pages/collection.html.heex index 12b5a1d..434891c 100644 --- a/lib/simpleshop_theme_web/live/theme_live/preview_pages/collection.html.heex +++ b/lib/simpleshop_theme_web/live/theme_live/preview_pages/collection.html.heex @@ -1,4 +1,9 @@ -
+
+ + <%= if @theme_settings.announcement_bar do %> + + <% end %> + @@ -109,25 +114,33 @@ ]}> <%= for product <- @preview_data.products do %>
-
+
+ <%= if product.on_sale do %> -
- SALE -
+ Sale <% end %> <%= if not product.in_stock do %> -
+
Out of Stock
<% end %> + {product.name} + + <%= if product[:hover_image_url] do %> + {product.name} + <% end %>

@@ -153,10 +166,10 @@

<%= if product.in_stock do %> <% end %>
@@ -167,4 +180,10 @@
+ + + + + +
diff --git a/lib/simpleshop_theme_web/live/theme_live/preview_pages/contact.html.heex b/lib/simpleshop_theme_web/live/theme_live/preview_pages/contact.html.heex index bc08f44..2749856 100644 --- a/lib/simpleshop_theme_web/live/theme_live/preview_pages/contact.html.heex +++ b/lib/simpleshop_theme_web/live/theme_live/preview_pages/contact.html.heex @@ -1,4 +1,9 @@ -
+
+ + <%= if @theme_settings.announcement_bar do %> + + <% end %> + @@ -124,4 +129,10 @@
+ + + + + +
diff --git a/lib/simpleshop_theme_web/live/theme_live/preview_pages/error.html.heex b/lib/simpleshop_theme_web/live/theme_live/preview_pages/error.html.heex index 472506d..2c28df6 100644 --- a/lib/simpleshop_theme_web/live/theme_live/preview_pages/error.html.heex +++ b/lib/simpleshop_theme_web/live/theme_live/preview_pages/error.html.heex @@ -1,4 +1,9 @@ -
+
+ + <%= if @theme_settings.announcement_bar do %> + + <% end %> + @@ -35,7 +40,7 @@
<%= for product <- Enum.take(@preview_data.products, 4) do %>
@@ -58,4 +63,10 @@
+ + + + + +
diff --git a/lib/simpleshop_theme_web/live/theme_live/preview_pages/home.html.heex b/lib/simpleshop_theme_web/live/theme_live/preview_pages/home.html.heex index 456e98f..94e37dd 100644 --- a/lib/simpleshop_theme_web/live/theme_live/preview_pages/home.html.heex +++ b/lib/simpleshop_theme_web/live/theme_live/preview_pages/home.html.heex @@ -1,145 +1,142 @@ -
+
+ + <%= if @theme_settings.announcement_bar do %> + + <% end %> + -
-
-
-

- Welcome to Our Store -

-

- Discover our curated collection of handpicked products crafted with care -

- -
-
-
+
+

+ Nature-inspired art prints +

+

+ Original botanical illustrations, printed on premium archival paper. Each piece brings a little bit of the outside, inside. +

+ +
+ + +
+ +
-
-

- Featured Products +
+

+ Featured prints

"lg:grid-cols-2" "3" -> "lg:grid-cols-3" "4" -> "lg:grid-cols-4" _ -> "lg:grid-cols-3" end - ]} style="gap: var(--space-lg);"> - <%= for product <- Enum.take(@preview_data.products, 6) do %> + ]}> + <%= for product <- Enum.take(@preview_data.products, 4) do %>
-
+
+ <%= if product[:is_new] do %> + New + <% end %> + <%= if product.on_sale do %> + Sale + <% end %> {product.name} + <%= if product[:hover_image_url] do %> + {product.name} + <% end %> +
-

+

<%= product.name %>

-

- <%= product.description %> -

-
-
- <%= if product.on_sale do %> - - $<%= product.price / 100 %> - - - $<%= product.compare_at_price / 100 %> - - <% else %> - - $<%= product.price / 100 %> - - <% end %> -
- -
-
-
- <% end %> -
-
- - -
-
-

- What Our Customers Say -

- -
- <%= for testimonial <- Enum.take(@preview_data.testimonials, 3) do %> -
-
- <%= for _ <- 1..testimonial.rating do %> - - - +

+ <%= if product.on_sale do %> + $<%= product.compare_at_price / 100 %> <% end %> -

-

- "<%= testimonial.content %>" -

-

- — <%= testimonial.author %> + $<%= product.price / 100 %>

- <% end %> -
-
-
- - -
-

- Shop by Category -

- -
- <%= for category <- @preview_data.categories do %> -
-
- {category.name} -
-

- <%= category.name %> -

-

- <%= category.product_count %> products -

<% end %>
-
+ +
+ +
+
+ + +
+
+
+

+ Made with care in Yorkshire +

+

+ Every illustration starts as a pencil sketch, inspired by the plants and flowers found in British woodlands, meadows, and gardens. Printed on museum-quality archival paper using pigment-based inks that will last a lifetime. +

+ + Learn more about the studio → + +
+
+ + + + + +

diff --git a/lib/simpleshop_theme_web/live/theme_live/preview_pages/pdp.html.heex b/lib/simpleshop_theme_web/live/theme_live/preview_pages/pdp.html.heex index 1278d67..18c8279 100644 --- a/lib/simpleshop_theme_web/live/theme_live/preview_pages/pdp.html.heex +++ b/lib/simpleshop_theme_web/live/theme_live/preview_pages/pdp.html.heex @@ -1,7 +1,12 @@ <% product = List.first(@preview_data.products) %> -
+
+ + <%= if @theme_settings.announcement_bar do %> + + <% end %> + @@ -145,7 +150,7 @@
<%= for related_product <- Enum.slice(@preview_data.products, 1, 4) do %>
@@ -168,4 +173,10 @@
+ + + + + +