feat: enhance contact page with newsletter and social cards
Add newsletter_card component with :card and :inline variants to share between footer and contact page. Add social_links_card component with full-width icon+text cards for better discoverability. Improve contact_form with optional email link and response time display, keeping important contact info above the fold. Reorganize contact page layout with form on left, info cards on right. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
1f5498d7d8
commit
6b45846d6d
30
ROADMAP.md
30
ROADMAP.md
@ -339,29 +339,7 @@ This ensures sellers never unknowingly sell at a loss due to Printify price chan
|
|||||||
|
|
||||||
## Quick Wins (Low Effort)
|
## Quick Wins (Low Effort)
|
||||||
|
|
||||||
### Enhanced Contact Page
|
*(None pending)*
|
||||||
**Status:** Not implemented
|
|
||||||
**Effort:** Small
|
|
||||||
|
|
||||||
The current contact page has subtle footer social icons that are easy to miss. Improvements:
|
|
||||||
|
|
||||||
1. **Newsletter signup card** - Prominent card encouraging newsletter subscription as the best way to stay updated (already in footer, but deserves dedicated placement)
|
|
||||||
|
|
||||||
2. **Social media links card** - Full-width card listing social platforms with icons and text labels:
|
|
||||||
```
|
|
||||||
[Instagram icon] Instagram
|
|
||||||
[Patreon icon] Patreon
|
|
||||||
[TikTok icon] TikTok
|
|
||||||
[Facebook icon] Facebook
|
|
||||||
[Pinterest icon] Pinterest
|
|
||||||
```
|
|
||||||
This makes social links more discoverable than the current small footer icons.
|
|
||||||
|
|
||||||
**Implementation:**
|
|
||||||
- Add `newsletter_card/1` component to ShopComponents
|
|
||||||
- Add `social_links_card/1` component with configurable platforms
|
|
||||||
- Update contact page template to include both cards
|
|
||||||
- Consider making platforms configurable via theme settings
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -488,3 +466,9 @@ The project is currently named `simpleshop_theme` (reflecting its origins as a t
|
|||||||
- Current page is not a link (avoids self-links)
|
- Current page is not a link (avoids self-links)
|
||||||
- Logo links to home except when on home page
|
- Logo links to home except when on home page
|
||||||
- `aria-current="page"` with visual underline indicator
|
- `aria-current="page"` with visual underline indicator
|
||||||
|
|
||||||
|
### Enhanced Contact Page ✅
|
||||||
|
- `newsletter_card` component with `:card` and `:inline` variants (shared with footer)
|
||||||
|
- `social_links_card` component with icon + text label cards
|
||||||
|
- Contact form with integrated email link and response time
|
||||||
|
- Reorganized layout: contact form left, info cards right
|
||||||
|
|||||||
@ -15,7 +15,7 @@
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<div class="grid gap-8 md:grid-cols-2 mb-12">
|
<div class="grid gap-8 md:grid-cols-2 mb-12">
|
||||||
<.contact_form />
|
<.contact_form email="hello@example.com" response_time="We typically respond within 24 hours" />
|
||||||
|
|
||||||
<div class="space-y-6">
|
<div class="space-y-6">
|
||||||
<.order_tracking_card />
|
<.order_tracking_card />
|
||||||
@ -26,9 +26,9 @@
|
|||||||
%{label: "Returns", value: "Happy to help with faulty or damaged items"}
|
%{label: "Returns", value: "Happy to help with faulty or damaged items"}
|
||||||
]} />
|
]} />
|
||||||
|
|
||||||
<.contact_info_card email="hello@example.com" />
|
<.newsletter_card />
|
||||||
|
|
||||||
<.social_links />
|
<.social_links_card />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
|
|||||||
@ -147,30 +147,7 @@ defmodule SimpleshopThemeWeb.ShopComponents do
|
|||||||
<footer style="background-color: var(--t-surface-raised); border-top: 1px solid var(--t-border-default);">
|
<footer style="background-color: var(--t-surface-raised); border-top: 1px solid var(--t-border-default);">
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
|
||||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-12">
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-12">
|
||||||
<!-- Newsletter -->
|
<.newsletter_card variant={:inline} />
|
||||||
<div>
|
|
||||||
<h3 class="text-xl font-bold mb-2" style="font-family: var(--t-font-heading); color: var(--t-text-primary); font-weight: var(--t-heading-weight);">
|
|
||||||
Stay in touch
|
|
||||||
</h3>
|
|
||||||
<p class="mb-4 text-sm" style="color: var(--t-text-secondary);">
|
|
||||||
Get 10% off your first order and be the first to know about new designs.
|
|
||||||
</p>
|
|
||||||
<form class="flex flex-wrap gap-2">
|
|
||||||
<input
|
|
||||||
type="email"
|
|
||||||
placeholder="your@email.com"
|
|
||||||
class="flex-1 min-w-0 px-4 py-2 text-sm"
|
|
||||||
style="background-color: var(--t-surface-base); color: var(--t-text-primary); border: 1px solid var(--t-border-default); border-radius: var(--t-radius-input); min-width: 150px;"
|
|
||||||
/>
|
|
||||||
<button
|
|
||||||
type="submit"
|
|
||||||
class="px-6 py-2 font-medium transition-all text-sm whitespace-nowrap"
|
|
||||||
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);"
|
|
||||||
>
|
|
||||||
Subscribe
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Links -->
|
<!-- Links -->
|
||||||
<div class="grid grid-cols-2 gap-8">
|
<div class="grid grid-cols-2 gap-8">
|
||||||
@ -1479,13 +1456,18 @@ defmodule SimpleshopThemeWeb.ShopComponents do
|
|||||||
## Attributes
|
## Attributes
|
||||||
|
|
||||||
* `title` - Optional. Form heading. Defaults to "Send us a message".
|
* `title` - Optional. Form heading. Defaults to "Send us a message".
|
||||||
|
* `email` - Optional. If provided, displays "or email us at [email]" below the title.
|
||||||
|
* `response_time` - Optional. Response time text shown below email (e.g., "We typically respond within 24 hours").
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
<.contact_form />
|
<.contact_form />
|
||||||
<.contact_form title="Get in touch" />
|
<.contact_form title="Get in touch" />
|
||||||
|
<.contact_form email="hello@example.com" response_time="We typically respond within 24 hours" />
|
||||||
"""
|
"""
|
||||||
attr :title, :string, default: "Send us a message"
|
attr :title, :string, default: "Send us a message"
|
||||||
|
attr :email, :string, default: nil
|
||||||
|
attr :response_time, :string, default: nil
|
||||||
|
|
||||||
def contact_form(assigns) do
|
def contact_form(assigns) do
|
||||||
~H"""
|
~H"""
|
||||||
@ -1493,9 +1475,21 @@ defmodule SimpleshopThemeWeb.ShopComponents do
|
|||||||
class="p-8"
|
class="p-8"
|
||||||
style="background-color: var(--t-surface-raised); border: 1px solid var(--t-border-default); border-radius: var(--t-radius-card);"
|
style="background-color: var(--t-surface-raised); border: 1px solid var(--t-border-default); border-radius: var(--t-radius-card);"
|
||||||
>
|
>
|
||||||
<h2 class="text-xl font-bold mb-6" style="font-family: var(--t-font-heading); color: var(--t-text-primary);">
|
<h2 class="text-xl font-bold mb-2" style="font-family: var(--t-font-heading); color: var(--t-text-primary);">
|
||||||
<%= @title %>
|
<%= @title %>
|
||||||
</h2>
|
</h2>
|
||||||
|
<%= if @email || @response_time do %>
|
||||||
|
<div class="mb-6 text-sm space-y-1" style="color: var(--t-text-secondary);">
|
||||||
|
<%= if @email do %>
|
||||||
|
<p>or email <a href={"mailto:#{@email}"} style="color: hsl(var(--t-accent-h) var(--t-accent-s) var(--t-accent-l));"><%= @email %></a></p>
|
||||||
|
<% end %>
|
||||||
|
<%= if @response_time do %>
|
||||||
|
<p><%= @response_time %></p>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
<% else %>
|
||||||
|
<div class="mb-4"></div>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
<form class="space-y-4">
|
<form class="space-y-4">
|
||||||
<div>
|
<div>
|
||||||
@ -1667,6 +1661,124 @@ defmodule SimpleshopThemeWeb.ShopComponents do
|
|||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Renders a newsletter signup card.
|
||||||
|
|
||||||
|
## Attributes
|
||||||
|
|
||||||
|
* `title` - Optional. Card heading. Defaults to "Stay in touch".
|
||||||
|
* `description` - Optional. Card description.
|
||||||
|
* `button_text` - Optional. Button text. Defaults to "Subscribe".
|
||||||
|
* `variant` - Optional. Either `:card` (default, with border/background) or `:inline` (no card styling, for embedding in footer).
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
<.newsletter_card />
|
||||||
|
<.newsletter_card title="Join our newsletter" description="Get updates on new products." />
|
||||||
|
<.newsletter_card variant={:inline} />
|
||||||
|
"""
|
||||||
|
attr :title, :string, default: "Stay in touch"
|
||||||
|
attr :description, :string, default: "Be the first to see new designs and get updates from the studio."
|
||||||
|
attr :button_text, :string, default: "Subscribe"
|
||||||
|
attr :variant, :atom, default: :card
|
||||||
|
|
||||||
|
def newsletter_card(%{variant: :inline} = assigns) do
|
||||||
|
~H"""
|
||||||
|
<div>
|
||||||
|
<h3 class="text-xl font-bold mb-2" style="font-family: var(--t-font-heading); color: var(--t-text-primary); font-weight: var(--t-heading-weight);">
|
||||||
|
<%= @title %>
|
||||||
|
</h3>
|
||||||
|
<p class="text-sm mb-4" style="color: var(--t-text-secondary);">
|
||||||
|
<%= @description %>
|
||||||
|
</p>
|
||||||
|
<form class="flex flex-wrap gap-2">
|
||||||
|
<input
|
||||||
|
type="email"
|
||||||
|
placeholder="your@email.com"
|
||||||
|
class="flex-1 min-w-0 px-4 py-2 text-sm"
|
||||||
|
style="background-color: var(--t-surface-base); color: var(--t-text-primary); border: 1px solid var(--t-border-default); border-radius: var(--t-radius-input); min-width: 150px;"
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
class="px-6 py-2 text-sm font-medium whitespace-nowrap"
|
||||||
|
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);"
|
||||||
|
>
|
||||||
|
<%= @button_text %>
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
"""
|
||||||
|
end
|
||||||
|
|
||||||
|
def newsletter_card(assigns) do
|
||||||
|
~H"""
|
||||||
|
<div
|
||||||
|
class="p-6"
|
||||||
|
style="background-color: var(--t-surface-raised); border: 1px solid var(--t-border-default); border-radius: var(--t-radius-card);"
|
||||||
|
>
|
||||||
|
<h3 class="font-bold mb-2" style="color: var(--t-text-primary);"><%= @title %></h3>
|
||||||
|
<p class="text-sm mb-4" style="color: var(--t-text-secondary);">
|
||||||
|
<%= @description %>
|
||||||
|
</p>
|
||||||
|
<form class="flex flex-wrap gap-2">
|
||||||
|
<input
|
||||||
|
type="email"
|
||||||
|
placeholder="your@email.com"
|
||||||
|
class="flex-1 min-w-0 px-3 py-2 text-sm"
|
||||||
|
style="background-color: var(--t-surface-base); color: var(--t-text-primary); border: 1px solid var(--t-border-default); border-radius: var(--t-radius-input); min-width: 150px;"
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
class="px-4 py-2 text-sm font-medium whitespace-nowrap"
|
||||||
|
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);"
|
||||||
|
>
|
||||||
|
<%= @button_text %>
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
"""
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Renders social media links as full-width cards with icons and text labels.
|
||||||
|
|
||||||
|
## Attributes
|
||||||
|
|
||||||
|
* `links` - Optional. List of maps with `platform`, `url`, and `label` keys.
|
||||||
|
Supported platforms: :instagram, :pinterest, :facebook, :twitter, :tiktok
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
<.social_links_card />
|
||||||
|
<.social_links_card links={[%{platform: :instagram, url: "https://instagram.com/example", label: "Follow on Instagram"}]} />
|
||||||
|
"""
|
||||||
|
attr :links, :list, default: [
|
||||||
|
%{platform: :instagram, url: "#", label: "Follow on Instagram"},
|
||||||
|
%{platform: :pinterest, url: "#", label: "Follow on Pinterest"}
|
||||||
|
]
|
||||||
|
|
||||||
|
def social_links_card(assigns) do
|
||||||
|
~H"""
|
||||||
|
<div class="space-y-2">
|
||||||
|
<%= for link <- @links do %>
|
||||||
|
<a
|
||||||
|
href={link.url}
|
||||||
|
class="flex items-center gap-3 p-4 transition-all hover:opacity-80"
|
||||||
|
style="background-color: var(--t-surface-raised); border: 1px solid var(--t-border-default); border-radius: var(--t-radius-card); color: var(--t-text-primary); text-decoration: none;"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="w-10 h-10 flex items-center justify-center flex-shrink-0"
|
||||||
|
style="background-color: var(--t-surface-base); border-radius: var(--t-radius-button); color: var(--t-text-secondary);"
|
||||||
|
>
|
||||||
|
<.social_icon platform={link.platform} />
|
||||||
|
</span>
|
||||||
|
<span class="font-medium"><%= link.label %></span>
|
||||||
|
</a>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
"""
|
||||||
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Renders social media icon links.
|
Renders social media icon links.
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user