fix navigation links, footer categories, product card structure, and social icons

- add missing cta_href to hero section and error page CTAs
- replace hardcoded footer shop links with real product categories
- restructure product cards with stretched-link pattern so category
  badges link to their collection page
- unify social icons: footer and contact page share the same default
  links from a single source in content.ex
- add search implementation plan (docs/plans/search.md, deferred)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
jamey
2026-02-11 08:17:19 +00:00
parent ac46c1504f
commit 209ae7aee7
15 changed files with 186 additions and 161 deletions

View File

@@ -8,6 +8,7 @@
cart_subtotal={@cart_subtotal}
cart_drawer_open={assigns[:cart_drawer_open] || false}
cart_status={assigns[:cart_status]}
categories={assigns[:categories] || []}
active_page="cart"
>
<main id="main-content" class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">

View File

@@ -8,6 +8,7 @@
cart_subtotal={@cart_subtotal}
cart_drawer_open={assigns[:cart_drawer_open] || false}
cart_status={assigns[:cart_status]}
categories={assigns[:categories] || []}
active_page="checkout"
>
<main id="main-content" class="max-w-3xl mx-auto px-4 sm:px-6 lg:px-8 py-16">

View File

@@ -8,6 +8,7 @@
cart_subtotal={@cart_subtotal}
cart_drawer_open={assigns[:cart_drawer_open] || false}
cart_status={assigns[:cart_status]}
categories={assigns[:categories] || []}
active_page="collection"
>
<main id="main-content">

View File

@@ -8,6 +8,7 @@
cart_subtotal={@cart_subtotal}
cart_drawer_open={assigns[:cart_drawer_open] || false}
cart_status={assigns[:cart_status]}
categories={assigns[:categories] || []}
active_page="contact"
>
<main id="main-content" class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-16">
@@ -34,13 +35,7 @@
<.newsletter_card />
<.social_links_card links={[
%{platform: :instagram, url: "https://instagram.com", label: "Instagram"},
%{platform: :bluesky, url: "https://bsky.app", label: "Bluesky"},
%{platform: :mastodon, url: "https://mastodon.social", label: "Mastodon"},
%{platform: :kofi, url: "https://ko-fi.com", label: "Ko-fi"},
%{platform: :github, url: "https://github.com", label: "GitHub"}
]} />
<.social_links_card />
</div>
</div>
</main>

View File

@@ -8,6 +8,7 @@
cart_subtotal={@cart_subtotal}
cart_drawer_open={assigns[:cart_drawer_open] || false}
cart_status={assigns[:cart_status]}
categories={assigns[:categories] || []}
active_page={@active_page}
>
<main id="main-content" class="content-page" style="background-color: var(--t-surface-base);">

View File

@@ -8,6 +8,7 @@
cart_subtotal={@cart_subtotal}
cart_drawer_open={assigns[:cart_drawer_open] || false}
cart_status={assigns[:cart_status]}
categories={assigns[:categories] || []}
active_page="error"
error_page
>
@@ -24,8 +25,10 @@
description={@error_description}
cta_text="Go to Homepage"
cta_page="home"
cta_href="/"
secondary_cta_text="Browse Products"
secondary_cta_page="collection"
secondary_cta_href="/collections/all"
mode={@mode}
/>

View File

@@ -8,6 +8,7 @@
cart_subtotal={@cart_subtotal}
cart_drawer_open={assigns[:cart_drawer_open] || false}
cart_status={assigns[:cart_status]}
categories={assigns[:categories] || []}
active_page="home"
>
<main id="main-content">
@@ -16,6 +17,7 @@
description="Welcome to the SimpleShop demo store. This is where your hero text goes something short and punchy about what makes your shop worth a browse."
cta_text="Shop the collection"
cta_page="collection"
cta_href="/collections/all"
mode={@mode}
/>
@@ -34,6 +36,7 @@
image_url="/mockups/mountain-sunrise-print-3-800.webp"
link_text="Learn more about the studio →"
link_page="about"
link_href="/about"
mode={@mode}
/>
</main>

View File

@@ -8,6 +8,7 @@
cart_subtotal={@cart_subtotal}
cart_drawer_open={assigns[:cart_drawer_open] || false}
cart_status={assigns[:cart_status]}
categories={assigns[:categories] || []}
active_page="pdp"
>
<main id="main-content" class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">

View File

