refactor: extract hero_section to shared ShopComponents module
Create a centered hero section component with: - Title (h1) and description (p) - Optional CTA button with preview/live mode support - Configurable background (:base or :sunken) Used in: home page (with CTA), about page (without CTA) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
b2869514cb
commit
f5b7693b96
@ -859,4 +859,79 @@ defmodule SimpleshopThemeWeb.ShopComponents do
|
|||||||
|> Enum.reject(&(&1 == ""))
|
|> Enum.reject(&(&1 == ""))
|
||||||
|> Enum.join(" ")
|
|> Enum.join(" ")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Renders a centered hero section with title, description, and optional CTA.
|
||||||
|
|
||||||
|
## Attributes
|
||||||
|
|
||||||
|
* `title` - Required. The main heading text.
|
||||||
|
* `description` - Required. The description paragraph text.
|
||||||
|
* `background` - Background style. Either `:base` (default) or `:sunken`.
|
||||||
|
* `cta_text` - Optional. Text for the CTA button.
|
||||||
|
* `cta_page` - Optional. Page to navigate to on click (for preview mode).
|
||||||
|
* `mode` - Either `:live` (default) or `:preview`.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
<.hero_section
|
||||||
|
title="Original designs, printed on demand"
|
||||||
|
description="From art prints to apparel – unique products created by independent artists."
|
||||||
|
cta_text="Shop the collection"
|
||||||
|
cta_page="collection"
|
||||||
|
mode={:preview}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<.hero_section
|
||||||
|
title="About the studio"
|
||||||
|
description="Nature photography, printed with care"
|
||||||
|
background={:sunken}
|
||||||
|
/>
|
||||||
|
"""
|
||||||
|
attr :title, :string, required: true
|
||||||
|
attr :description, :string, required: true
|
||||||
|
attr :background, :atom, default: :base
|
||||||
|
attr :cta_text, :string, default: nil
|
||||||
|
attr :cta_page, :string, default: nil
|
||||||
|
attr :cta_href, :string, default: nil
|
||||||
|
attr :mode, :atom, default: :live
|
||||||
|
|
||||||
|
def hero_section(assigns) do
|
||||||
|
~H"""
|
||||||
|
<section
|
||||||
|
class="text-center"
|
||||||
|
style={"padding: var(--space-2xl) var(--space-lg); background-color: var(--t-surface-#{@background});"}
|
||||||
|
>
|
||||||
|
<h1
|
||||||
|
class="text-3xl md:text-4xl mb-4"
|
||||||
|
style="font-family: var(--t-font-heading); font-weight: var(--t-heading-weight); letter-spacing: var(--t-heading-tracking); color: var(--t-text-primary);"
|
||||||
|
>
|
||||||
|
<%= @title %>
|
||||||
|
</h1>
|
||||||
|
<p class="text-lg max-w-lg mx-auto mb-8" style="color: var(--t-text-secondary); line-height: 1.6;">
|
||||||
|
<%= @description %>
|
||||||
|
</p>
|
||||||
|
<%= if @cta_text do %>
|
||||||
|
<%= if @mode == :preview do %>
|
||||||
|
<button
|
||||||
|
phx-click="change_preview_page"
|
||||||
|
phx-value-page={@cta_page}
|
||||||
|
class="px-6 py-3 font-medium transition-all"
|
||||||
|
style="background-color: hsl(var(--t-accent-h) var(--t-accent-s) var(--t-accent-l)); color: var(--t-text-inverse); border-radius: var(--t-radius-button); cursor: pointer; border: none;"
|
||||||
|
>
|
||||||
|
<%= @cta_text %>
|
||||||
|
</button>
|
||||||
|
<% else %>
|
||||||
|
<a
|
||||||
|
href={@cta_href || "/products"}
|
||||||
|
class="inline-block px-6 py-3 font-medium transition-all"
|
||||||
|
style="background-color: hsl(var(--t-accent-h) var(--t-accent-s) var(--t-accent-l)); color: var(--t-text-inverse); border-radius: var(--t-radius-button); text-decoration: none;"
|
||||||
|
>
|
||||||
|
<%= @cta_text %>
|
||||||
|
</a>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
</section>
|
||||||
|
"""
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -13,14 +13,11 @@
|
|||||||
<!-- Content Page -->
|
<!-- Content Page -->
|
||||||
<main id="main-content" class="content-page" style="background-color: var(--t-surface-base);">
|
<main id="main-content" class="content-page" style="background-color: var(--t-surface-base);">
|
||||||
<!-- Hero Section -->
|
<!-- Hero Section -->
|
||||||
<div class="content-hero text-center" style="padding: var(--space-2xl) var(--space-lg); background-color: var(--t-surface-sunken);">
|
<.hero_section
|
||||||
<h1 class="text-3xl md:text-4xl mb-3" style="font-family: var(--t-font-heading); font-weight: var(--t-heading-weight); letter-spacing: var(--t-heading-tracking); color: var(--t-text-primary);">
|
title="About the studio"
|
||||||
About the studio
|
description="Nature photography, printed with care"
|
||||||
</h1>
|
background={:sunken}
|
||||||
<p class="text-lg" style="color: var(--t-text-secondary);">
|
/>
|
||||||
Nature photography, printed with care
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Content Body -->
|
<!-- Content Body -->
|
||||||
<div class="content-body" style="padding: var(--space-xl) var(--space-lg); max-width: 800px; margin: 0 auto;">
|
<div class="content-body" style="padding: var(--space-xl) var(--space-lg); max-width: 800px; margin: 0 auto;">
|
||||||
|
|||||||
@ -12,22 +12,13 @@
|
|||||||
|
|
||||||
<!-- Hero Section -->
|
<!-- Hero Section -->
|
||||||
<main id="main-content">
|
<main id="main-content">
|
||||||
<section class="text-center" style="padding: var(--space-2xl) var(--space-lg); background-color: var(--t-surface-base);">
|
<.hero_section
|
||||||
<h1 class="text-3xl md:text-4xl mb-4" style="font-family: var(--t-font-heading); font-weight: var(--t-heading-weight); letter-spacing: var(--t-heading-tracking); color: var(--t-text-primary);">
|
title="Original designs, printed on demand"
|
||||||
Original designs, printed on demand
|
description="From art prints to apparel – unique products created by independent artists and delivered straight to your door."
|
||||||
</h1>
|
cta_text="Shop the collection"
|
||||||
<p class="text-lg max-w-lg mx-auto mb-8" style="color: var(--t-text-secondary); line-height: 1.6;">
|
cta_page="collection"
|
||||||
From art prints to apparel – unique products created by independent artists and delivered straight to your door.
|
mode={:preview}
|
||||||
</p>
|
/>
|
||||||
<button
|
|
||||||
phx-click="change_preview_page"
|
|
||||||
phx-value-page="collection"
|
|
||||||
class="px-6 py-3 font-medium transition-all"
|
|
||||||
style="background-color: hsl(var(--t-accent-h) var(--t-accent-s) var(--t-accent-l)); color: var(--t-text-inverse); border-radius: var(--t-radius-button); cursor: pointer; border: none;"
|
|
||||||
>
|
|
||||||
Shop the collection
|
|
||||||
</button>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<!-- Categories -->
|
<!-- Categories -->
|
||||||
<section style="padding: var(--space-xl) var(--space-lg); background-color: var(--t-surface-base);">
|
<section style="padding: var(--space-xl) var(--space-lg); background-color: var(--t-surface-base);">
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user