feat: implement UX pattern improvements for accessibility & performance
Accessibility: - Add skip link component for keyboard navigation - Add visible focus rings on all interactive elements - Add aria-current="page" to navigation active states - Ensure 44px minimum touch targets on header icons and filter pills Product Page (PDP): - Add accordion layout for Description, Size Guide, Shipping & Returns - Convert Reviews section to accordion format (open by default) - Make Add to Basket button sticky on mobile, normal on desktop Product Cards (home & collection): - Add "Free delivery over £40" shipping badge - Add loading="lazy" and decoding="async" to images Cart Drawer: - Add "Delivery: Calculated at checkout" label - Add Remove button to each cart item All Preview Pages: - Add skip link to all 7 preview pages - Wrap main content in <main id="main-content"> - Pass active_page to shop_header for nav highlighting Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
0c43d65a04
commit
aa469ffb50
@ -105,3 +105,77 @@
|
|||||||
.preview-frame[data-mood="dark"], .shop-root[data-mood="dark"] {
|
.preview-frame[data-mood="dark"], .shop-root[data-mood="dark"] {
|
||||||
--t-accent-subtle: hsl(var(--t-accent-h) 30% 15%);
|
--t-accent-subtle: hsl(var(--t-accent-h) 30% 15%);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ========================================
|
||||||
|
ACCESSIBILITY - Focus Rings
|
||||||
|
Visible focus indicators for all interactive elements
|
||||||
|
======================================== */
|
||||||
|
|
||||||
|
/* Base focus ring style */
|
||||||
|
.shop-container a:focus-visible,
|
||||||
|
.shop-container button:focus-visible,
|
||||||
|
.shop-container input:focus-visible,
|
||||||
|
.shop-container select:focus-visible,
|
||||||
|
.shop-container textarea:focus-visible,
|
||||||
|
.shop-container [tabindex]:focus-visible,
|
||||||
|
.shop-container details summary:focus-visible {
|
||||||
|
outline: 2px solid hsl(var(--t-accent-h) var(--t-accent-s) var(--t-accent-l));
|
||||||
|
outline-offset: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove default browser outlines when using focus-visible */
|
||||||
|
.shop-container a:focus:not(:focus-visible),
|
||||||
|
.shop-container button:focus:not(:focus-visible),
|
||||||
|
.shop-container input:focus:not(:focus-visible),
|
||||||
|
.shop-container select:focus:not(:focus-visible),
|
||||||
|
.shop-container textarea:focus:not(:focus-visible) {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Skip link for keyboard navigation */
|
||||||
|
.skip-link {
|
||||||
|
position: absolute;
|
||||||
|
top: -100px;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
background: hsl(var(--t-accent-h) var(--t-accent-s) var(--t-accent-l));
|
||||||
|
color: var(--t-text-inverse);
|
||||||
|
padding: 0.75rem 1.5rem;
|
||||||
|
z-index: 9999;
|
||||||
|
border-radius: var(--t-radius-button);
|
||||||
|
font-weight: 600;
|
||||||
|
text-decoration: none;
|
||||||
|
transition: top 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skip-link:focus {
|
||||||
|
top: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ensure minimum touch target size (44x44px) */
|
||||||
|
.shop-container .header-icon-btn {
|
||||||
|
min-width: 44px;
|
||||||
|
min-height: 44px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shop-container .filter-pill {
|
||||||
|
min-height: 44px;
|
||||||
|
padding-left: 1rem;
|
||||||
|
padding-right: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Nav link styling with active state indicator */
|
||||||
|
.shop-nav a {
|
||||||
|
padding: 0.5rem 0;
|
||||||
|
border-bottom: 2px solid transparent;
|
||||||
|
transition: border-color 0.2s ease, color 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shop-nav a:hover {
|
||||||
|
color: var(--t-text-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.shop-nav a[aria-current="page"] {
|
||||||
|
color: var(--t-text-primary);
|
||||||
|
border-bottom-color: hsl(var(--t-accent-h) var(--t-accent-s) var(--t-accent-l));
|
||||||
|
}
|
||||||
|
|||||||
@ -3,6 +3,17 @@ defmodule SimpleshopThemeWeb.ThemeLive.PreviewPages do
|
|||||||
|
|
||||||
embed_templates "preview_pages/*"
|
embed_templates "preview_pages/*"
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Renders the skip link for keyboard navigation accessibility.
|
||||||
|
"""
|
||||||
|
def skip_link(assigns) do
|
||||||
|
~H"""
|
||||||
|
<a href="#main-content" class="skip-link">
|
||||||
|
Skip to main content
|
||||||
|
</a>
|
||||||
|
"""
|
||||||
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Renders the announcement bar.
|
Renders the announcement bar.
|
||||||
"""
|
"""
|
||||||
@ -25,6 +36,7 @@ defmodule SimpleshopThemeWeb.ThemeLive.PreviewPages do
|
|||||||
attr :theme_settings, :map, required: true
|
attr :theme_settings, :map, required: true
|
||||||
attr :logo_image, :map, default: nil
|
attr :logo_image, :map, default: nil
|
||||||
attr :header_image, :map, default: nil
|
attr :header_image, :map, default: nil
|
||||||
|
attr :active_page, :string, default: nil
|
||||||
|
|
||||||
def shop_header(assigns) do
|
def shop_header(assigns) do
|
||||||
~H"""
|
~H"""
|
||||||
@ -76,10 +88,10 @@ defmodule SimpleshopThemeWeb.ThemeLive.PreviewPages do
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<nav class="shop-nav hidden md:flex" style="gap: 1.5rem; position: relative; z-index: 1;">
|
<nav class="shop-nav hidden md:flex" style="gap: 1.5rem; position: relative; z-index: 1;">
|
||||||
<a href="#" phx-click="change_preview_page" phx-value-page="home" style="color: var(--t-text-secondary); text-decoration: none; cursor: pointer;">Home</a>
|
<a href="#" phx-click="change_preview_page" phx-value-page="home" aria-current={if @active_page == "home", do: "page"} style="color: var(--t-text-secondary); text-decoration: none; cursor: pointer;">Home</a>
|
||||||
<a href="#" phx-click="change_preview_page" phx-value-page="collection" style="color: var(--t-text-secondary); text-decoration: none; cursor: pointer;">Shop</a>
|
<a href="#" phx-click="change_preview_page" phx-value-page="collection" aria-current={if @active_page in ["collection", "pdp"], do: "page"} style="color: var(--t-text-secondary); text-decoration: none; cursor: pointer;">Shop</a>
|
||||||
<a href="#" phx-click="change_preview_page" phx-value-page="about" style="color: var(--t-text-secondary); text-decoration: none; cursor: pointer;">About</a>
|
<a href="#" phx-click="change_preview_page" phx-value-page="about" aria-current={if @active_page == "about", do: "page"} style="color: var(--t-text-secondary); text-decoration: none; cursor: pointer;">About</a>
|
||||||
<a href="#" phx-click="change_preview_page" phx-value-page="contact" style="color: var(--t-text-secondary); text-decoration: none; cursor: pointer;">Contact</a>
|
<a href="#" phx-click="change_preview_page" phx-value-page="contact" aria-current={if @active_page == "contact", do: "page"} style="color: var(--t-text-secondary); text-decoration: none; cursor: pointer;">Contact</a>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<div class="shop-actions flex items-center gap-1" style="position: relative; z-index: 1;">
|
<div class="shop-actions flex items-center gap-1" style="position: relative; z-index: 1;">
|
||||||
@ -266,15 +278,24 @@ defmodule SimpleshopThemeWeb.ThemeLive.PreviewPages do
|
|||||||
<p style="font-family: var(--t-font-body); font-size: var(--t-text-caption); color: var(--t-text-tertiary); margin: 0;">
|
<p style="font-family: var(--t-font-body); font-size: var(--t-text-caption); color: var(--t-text-tertiary); margin: 0;">
|
||||||
<%= item.variant %>
|
<%= item.variant %>
|
||||||
</p>
|
</p>
|
||||||
<p class="cart-drawer-item-price" style="color: var(--t-text-primary); font-weight: 500; margin-top: 4px; font-size: var(--t-text-small);">
|
<div style="display: flex; justify-content: space-between; align-items: center; margin-top: 4px;">
|
||||||
<%= item.price %>
|
<p class="cart-drawer-item-price" style="color: var(--t-text-primary); font-weight: 500; font-size: var(--t-text-small); margin: 0;">
|
||||||
</p>
|
<%= item.price %>
|
||||||
|
</p>
|
||||||
|
<button type="button" style="background: none; border: none; padding: 0; cursor: pointer; font-family: var(--t-font-body); font-size: var(--t-text-caption); color: var(--t-text-tertiary); text-decoration: underline;">
|
||||||
|
Remove
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="cart-drawer-footer" style="padding: 1rem 1.5rem; border-top: 1px solid var(--t-border-default); background: var(--t-surface-sunken);">
|
<div class="cart-drawer-footer" style="padding: 1rem 1.5rem; border-top: 1px solid var(--t-border-default); background: var(--t-surface-sunken);">
|
||||||
|
<div style="display: flex; justify-content: space-between; font-family: var(--t-font-body); font-size: var(--t-text-small); color: var(--t-text-secondary); margin-bottom: 0.5rem;">
|
||||||
|
<span>Delivery</span>
|
||||||
|
<span>Calculated at checkout</span>
|
||||||
|
</div>
|
||||||
<div class="cart-drawer-total" style="display: flex; justify-content: space-between; font-family: var(--t-font-body); font-size: var(--t-text-base); font-weight: 600; color: var(--t-text-primary); margin-bottom: 1rem;">
|
<div class="cart-drawer-total" style="display: flex; justify-content: space-between; font-family: var(--t-font-body); font-size: var(--t-text-base); font-weight: 600; color: var(--t-text-primary); margin-bottom: 1rem;">
|
||||||
<span>Subtotal</span>
|
<span>Subtotal</span>
|
||||||
<span>£72.00</span>
|
<span>£72.00</span>
|
||||||
|
|||||||
@ -1,14 +1,17 @@
|
|||||||
<div class="shop-container min-h-screen" style="position: relative; background-color: var(--t-surface-base); font-family: var(--t-font-body); color: var(--t-text-primary);">
|
<div class="shop-container min-h-screen" style="position: relative; background-color: var(--t-surface-base); font-family: var(--t-font-body); color: var(--t-text-primary);">
|
||||||
|
<!-- Skip Link for Accessibility -->
|
||||||
|
<SimpleshopThemeWeb.ThemeLive.PreviewPages.skip_link />
|
||||||
|
|
||||||
<!-- Announcement Bar -->
|
<!-- Announcement Bar -->
|
||||||
<%= if @theme_settings.announcement_bar do %>
|
<%= if @theme_settings.announcement_bar do %>
|
||||||
<SimpleshopThemeWeb.ThemeLive.PreviewPages.announcement_bar theme_settings={@theme_settings} />
|
<SimpleshopThemeWeb.ThemeLive.PreviewPages.announcement_bar theme_settings={@theme_settings} />
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<!-- Header -->
|
<!-- Header -->
|
||||||
<SimpleshopThemeWeb.ThemeLive.PreviewPages.shop_header theme_settings={@theme_settings} logo_image={@logo_image} header_image={@header_image} />
|
<SimpleshopThemeWeb.ThemeLive.PreviewPages.shop_header theme_settings={@theme_settings} logo_image={@logo_image} header_image={@header_image} active_page="about" />
|
||||||
|
|
||||||
<!-- Content Page -->
|
<!-- Content Page -->
|
||||||
<div 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);">
|
<div class="content-hero text-center" style="padding: var(--space-2xl) var(--space-lg); background-color: var(--t-surface-sunken);">
|
||||||
<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);">
|
<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);">
|
||||||
@ -60,7 +63,7 @@
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</main>
|
||||||
|
|
||||||
<!-- Footer -->
|
<!-- Footer -->
|
||||||
<SimpleshopThemeWeb.ThemeLive.PreviewPages.shop_footer theme_settings={@theme_settings} />
|
<SimpleshopThemeWeb.ThemeLive.PreviewPages.shop_footer theme_settings={@theme_settings} />
|
||||||
|
|||||||
@ -1,13 +1,16 @@
|
|||||||
<div class="shop-container min-h-screen" style="position: relative; background-color: var(--t-surface-base); font-family: var(--t-font-body); color: var(--t-text-primary);">
|
<div class="shop-container min-h-screen" style="position: relative; background-color: var(--t-surface-base); font-family: var(--t-font-body); color: var(--t-text-primary);">
|
||||||
|
<!-- Skip Link for Accessibility -->
|
||||||
|
<SimpleshopThemeWeb.ThemeLive.PreviewPages.skip_link />
|
||||||
|
|
||||||
<!-- Announcement Bar -->
|
<!-- Announcement Bar -->
|
||||||
<%= if @theme_settings.announcement_bar do %>
|
<%= if @theme_settings.announcement_bar do %>
|
||||||
<SimpleshopThemeWeb.ThemeLive.PreviewPages.announcement_bar theme_settings={@theme_settings} />
|
<SimpleshopThemeWeb.ThemeLive.PreviewPages.announcement_bar theme_settings={@theme_settings} />
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<!-- Header -->
|
<!-- Header -->
|
||||||
<SimpleshopThemeWeb.ThemeLive.PreviewPages.shop_header theme_settings={@theme_settings} logo_image={@logo_image} header_image={@header_image} />
|
<SimpleshopThemeWeb.ThemeLive.PreviewPages.shop_header theme_settings={@theme_settings} logo_image={@logo_image} header_image={@header_image} active_page="cart" />
|
||||||
|
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
<main id="main-content" class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
||||||
<h1 class="text-3xl md:text-4xl font-bold mb-8" style="font-family: var(--t-font-heading); color: var(--t-text-primary); font-weight: var(--t-heading-weight); letter-spacing: var(--t-heading-tracking);">
|
<h1 class="text-3xl md:text-4xl font-bold mb-8" style="font-family: var(--t-font-heading); color: var(--t-text-primary); font-weight: var(--t-heading-weight); letter-spacing: var(--t-heading-tracking);">
|
||||||
Your basket
|
Your basket
|
||||||
</h1>
|
</h1>
|
||||||
@ -113,7 +116,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</main>
|
||||||
|
|
||||||
<!-- Footer -->
|
<!-- Footer -->
|
||||||
<SimpleshopThemeWeb.ThemeLive.PreviewPages.shop_footer theme_settings={@theme_settings} />
|
<SimpleshopThemeWeb.ThemeLive.PreviewPages.shop_footer theme_settings={@theme_settings} />
|
||||||
|
|||||||
@ -1,13 +1,17 @@
|
|||||||
<div class="shop-container min-h-screen" style="position: relative; background-color: var(--t-surface-base); font-family: var(--t-font-body); color: var(--t-text-primary);">
|
<div class="shop-container min-h-screen" style="position: relative; background-color: var(--t-surface-base); font-family: var(--t-font-body); color: var(--t-text-primary);">
|
||||||
|
<!-- Skip Link for Accessibility -->
|
||||||
|
<SimpleshopThemeWeb.ThemeLive.PreviewPages.skip_link />
|
||||||
|
|
||||||
<!-- Announcement Bar -->
|
<!-- Announcement Bar -->
|
||||||
<%= if @theme_settings.announcement_bar do %>
|
<%= if @theme_settings.announcement_bar do %>
|
||||||
<SimpleshopThemeWeb.ThemeLive.PreviewPages.announcement_bar theme_settings={@theme_settings} />
|
<SimpleshopThemeWeb.ThemeLive.PreviewPages.announcement_bar theme_settings={@theme_settings} />
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<!-- Header -->
|
<!-- Header -->
|
||||||
<SimpleshopThemeWeb.ThemeLive.PreviewPages.shop_header theme_settings={@theme_settings} logo_image={@logo_image} header_image={@header_image} />
|
<SimpleshopThemeWeb.ThemeLive.PreviewPages.shop_header theme_settings={@theme_settings} logo_image={@logo_image} header_image={@header_image} active_page="collection" />
|
||||||
|
|
||||||
<!-- Page Header -->
|
<!-- Page Header -->
|
||||||
|
<main id="main-content">
|
||||||
<div class="border-b" style="background-color: var(--t-surface-raised); border-color: var(--t-border-default);">
|
<div class="border-b" style="background-color: var(--t-surface-raised); border-color: var(--t-border-default);">
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
||||||
<h1 class="text-3xl md:text-4xl font-bold mb-2" style="font-family: var(--t-font-heading); color: var(--t-text-primary); font-weight: var(--t-heading-weight); letter-spacing: var(--t-heading-tracking);">
|
<h1 class="text-3xl md:text-4xl font-bold mb-2" style="font-family: var(--t-font-heading); color: var(--t-text-primary); font-weight: var(--t-heading-weight); letter-spacing: var(--t-heading-tracking);">
|
||||||
@ -77,6 +81,8 @@
|
|||||||
<img
|
<img
|
||||||
src={product.image_url}
|
src={product.image_url}
|
||||||
alt={product.name}
|
alt={product.name}
|
||||||
|
loading="lazy"
|
||||||
|
decoding="async"
|
||||||
class="product-image-primary w-full h-full object-cover transition-opacity duration-300"
|
class="product-image-primary w-full h-full object-cover transition-opacity duration-300"
|
||||||
/>
|
/>
|
||||||
<!-- Hover Image -->
|
<!-- Hover Image -->
|
||||||
@ -84,6 +90,8 @@
|
|||||||
<img
|
<img
|
||||||
src={product.hover_image_url}
|
src={product.hover_image_url}
|
||||||
alt={product.name}
|
alt={product.name}
|
||||||
|
loading="lazy"
|
||||||
|
decoding="async"
|
||||||
class="product-image-hover w-full h-full object-cover"
|
class="product-image-hover w-full h-full object-cover"
|
||||||
/>
|
/>
|
||||||
<% end %>
|
<% end %>
|
||||||
@ -111,11 +119,15 @@
|
|||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
<p class="text-xs mt-1" style="color: var(--t-text-tertiary);">
|
||||||
|
Free delivery over £40
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
<!-- Footer -->
|
<!-- Footer -->
|
||||||
<SimpleshopThemeWeb.ThemeLive.PreviewPages.shop_footer theme_settings={@theme_settings} />
|
<SimpleshopThemeWeb.ThemeLive.PreviewPages.shop_footer theme_settings={@theme_settings} />
|
||||||
|
|||||||
@ -1,13 +1,16 @@
|
|||||||
<div class="shop-container min-h-screen" style="position: relative; background-color: var(--t-surface-base); font-family: var(--t-font-body); color: var(--t-text-primary);">
|
<div class="shop-container min-h-screen" style="position: relative; background-color: var(--t-surface-base); font-family: var(--t-font-body); color: var(--t-text-primary);">
|
||||||
|
<!-- Skip Link for Accessibility -->
|
||||||
|
<SimpleshopThemeWeb.ThemeLive.PreviewPages.skip_link />
|
||||||
|
|
||||||
<!-- Announcement Bar -->
|
<!-- Announcement Bar -->
|
||||||
<%= if @theme_settings.announcement_bar do %>
|
<%= if @theme_settings.announcement_bar do %>
|
||||||
<SimpleshopThemeWeb.ThemeLive.PreviewPages.announcement_bar theme_settings={@theme_settings} />
|
<SimpleshopThemeWeb.ThemeLive.PreviewPages.announcement_bar theme_settings={@theme_settings} />
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<!-- Header -->
|
<!-- Header -->
|
||||||
<SimpleshopThemeWeb.ThemeLive.PreviewPages.shop_header theme_settings={@theme_settings} logo_image={@logo_image} header_image={@header_image} />
|
<SimpleshopThemeWeb.ThemeLive.PreviewPages.shop_header theme_settings={@theme_settings} logo_image={@logo_image} header_image={@header_image} active_page="contact" />
|
||||||
|
|
||||||
<div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-16">
|
<main id="main-content" class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-16">
|
||||||
<h1 class="text-4xl md:text-5xl font-bold mb-6 text-center" style="font-family: var(--t-font-heading); color: var(--t-text-primary); font-weight: var(--t-heading-weight); letter-spacing: var(--t-heading-tracking);">
|
<h1 class="text-4xl md:text-5xl font-bold mb-6 text-center" style="font-family: var(--t-font-heading); color: var(--t-text-primary); font-weight: var(--t-heading-weight); letter-spacing: var(--t-heading-tracking);">
|
||||||
Contact Us
|
Contact Us
|
||||||
</h1>
|
</h1>
|
||||||
@ -180,7 +183,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</main>
|
||||||
|
|
||||||
<!-- Footer -->
|
<!-- Footer -->
|
||||||
<SimpleshopThemeWeb.ThemeLive.PreviewPages.shop_footer theme_settings={@theme_settings} />
|
<SimpleshopThemeWeb.ThemeLive.PreviewPages.shop_footer theme_settings={@theme_settings} />
|
||||||
|
|||||||
@ -1,13 +1,16 @@
|
|||||||
<div class="shop-container min-h-screen" style="position: relative; background-color: var(--t-surface-base); font-family: var(--t-font-body); color: var(--t-text-primary);">
|
<div class="shop-container min-h-screen" style="position: relative; background-color: var(--t-surface-base); font-family: var(--t-font-body); color: var(--t-text-primary);">
|
||||||
|
<!-- Skip Link for Accessibility -->
|
||||||
|
<SimpleshopThemeWeb.ThemeLive.PreviewPages.skip_link />
|
||||||
|
|
||||||
<!-- Announcement Bar -->
|
<!-- Announcement Bar -->
|
||||||
<%= if @theme_settings.announcement_bar do %>
|
<%= if @theme_settings.announcement_bar do %>
|
||||||
<SimpleshopThemeWeb.ThemeLive.PreviewPages.announcement_bar theme_settings={@theme_settings} />
|
<SimpleshopThemeWeb.ThemeLive.PreviewPages.announcement_bar theme_settings={@theme_settings} />
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<!-- Header -->
|
<!-- Header -->
|
||||||
<SimpleshopThemeWeb.ThemeLive.PreviewPages.shop_header theme_settings={@theme_settings} logo_image={@logo_image} header_image={@header_image} />
|
<SimpleshopThemeWeb.ThemeLive.PreviewPages.shop_header theme_settings={@theme_settings} logo_image={@logo_image} header_image={@header_image} active_page="error" />
|
||||||
|
|
||||||
<div class="flex items-center justify-center" style="min-height: calc(100vh - 4rem);">
|
<main id="main-content" class="flex items-center justify-center" style="min-height: calc(100vh - 4rem);">
|
||||||
<div class="max-w-2xl mx-auto px-4 sm:px-6 lg:px-8 py-16 text-center">
|
<div class="max-w-2xl mx-auto px-4 sm:px-6 lg:px-8 py-16 text-center">
|
||||||
<h1 class="text-8xl md:text-9xl font-bold mb-4" style="font-family: var(--t-font-heading); color: hsl(var(--t-accent-h) var(--t-accent-s) var(--t-accent-l)); font-weight: var(--t-heading-weight);">
|
<h1 class="text-8xl md:text-9xl font-bold mb-4" style="font-family: var(--t-font-heading); color: hsl(var(--t-accent-h) var(--t-accent-s) var(--t-accent-l)); font-weight: var(--t-heading-weight);">
|
||||||
404
|
404
|
||||||
@ -71,7 +74,7 @@
|
|||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</main>
|
||||||
|
|
||||||
<!-- Footer -->
|
<!-- Footer -->
|
||||||
<SimpleshopThemeWeb.ThemeLive.PreviewPages.shop_footer theme_settings={@theme_settings} />
|
<SimpleshopThemeWeb.ThemeLive.PreviewPages.shop_footer theme_settings={@theme_settings} />
|
||||||
|
|||||||
@ -1,13 +1,17 @@
|
|||||||
<div class="shop-container min-h-screen" style="background-color: var(--t-surface-base); font-family: var(--t-font-body); color: var(--t-text-primary);">
|
<div class="shop-container min-h-screen" style="background-color: var(--t-surface-base); font-family: var(--t-font-body); color: var(--t-text-primary);">
|
||||||
|
<!-- Skip Link for Accessibility -->
|
||||||
|
<SimpleshopThemeWeb.ThemeLive.PreviewPages.skip_link />
|
||||||
|
|
||||||
<!-- Announcement Bar -->
|
<!-- Announcement Bar -->
|
||||||
<%= if @theme_settings.announcement_bar do %>
|
<%= if @theme_settings.announcement_bar do %>
|
||||||
<SimpleshopThemeWeb.ThemeLive.PreviewPages.announcement_bar theme_settings={@theme_settings} />
|
<SimpleshopThemeWeb.ThemeLive.PreviewPages.announcement_bar theme_settings={@theme_settings} />
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<!-- Header -->
|
<!-- Header -->
|
||||||
<SimpleshopThemeWeb.ThemeLive.PreviewPages.shop_header theme_settings={@theme_settings} logo_image={@logo_image} header_image={@header_image} />
|
<SimpleshopThemeWeb.ThemeLive.PreviewPages.shop_header theme_settings={@theme_settings} logo_image={@logo_image} header_image={@header_image} active_page="home" />
|
||||||
|
|
||||||
<!-- Hero Section -->
|
<!-- Hero Section -->
|
||||||
|
<main id="main-content">
|
||||||
<section class="text-center" style="padding: var(--space-2xl) var(--space-lg); background-color: var(--t-surface-base);">
|
<section class="text-center" style="padding: var(--space-2xl) var(--space-lg); background-color: var(--t-surface-base);">
|
||||||
<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);">
|
<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);">
|
||||||
Original designs, printed on demand
|
Original designs, printed on demand
|
||||||
@ -74,12 +78,16 @@
|
|||||||
<img
|
<img
|
||||||
src={product.image_url}
|
src={product.image_url}
|
||||||
alt={product.name}
|
alt={product.name}
|
||||||
|
loading="lazy"
|
||||||
|
decoding="async"
|
||||||
class="product-image-primary w-full h-full object-cover transition-opacity duration-300"
|
class="product-image-primary w-full h-full object-cover transition-opacity duration-300"
|
||||||
/>
|
/>
|
||||||
<%= if @theme_settings.hover_image && product[:hover_image_url] do %>
|
<%= if @theme_settings.hover_image && product[:hover_image_url] do %>
|
||||||
<img
|
<img
|
||||||
src={product.hover_image_url}
|
src={product.hover_image_url}
|
||||||
alt={product.name}
|
alt={product.name}
|
||||||
|
loading="lazy"
|
||||||
|
decoding="async"
|
||||||
class="product-image-hover w-full h-full object-cover"
|
class="product-image-hover w-full h-full object-cover"
|
||||||
/>
|
/>
|
||||||
<% end %>
|
<% end %>
|
||||||
@ -96,6 +104,9 @@
|
|||||||
£<%= product.price / 100 %>
|
£<%= product.price / 100 %>
|
||||||
</p>
|
</p>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
<p class="text-xs mt-1" style="color: var(--t-text-tertiary);">
|
||||||
|
Free delivery over £40
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
@ -137,6 +148,7 @@
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
</main>
|
||||||
|
|
||||||
<!-- Footer -->
|
<!-- Footer -->
|
||||||
<SimpleshopThemeWeb.ThemeLive.PreviewPages.shop_footer theme_settings={@theme_settings} />
|
<SimpleshopThemeWeb.ThemeLive.PreviewPages.shop_footer theme_settings={@theme_settings} />
|
||||||
|
|||||||
@ -2,15 +2,18 @@
|
|||||||
product = List.first(@preview_data.products)
|
product = List.first(@preview_data.products)
|
||||||
%>
|
%>
|
||||||
<div class="shop-container min-h-screen" style="position: relative; background-color: var(--t-surface-base); font-family: var(--t-font-body); color: var(--t-text-primary);">
|
<div class="shop-container min-h-screen" style="position: relative; background-color: var(--t-surface-base); font-family: var(--t-font-body); color: var(--t-text-primary);">
|
||||||
|
<!-- Skip Link for Accessibility -->
|
||||||
|
<SimpleshopThemeWeb.ThemeLive.PreviewPages.skip_link />
|
||||||
|
|
||||||
<!-- Announcement Bar -->
|
<!-- Announcement Bar -->
|
||||||
<%= if @theme_settings.announcement_bar do %>
|
<%= if @theme_settings.announcement_bar do %>
|
||||||
<SimpleshopThemeWeb.ThemeLive.PreviewPages.announcement_bar theme_settings={@theme_settings} />
|
<SimpleshopThemeWeb.ThemeLive.PreviewPages.announcement_bar theme_settings={@theme_settings} />
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<!-- Header -->
|
<!-- Header -->
|
||||||
<SimpleshopThemeWeb.ThemeLive.PreviewPages.shop_header theme_settings={@theme_settings} logo_image={@logo_image} header_image={@header_image} />
|
<SimpleshopThemeWeb.ThemeLive.PreviewPages.shop_header theme_settings={@theme_settings} logo_image={@logo_image} header_image={@header_image} active_page="pdp" />
|
||||||
|
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
<main id="main-content" class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
||||||
<!-- Breadcrumb -->
|
<!-- Breadcrumb -->
|
||||||
<nav class="mb-8 flex items-center gap-2 text-sm" style="color: var(--t-text-secondary);">
|
<nav class="mb-8 flex items-center gap-2 text-sm" style="color: var(--t-text-secondary);">
|
||||||
<a href="#" phx-click="change_preview_page" phx-value-page="home" class="hover:underline">Home</a>
|
<a href="#" phx-click="change_preview_page" phx-value-page="home" class="hover:underline">Home</a>
|
||||||
@ -157,10 +160,6 @@
|
|||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p class="mb-8 leading-relaxed" style="color: var(--t-text-secondary);">
|
|
||||||
<%= product.description %>. Crafted with attention to detail and quality materials, this product is designed to last. Perfect for everyday use or special occasions.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<!-- Variant Options -->
|
<!-- Variant Options -->
|
||||||
<div class="mb-6">
|
<div class="mb-6">
|
||||||
<label class="block font-semibold mb-2" style="color: var(--t-text-primary);">
|
<label class="block font-semibold mb-2" style="color: var(--t-text-primary);">
|
||||||
@ -199,14 +198,16 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Add to Cart -->
|
<!-- Add to Cart - Sticky on mobile -->
|
||||||
<button
|
<div class="sticky bottom-0 z-10 py-3 md:relative md:py-0 -mx-4 px-4 md:mx-0 md:px-0 border-t md:border-0 mb-4" style="background-color: var(--t-surface-base); border-color: var(--t-border-subtle);">
|
||||||
phx-click={Phoenix.LiveView.JS.add_class("open", to: "#cart-drawer") |> Phoenix.LiveView.JS.add_class("open", to: "#cart-drawer-overlay")}
|
<button
|
||||||
class="w-full px-6 py-4 text-lg font-semibold transition-all mb-4"
|
phx-click={Phoenix.LiveView.JS.add_class("open", to: "#cart-drawer") |> Phoenix.LiveView.JS.add_class("open", to: "#cart-drawer-overlay")}
|
||||||
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;"
|
class="w-full px-6 py-4 text-lg font-semibold 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;"
|
||||||
Add to basket
|
>
|
||||||
</button>
|
Add to basket
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Features / Trust Badges -->
|
<!-- Features / Trust Badges -->
|
||||||
<%= if @theme_settings.pdp_trust_badges do %>
|
<%= if @theme_settings.pdp_trust_badges do %>
|
||||||
@ -231,32 +232,97 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
|
<!-- Product Info Accordion -->
|
||||||
|
<div class="mt-8 divide-y" style="border-top: 1px solid var(--t-border-subtle); border-bottom: 1px solid var(--t-border-subtle); border-color: var(--t-border-subtle);">
|
||||||
|
<!-- Description - open by default -->
|
||||||
|
<details open class="group">
|
||||||
|
<summary class="flex justify-between items-center py-4 cursor-pointer list-none [&::-webkit-details-marker]:hidden" style="color: var(--t-text-primary);">
|
||||||
|
<span class="font-semibold">Description</span>
|
||||||
|
<svg class="w-5 h-5 transition-transform duration-200 group-open:rotate-180" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
|
||||||
|
</svg>
|
||||||
|
</summary>
|
||||||
|
<div class="pb-4 leading-relaxed" style="color: var(--t-text-secondary);">
|
||||||
|
<p><%= product.description %>. Crafted with attention to detail and quality materials, this product is designed to last. Perfect for everyday use or special occasions.</p>
|
||||||
|
</div>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<!-- Size Guide - collapsed by default -->
|
||||||
|
<details class="group">
|
||||||
|
<summary class="flex justify-between items-center py-4 cursor-pointer list-none [&::-webkit-details-marker]:hidden" style="color: var(--t-text-primary);">
|
||||||
|
<span class="font-semibold">Size Guide</span>
|
||||||
|
<svg class="w-5 h-5 transition-transform duration-200 group-open:rotate-180" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
|
||||||
|
</svg>
|
||||||
|
</summary>
|
||||||
|
<div class="pb-4" style="color: var(--t-text-secondary);">
|
||||||
|
<table class="w-full text-sm">
|
||||||
|
<thead>
|
||||||
|
<tr style="border-bottom: 1px solid var(--t-border-subtle);">
|
||||||
|
<th class="text-left py-2 font-semibold" style="color: var(--t-text-primary);">Size</th>
|
||||||
|
<th class="text-left py-2 font-semibold" style="color: var(--t-text-primary);">Chest (cm)</th>
|
||||||
|
<th class="text-left py-2 font-semibold" style="color: var(--t-text-primary);">Length (cm)</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr style="border-bottom: 1px solid var(--t-border-subtle);">
|
||||||
|
<td class="py-2">S</td>
|
||||||
|
<td class="py-2">86-91</td>
|
||||||
|
<td class="py-2">71</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-bottom: 1px solid var(--t-border-subtle);">
|
||||||
|
<td class="py-2">M</td>
|
||||||
|
<td class="py-2">91-96</td>
|
||||||
|
<td class="py-2">73</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-bottom: 1px solid var(--t-border-subtle);">
|
||||||
|
<td class="py-2">L</td>
|
||||||
|
<td class="py-2">96-101</td>
|
||||||
|
<td class="py-2">75</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="py-2">XL</td>
|
||||||
|
<td class="py-2">101-106</td>
|
||||||
|
<td class="py-2">77</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<!-- Shipping & Returns - collapsed by default -->
|
||||||
|
<details class="group">
|
||||||
|
<summary class="flex justify-between items-center py-4 cursor-pointer list-none [&::-webkit-details-marker]:hidden" style="color: var(--t-text-primary);">
|
||||||
|
<span class="font-semibold">Shipping & Returns</span>
|
||||||
|
<svg class="w-5 h-5 transition-transform duration-200 group-open:rotate-180" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
|
||||||
|
</svg>
|
||||||
|
</summary>
|
||||||
|
<div class="pb-4 space-y-3" style="color: var(--t-text-secondary);">
|
||||||
|
<div>
|
||||||
|
<p class="font-semibold mb-1" style="color: var(--t-text-primary);">Delivery</p>
|
||||||
|
<p class="text-sm">Free UK delivery on orders over £40. Standard delivery 3-5 working days. Express delivery available at checkout.</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p class="font-semibold mb-1" style="color: var(--t-text-primary);">Returns</p>
|
||||||
|
<p class="text-sm">We offer a 30-day return policy. Items must be unused and in original packaging. Please contact us to arrange a return.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</details>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Reviews Section -->
|
<!-- Reviews Section - Accordion format, open by default for social proof -->
|
||||||
<%= if @theme_settings.pdp_reviews do %>
|
<%= if @theme_settings.pdp_reviews do %>
|
||||||
<div class="pdp-reviews py-12" style="border-top: 1px solid var(--t-border-default);">
|
<details open class="pdp-reviews group" style="border-top: 1px solid var(--t-border-default);">
|
||||||
<div class="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4 mb-8">
|
<summary class="flex justify-between items-center py-6 cursor-pointer list-none [&::-webkit-details-marker]:hidden" style="color: var(--t-text-primary);">
|
||||||
<h2 class="text-2xl font-bold" style="font-family: var(--t-font-heading); color: var(--t-text-primary); font-weight: var(--t-heading-weight);">
|
<div class="flex flex-col sm:flex-row sm:items-center gap-2 sm:gap-4">
|
||||||
Customer reviews
|
<h2 class="text-2xl font-bold" style="font-family: var(--t-font-heading); color: var(--t-text-primary); font-weight: var(--t-heading-weight);">
|
||||||
</h2>
|
Customer reviews
|
||||||
<div class="flex items-center gap-3">
|
</h2>
|
||||||
<div class="flex gap-0.5">
|
<div class="flex items-center gap-2">
|
||||||
<%= for _i <- 1..5 do %>
|
|
||||||
<svg class="w-5 h-5" viewBox="0 0 20 20" style="color: #f59e0b;">
|
|
||||||
<path d="M10 15l-5.878 3.09 1.123-6.545L.489 6.91l6.572-.955L10 0l2.939 5.955 6.572.955-4.756 4.635 1.123 6.545z" fill="currentColor"/>
|
|
||||||
</svg>
|
|
||||||
<% end %>
|
|
||||||
</div>
|
|
||||||
<span class="text-sm" style="color: var(--t-text-secondary);">Based on 24 reviews</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="space-y-6">
|
|
||||||
<!-- Review 1 -->
|
|
||||||
<article class="pb-6" style="border-bottom: 1px solid var(--t-border-subtle);">
|
|
||||||
<div class="flex items-center justify-between mb-2">
|
|
||||||
<div class="flex gap-0.5">
|
<div class="flex gap-0.5">
|
||||||
<%= for _i <- 1..5 do %>
|
<%= for _i <- 1..5 do %>
|
||||||
<svg class="w-4 h-4" viewBox="0 0 20 20" style="color: #f59e0b;">
|
<svg class="w-4 h-4" viewBox="0 0 20 20" style="color: #f59e0b;">
|
||||||
@ -264,48 +330,69 @@
|
|||||||
</svg>
|
</svg>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
<span class="text-xs" style="color: var(--t-text-tertiary);">2 weeks ago</span>
|
<span class="text-sm" style="color: var(--t-text-secondary);">(24)</span>
|
||||||
</div>
|
</div>
|
||||||
<h3 class="font-semibold mb-1" style="color: var(--t-text-primary);">Absolutely beautiful</h3>
|
</div>
|
||||||
<p class="text-sm mb-3" style="color: var(--t-text-secondary); line-height: 1.6;">
|
<svg class="w-5 h-5 transition-transform duration-200 group-open:rotate-180 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
The quality exceeded my expectations. The colours are vibrant and the paper feels premium. It's now pride of place in my living room.
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
|
||||||
</p>
|
</svg>
|
||||||
<div class="flex items-center gap-2">
|
</summary>
|
||||||
<span class="text-sm font-medium" style="color: var(--t-text-primary);">Sarah M.</span>
|
|
||||||
<span class="text-xs px-2 py-0.5 rounded" style="background-color: var(--t-surface-sunken); color: var(--t-text-tertiary);">Verified purchase</span>
|
|
||||||
</div>
|
|
||||||
</article>
|
|
||||||
|
|
||||||
<!-- Review 2 -->
|
<div class="pb-8">
|
||||||
<article class="pb-6" style="border-bottom: 1px solid var(--t-border-subtle);">
|
<div class="space-y-6">
|
||||||
<div class="flex items-center justify-between mb-2">
|
<!-- Review 1 -->
|
||||||
<div class="flex gap-0.5">
|
<article class="pb-6" style="border-bottom: 1px solid var(--t-border-subtle);">
|
||||||
<%= for i <- 1..5 do %>
|
<div class="flex items-center justify-between mb-2">
|
||||||
<svg class="w-4 h-4" viewBox="0 0 20 20" style={"color: #{if i <= 4, do: "#f59e0b", else: "var(--t-border-default)"};"}>
|
<div class="flex gap-0.5">
|
||||||
<path d="M10 15l-5.878 3.09 1.123-6.545L.489 6.91l6.572-.955L10 0l2.939 5.955 6.572.955-4.756 4.635 1.123 6.545z" fill="currentColor"/>
|
<%= for _i <- 1..5 do %>
|
||||||
</svg>
|
<svg class="w-4 h-4" viewBox="0 0 20 20" style="color: #f59e0b;">
|
||||||
<% end %>
|
<path d="M10 15l-5.878 3.09 1.123-6.545L.489 6.91l6.572-.955L10 0l2.939 5.955 6.572.955-4.756 4.635 1.123 6.545z" fill="currentColor"/>
|
||||||
|
</svg>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
<span class="text-xs" style="color: var(--t-text-tertiary);">2 weeks ago</span>
|
||||||
</div>
|
</div>
|
||||||
<span class="text-xs" style="color: var(--t-text-tertiary);">1 month ago</span>
|
<h3 class="font-semibold mb-1" style="color: var(--t-text-primary);">Absolutely beautiful</h3>
|
||||||
</div>
|
<p class="text-sm mb-3" style="color: var(--t-text-secondary); line-height: 1.6;">
|
||||||
<h3 class="font-semibold mb-1" style="color: var(--t-text-primary);">Great gift</h3>
|
The quality exceeded my expectations. The colours are vibrant and the paper feels premium. It's now pride of place in my living room.
|
||||||
<p class="text-sm mb-3" style="color: var(--t-text-secondary); line-height: 1.6;">
|
</p>
|
||||||
Bought this as a gift and it arrived beautifully packaged. Fast shipping too. Would definitely order again.
|
<div class="flex items-center gap-2">
|
||||||
</p>
|
<span class="text-sm font-medium" style="color: var(--t-text-primary);">Sarah M.</span>
|
||||||
<div class="flex items-center gap-2">
|
<span class="text-xs px-2 py-0.5 rounded" style="background-color: var(--t-surface-sunken); color: var(--t-text-tertiary);">Verified purchase</span>
|
||||||
<span class="text-sm font-medium" style="color: var(--t-text-primary);">James T.</span>
|
</div>
|
||||||
<span class="text-xs px-2 py-0.5 rounded" style="background-color: var(--t-surface-sunken); color: var(--t-text-tertiary);">Verified purchase</span>
|
</article>
|
||||||
</div>
|
|
||||||
</article>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<button
|
<!-- Review 2 -->
|
||||||
class="mt-6 px-6 py-2 text-sm font-medium transition-all mx-auto block"
|
<article class="pb-6" style="border-bottom: 1px solid var(--t-border-subtle);">
|
||||||
style="background-color: transparent; color: var(--t-text-primary); border: 1px solid var(--t-border-default); border-radius: var(--t-radius-button);"
|
<div class="flex items-center justify-between mb-2">
|
||||||
>
|
<div class="flex gap-0.5">
|
||||||
Load more reviews
|
<%= for i <- 1..5 do %>
|
||||||
</button>
|
<svg class="w-4 h-4" viewBox="0 0 20 20" style={"color: #{if i <= 4, do: "#f59e0b", else: "var(--t-border-default)"};"}>
|
||||||
</div>
|
<path d="M10 15l-5.878 3.09 1.123-6.545L.489 6.91l6.572-.955L10 0l2.939 5.955 6.572.955-4.756 4.635 1.123 6.545z" fill="currentColor"/>
|
||||||
|
</svg>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
<span class="text-xs" style="color: var(--t-text-tertiary);">1 month ago</span>
|
||||||
|
</div>
|
||||||
|
<h3 class="font-semibold mb-1" style="color: var(--t-text-primary);">Great gift</h3>
|
||||||
|
<p class="text-sm mb-3" style="color: var(--t-text-secondary); line-height: 1.6;">
|
||||||
|
Bought this as a gift and it arrived beautifully packaged. Fast shipping too. Would definitely order again.
|
||||||
|
</p>
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<span class="text-sm font-medium" style="color: var(--t-text-primary);">James T.</span>
|
||||||
|
<span class="text-xs px-2 py-0.5 rounded" style="background-color: var(--t-surface-sunken); color: var(--t-text-tertiary);">Verified purchase</span>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button
|
||||||
|
class="mt-6 px-6 py-2 text-sm font-medium transition-all mx-auto block"
|
||||||
|
style="background-color: transparent; color: var(--t-text-primary); border: 1px solid var(--t-border-default); border-radius: var(--t-radius-button);"
|
||||||
|
>
|
||||||
|
Load more reviews
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</details>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<!-- Related Products -->
|
<!-- Related Products -->
|
||||||
@ -328,12 +415,16 @@
|
|||||||
<img
|
<img
|
||||||
src={related_product.image_url}
|
src={related_product.image_url}
|
||||||
alt={related_product.name}
|
alt={related_product.name}
|
||||||
|
loading="lazy"
|
||||||
|
decoding="async"
|
||||||
class="product-image-primary w-full h-full object-cover transition-opacity duration-300"
|
class="product-image-primary w-full h-full object-cover transition-opacity duration-300"
|
||||||
/>
|
/>
|
||||||
<%= if @theme_settings.hover_image && related_product[:hover_image_url] do %>
|
<%= if @theme_settings.hover_image && related_product[:hover_image_url] do %>
|
||||||
<img
|
<img
|
||||||
src={related_product.hover_image_url}
|
src={related_product.hover_image_url}
|
||||||
alt={related_product.name}
|
alt={related_product.name}
|
||||||
|
loading="lazy"
|
||||||
|
decoding="async"
|
||||||
class="product-image-hover w-full h-full object-cover"
|
class="product-image-hover w-full h-full object-cover"
|
||||||
/>
|
/>
|
||||||
<% end %>
|
<% end %>
|
||||||
@ -353,7 +444,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</main>
|
||||||
|
|
||||||
<!-- Footer -->
|
<!-- Footer -->
|
||||||
<SimpleshopThemeWeb.ThemeLive.PreviewPages.shop_footer theme_settings={@theme_settings} />
|
<SimpleshopThemeWeb.ThemeLive.PreviewPages.shop_footer theme_settings={@theme_settings} />
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user