@@ -5,6 +5,14 @@ defmodule SimpleshopThemeWeb.ShopComponents.Content do
import SimpleshopThemeWeb.ShopComponents.Base
@default_social_links [
%{platform: :instagram, url: "https://instagram.com", label: "Instagram"},
%{platform: :bluesky, url: "https://bsky.app", label: "Bluesky"},
%{platform: :mastodon, url: "https://mastodon.social", label: "Mastodon"},
%{platform: :kofi, url: "https://ko-fi.com", label: "Ko-fi"},
%{platform: :github, url: "https://github.com", label: "GitHub"}
]
@doc """
Renders a content body container for long-form content pages (about, etc.).
@@ -338,11 +346,7 @@ defmodule SimpleshopThemeWeb.ShopComponents.Content do
"""
attr :title, :string, default: "Find me on"
attr :links, :list,
default: [
%{platform: :instagram, url: "#", label: "Instagram"},
%{platform: :pinterest, url: "#", label: "Pinterest"}
]
attr :links, :list, default: @default_social_links
def social_links_card(assigns) do
~H"""
@@ -381,11 +385,7 @@ defmodule SimpleshopThemeWeb.ShopComponents.Content do
<.social_links />
<.social_links links={[%{platform: :instagram, url: "https://instagram.com/example", label: "Instagram"}]} />
"""
attr :links, :list,
default: [
%{platform: :instagram, url: "https://instagram.com", label: "Instagram"},
%{platform: :pinterest, url: "https://pinterest.com", label: "Pinterest"}
]
attr :links, :list, default: @default_social_links
def social_links(assigns) do
~H"""

View File

@@ -65,6 +65,7 @@ defmodule SimpleshopThemeWeb.ShopComponents.Layout do
attr :cart_subtotal, :string, required: true
attr :cart_drawer_open, :boolean, default: false
attr :cart_status, :string, default: nil
attr :categories, :list, default: []
attr :active_page, :string, required: true
attr :error_page, :boolean, default: false
@@ -95,7 +96,7 @@ defmodule SimpleshopThemeWeb.ShopComponents.Layout do
{render_slot(@inner_block)}
<.shop_footer theme_settings={@theme_settings} mode={@mode} />
<.shop_footer theme_settings={@theme_settings} mode={@mode} categories={@categories} />
<.cart_drawer
cart_items={@cart_items}
@@ -405,6 +406,7 @@ defmodule SimpleshopThemeWeb.ShopComponents.Layout do
"""
attr :theme_settings, :map, required: true
attr :mode, :atom, default: :live
attr :categories, :list, default: []
def shop_footer(assigns) do
assigns = assign(assigns, :current_year, Date.utc_today().year)
@@ -437,28 +439,19 @@ defmodule SimpleshopThemeWeb.ShopComponents.Layout do
All products
</a>
</li>
<li>
<a
href="#"
phx-click="change_preview_page"
phx-value-page="collection"
class="transition-colors hover:opacity-80"
style="color: var(--t-text-secondary); cursor: pointer;"
>
New arrivals
</a>
</li>
<li>
<a
href="#"
phx-click="change_preview_page"
phx-value-page="collection"
class="transition-colors hover:opacity-80"
style="color: var(--t-text-secondary); cursor: pointer;"
>
Best sellers
</a>
</li>
<%= for category <- @categories do %>
<li>
<a
href="#"
phx-click="change_preview_page"
phx-value-page="collection"
class="transition-colors hover:opacity-80"
style="color: var(--t-text-secondary); cursor: pointer;"
>
{category.name}
</a>
</li>
<% end %>
<% else %>
<li>
<a
@@ -469,24 +462,17 @@ defmodule SimpleshopThemeWeb.ShopComponents.Layout do
All products
</a>
</li>
<li>
<a
href="/collections/all"
class="transition-colors hover:opacity-80"
style="color: var(--t-text-secondary);"
>
New arrivals
</a>
</li>
<li>
<a
href="/collections/all"
class="transition-colors hover:opacity-80"
style="color: var(--t-text-secondary);"
>
Best sellers
</a>
</li>
<%= for category <- @categories do %>
<li>
<a
href={"/collections/#{category.slug}"}
class="transition-colors hover:opacity-80"
style="color: var(--t-text-secondary);"
>
{category.name}
</a>
</li>
<% end %>
<% end %>
</ul>
</div>
@@ -594,48 +580,7 @@ defmodule SimpleshopThemeWeb.ShopComponents.Layout do
<p class="text-xs" style="color: var(--t-text-tertiary);">
© {@current_year} {@theme_settings.site_name}
</p>
<div class="flex gap-2">
<a
href="https://instagram.com"
target="_blank"
rel="noopener noreferrer"
class="social-link w-9 h-9 flex items-center justify-center transition-all"
style="color: var(--t-text-secondary); border-radius: var(--t-radius-button);"
aria-label="Instagram"
>
<svg
class="w-5 h-5"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
>
<rect x="2" y="2" width="20" height="20" rx="5" ry="5"></rect>
<path d="M16 11.37A4 4 0 1 1 12.63 8 4 4 0 0 1 16 11.37z"></path>
<line x1="17.5" y1="6.5" x2="17.51" y2="6.5"></line>
</svg>
</a>
<a
href="https://pinterest.com"
target="_blank"
rel="noopener noreferrer"
class="social-link w-9 h-9 flex items-center justify-center transition-all"
style="color: var(--t-text-secondary); border-radius: var(--t-radius-button);"
aria-label="Pinterest"
>
<svg
class="w-5 h-5"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
>
<circle cx="12" cy="12" r="10"></circle>
<path d="M8 12c0-2.2 1.8-4 4-4s4 1.8 4 4-1.8 4-4 4"></path>
<line x1="12" y1="16" x2="9" y2="21"></line>
</svg>
</a>
</div>
<.social_links />
</div>
</div>
</footer>

View File

@@ -59,58 +59,22 @@ defmodule SimpleshopThemeWeb.ShopComponents.Product do
end)
~H"""
<%= if @clickable_resolved do %>
<%= if @mode == :preview do %>
<a
href="#"
phx-click="change_preview_page"
phx-value-page="pdp"
class={card_classes(@variant)}
style={card_style(@variant)}
>
<.product_card_inner
product={@product}
theme_settings={@theme_settings}
variant={@variant}
priority={@priority}
show_category={@show_category_resolved}
show_badges={@show_badges_resolved}
show_delivery_text={@show_delivery_text_resolved}
/>
</a>
<% else %>
<a
href={"/products/#{@product[:slug] || @product[:id]}"}
class={card_classes(@variant)}
style={card_style(@variant)}
>
<.product_card_inner
product={@product}
theme_settings={@theme_settings}
variant={@variant}
priority={@priority}
show_category={@show_category_resolved}
show_badges={@show_badges_resolved}
show_delivery_text={@show_delivery_text_resolved}
/>
</a>
<% end %>
<% else %>
<div
class={card_classes(@variant)}
style={card_style(@variant)}
>
<.product_card_inner
product={@product}
theme_settings={@theme_settings}
variant={@variant}
priority={@priority}
show_category={@show_category_resolved}
show_badges={@show_badges_resolved}
show_delivery_text={@show_delivery_text_resolved}
/>
</div>
<% end %>
<article
class={card_classes(@variant)}
style={card_style(@variant) <> if(@clickable_resolved, do: " position: relative;", else: "")}
>
<.product_card_inner
product={@product}
theme_settings={@theme_settings}
variant={@variant}
priority={@priority}
show_category={@show_category_resolved}
show_badges={@show_badges_resolved}
show_delivery_text={@show_delivery_text_resolved}
clickable={@clickable_resolved}
mode={@mode}
/>
</article>
"""
end
@@ -121,6 +85,8 @@ defmodule SimpleshopThemeWeb.ShopComponents.Product do
attr :show_category, :boolean, required: true
attr :show_badges, :boolean, required: true
attr :show_delivery_text, :boolean, required: true
attr :clickable, :boolean, default: true
attr :mode, :atom, default: :live
defp product_card_inner(assigns) do
assigns =
@@ -171,12 +137,47 @@ defmodule SimpleshopThemeWeb.ShopComponents.Product do
</div>
<div class={content_padding_class(@variant)}>
<%= if @show_category && @product[:category] do %>
<p class="text-xs mb-1" style="color: var(--t-text-tertiary);">
{@product.category}
</p>
<%= if @mode == :preview do %>
<p
class="text-xs mb-1"
style="color: var(--t-text-tertiary); position: relative; z-index: 1;"
>
{@product.category}
</p>
<% else %>
<a
href={"/collections/#{Slug.slugify(@product.category)}"}
class="text-xs mb-1 block hover:underline"
style="color: var(--t-text-tertiary); text-decoration: none; position: relative; z-index: 1;"
>
{@product.category}
</a>
<% end %>
<% end %>
<h3 class={title_classes(@variant)} style={title_style(@variant)}>
{@product.name}
<%= if @clickable do %>
<%= if @mode == :preview do %>
<a
href="#"
phx-click="change_preview_page"
phx-value-page="pdp"
class="stretched-link"
style="color: inherit; text-decoration: none;"
>
{@product.name}
</a>
<% else %>
<a
href={"/products/#{@product[:slug] || @product[:id]}"}
class="stretched-link"
style="color: inherit; text-decoration: none;"
>
{@product.name}
</a>
<% end %>
<% else %>
{@product.name}
<% end %>
</h3>
<%= if @theme_settings.show_prices do %>
<.product_price product={@product} variant={@variant} />