extract content + template inline styles to CSS classes (Phase 4)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
jamey 2026-02-17 08:01:32 +00:00
parent d172997685
commit 84de1c37c5
8 changed files with 387 additions and 155 deletions

View File

@ -869,4 +869,307 @@
.order-summary-divider { .order-summary-divider {
border-color: var(--t-border-default); border-color: var(--t-border-default);
} }
/* ── Content body ── */
.content-body {
padding: var(--space-xl) var(--space-lg);
max-width: 800px;
margin: 0 auto;
}
.content-image {
margin-bottom: var(--space-lg);
border-radius: var(--t-radius-image);
overflow: hidden;
}
.content-text {
line-height: 1.7;
}
.content-page {
background-color: var(--t-surface-base);
}
/* ── Contact form ── */
.contact-form-meta {
color: var(--t-text-secondary);
}
.contact-form-label {
color: var(--t-text-primary);
}
/* ── Accent email link ── */
.accent-email {
color: hsl(var(--t-accent-h) var(--t-accent-s) var(--t-accent-l));
}
/* ── Card shared styles (info, tracking, newsletter, social cards) ── */
.card-heading {
color: var(--t-text-primary);
}
.card-text {
color: var(--t-text-secondary);
}
/* ── Info card ── */
.info-card-list {
color: var(--t-text-secondary);
}
.info-card-bullet {
color: var(--t-text-tertiary);
}
.info-card-label {
color: var(--t-text-primary);
}
/* ── Contact info card ── */
.contact-info-email {
color: hsl(var(--t-accent-h) var(--t-accent-s) var(--t-accent-l));
text-decoration: none;
}
/* ── Email input min-width ── */
.email-input {
min-width: 150px;
}
/* ── Social links card ── */
.social-link-card-item {
text-decoration: none;
}
.social-link-card-icon {
color: var(--t-text-secondary);
}
/* ── Social links (footer) ── */
.social-link {
color: var(--t-text-secondary);
border-radius: var(--t-radius-button);
}
/* ── Trust badges ── */
.trust-badges {
background-color: var(--t-surface-sunken);
border-radius: var(--t-radius-card);
}
.trust-badge-icon {
color: hsl(var(--t-accent-h) var(--t-accent-s) var(--t-accent-l));
}
.trust-badge-title {
color: var(--t-text-primary);
}
.trust-badge-text {
color: var(--t-text-secondary);
}
/* ── Reviews section ── */
.pdp-reviews {
border-top: 1px solid var(--t-border-default);
}
.reviews-summary {
color: var(--t-text-primary);
}
.reviews-count {
color: var(--t-text-secondary);
}
/* ── Review card ── */
.review-card {
border-bottom: 1px solid var(--t-border-subtle);
}
.review-date {
color: var(--t-text-tertiary);
}
.review-title {
color: var(--t-text-primary);
}
.review-body {
color: var(--t-text-secondary);
line-height: 1.6;
}
.review-author {
color: var(--t-text-primary);
}
.review-verified {
background-color: var(--t-surface-sunken);
color: var(--t-text-tertiary);
}
/* ── Rich text ── */
.rich-text {
line-height: 1.7;
}
.rich-text-lead {
color: var(--t-text-primary);
}
.rich-text-paragraph {
color: var(--t-text-secondary);
}
.rich-text-heading {
font-family: var(--t-font-heading);
font-weight: var(--t-heading-weight);
font-size: var(--t-text-xl);
color: var(--t-text-primary);
}
.rich-text-list {
color: var(--t-text-secondary);
}
/* ── Flash messages ── */
.shop-flash {
background-color: var(--t-surface-raised, #fff);
color: var(--t-text-primary);
}
.shop-flash--info {
border: 1px solid var(--t-border-default);
}
.shop-flash--error {
border: 1px solid hsl(0 70% 50% / 0.3);
}
.shop-flash-icon--info {
color: var(--t-accent);
}
.shop-flash-icon--error {
color: hsl(0 70% 50%);
}
/* ── Link buttons (make <a> links styled as buttons) ── */
.themed-button:where(a),
.themed-button-outline:where(a) {
text-decoration: none;
display: inline-block;
}
/* ── Checkout success ── */
.checkout-icon {
background-color: var(--t-accent);
color: var(--t-accent-contrast);
}
.checkout-heading {
font-family: var(--t-font-heading);
color: var(--t-text-primary);
}
.checkout-meta {
color: var(--t-text-secondary);
& strong {
color: var(--t-text-primary);
}
}
.checkout-items {
list-style: none;
margin: 0;
padding: 0;
}
.checkout-item {
border-color: var(--t-border-default);
}
.checkout-item-name {
color: var(--t-text-primary);
}
.checkout-item-detail {
color: var(--t-text-secondary);
}
.checkout-item-price {
color: var(--t-text-primary);
}
.checkout-total-border {
border-color: var(--t-border-default);
}
.checkout-total {
color: var(--t-text-primary);
}
.checkout-shipping-address {
color: var(--t-text-secondary);
}
.checkout-pending-icon {
background-color: var(--t-surface-sunken);
}
.checkout-pending-spinner {
color: var(--t-text-secondary);
}
.checkout-pending-text {
color: var(--t-text-secondary);
}
.checkout-pending-hint {
color: var(--t-text-tertiary);
}
.checkout-contact-link {
color: var(--t-accent);
}
/* ── Error page ── */
.error-main {
min-height: calc(100vh - 4rem);
}
/* ── PDP variant fallback ── */
.pdp-variant-fallback {
color: var(--t-text-secondary);
}
/* ── Cart page list ── */
.cart-page-list {
list-style: none;
margin: 0;
padding: 0;
}
} }

View File

@ -10,8 +10,7 @@
<ul <ul
role="list" role="list"
aria-label="Cart items" aria-label="Cart items"
class="flex flex-col gap-4" class="cart-page-list flex flex-col gap-4"
style="list-style: none; margin: 0; padding: 0;"
> >
<%= for item <- @cart_items do %> <%= for item <- @cart_items do %>
<li> <li>

View File

@ -2,10 +2,7 @@
<main id="main-content" class="max-w-3xl mx-auto px-4 sm:px-6 lg:px-8 py-16"> <main id="main-content" class="max-w-3xl mx-auto px-4 sm:px-6 lg:px-8 py-16">
<%= if @order && @order.payment_status == "paid" do %> <%= if @order && @order.payment_status == "paid" do %>
<div class="text-center mb-12"> <div class="text-center mb-12">
<div <div class="checkout-icon inline-flex items-center justify-center w-16 h-16 rounded-full mb-6">
class="inline-flex items-center justify-center w-16 h-16 rounded-full mb-6"
style="background-color: var(--t-accent); color: var(--t-accent-contrast);"
>
<svg <svg
class="w-8 h-8" class="w-8 h-8"
fill="none" fill="none"
@ -17,62 +14,53 @@
</svg> </svg>
</div> </div>
<h1 <h1 class="checkout-heading text-3xl font-bold mb-3">
class="text-3xl font-bold mb-3"
style="font-family: var(--t-font-heading); color: var(--t-text-primary);"
>
Thank you for your order Thank you for your order
</h1> </h1>
<p class="text-lg mb-2" style="color: var(--t-text-secondary);"> <p class="checkout-meta text-lg mb-2">
Order <strong style="color: var(--t-text-primary);">{@order.order_number}</strong> Order <strong>{@order.order_number}</strong>
</p> </p>
<%= if @order.customer_email do %> <%= if @order.customer_email do %>
<p style="color: var(--t-text-secondary);"> <p class="checkout-meta">
A confirmation will be sent to <strong>{@order.customer_email}</strong> A confirmation will be sent to <strong>{@order.customer_email}</strong>
</p> </p>
<% end %> <% end %>
</div> </div>
<.shop_card class="p-6 mb-8"> <.shop_card class="p-6 mb-8">
<h2 <h2 class="checkout-heading text-lg font-semibold mb-4">
class="text-lg font-semibold mb-4"
style="font-family: var(--t-font-heading); color: var(--t-text-primary);"
>
Order details Order details
</h2> </h2>
<ul class="flex flex-col gap-4 mb-6" style="list-style: none; margin: 0; padding: 0;"> <ul class="checkout-items flex flex-col gap-4 mb-6">
<%= for item <- @order.items do %> <%= for item <- @order.items do %>
<li <li class="checkout-item flex justify-between items-start pb-4 border-b last:border-b-0 last:pb-0">
class="flex justify-between items-start pb-4 border-b last:border-b-0 last:pb-0"
style="border-color: var(--t-border-default);"
>
<div> <div>
<p class="font-medium" style="color: var(--t-text-primary);"> <p class="checkout-item-name font-medium">
{item.product_name} {item.product_name}
</p> </p>
<%= if item.variant_title do %> <%= if item.variant_title do %>
<p class="text-sm" style="color: var(--t-text-secondary);"> <p class="checkout-item-detail text-sm">
{item.variant_title} {item.variant_title}
</p> </p>
<% end %> <% end %>
<p class="text-sm" style="color: var(--t-text-secondary);"> <p class="checkout-item-detail text-sm">
Qty: {item.quantity} Qty: {item.quantity}
</p> </p>
</div> </div>
<span class="font-medium" style="color: var(--t-text-primary);"> <span class="checkout-item-price font-medium">
{SimpleshopTheme.Cart.format_price(item.unit_price * item.quantity)} {SimpleshopTheme.Cart.format_price(item.unit_price * item.quantity)}
</span> </span>
</li> </li>
<% end %> <% end %>
</ul> </ul>
<div class="border-t pt-4" style="border-color: var(--t-border-default);"> <div class="checkout-total-border border-t pt-4">
<div class="flex justify-between text-lg"> <div class="checkout-total flex justify-between text-lg">
<span class="font-semibold" style="color: var(--t-text-primary);">Total</span> <span class="font-semibold">Total</span>
<span class="font-bold" style="color: var(--t-text-primary);"> <span class="font-bold">
{SimpleshopTheme.Cart.format_price(@order.total)} {SimpleshopTheme.Cart.format_price(@order.total)}
</span> </span>
</div> </div>
@ -81,13 +69,10 @@
<%= if @order.shipping_address != %{} do %> <%= if @order.shipping_address != %{} do %>
<.shop_card class="p-6 mb-8"> <.shop_card class="p-6 mb-8">
<h2 <h2 class="checkout-heading text-lg font-semibold mb-3">
class="text-lg font-semibold mb-3"
style="font-family: var(--t-font-heading); color: var(--t-text-primary);"
>
Shipping to Shipping to
</h2> </h2>
<div style="color: var(--t-text-secondary);"> <div class="checkout-shipping-address">
<p>{@order.shipping_address["name"]}</p> <p>{@order.shipping_address["name"]}</p>
<p>{@order.shipping_address["line1"]}</p> <p>{@order.shipping_address["line1"]}</p>
<%= if @order.shipping_address["line2"] do %> <%= if @order.shipping_address["line2"] do %>
@ -109,11 +94,8 @@
<% else %> <% else %>
<%!-- Payment pending or order not found --%> <%!-- Payment pending or order not found --%>
<div class="text-center py-16"> <div class="text-center py-16">
<div <div class="checkout-pending-icon inline-flex items-center justify-center w-16 h-16 rounded-full mb-6 animate-pulse">
class="inline-flex items-center justify-center w-16 h-16 rounded-full mb-6 animate-pulse" <span class="checkout-pending-spinner">
style="background-color: var(--t-surface-sunken);"
>
<span style="color: var(--t-text-secondary);">
<svg <svg
class="w-8 h-8" class="w-8 h-8"
fill="none" fill="none"
@ -130,22 +112,18 @@
</span> </span>
</div> </div>
<h1 <h1 class="checkout-heading text-3xl font-bold mb-3">
class="text-3xl font-bold mb-3"
style="font-family: var(--t-font-heading); color: var(--t-text-primary);"
>
Processing your payment Processing your payment
</h1> </h1>
<p class="text-lg mb-8" style="color: var(--t-text-secondary);"> <p class="checkout-pending-text text-lg mb-8">
Please wait while we confirm your payment. This usually takes a few seconds. Please wait while we confirm your payment. This usually takes a few seconds.
</p> </p>
<p class="text-sm" style="color: var(--t-text-tertiary);"> <p class="checkout-pending-hint text-sm">
If this page doesn't update, please <.link If this page doesn't update, please <.link
navigate="/contact" navigate="/contact"
class="underline" class="checkout-contact-link underline"
style="color: var(--t-accent);"
>contact us</.link>. >contact us</.link>.
</p> </p>
</div> </div>

View File

@ -1,5 +1,5 @@
<.shop_layout {layout_assigns(assigns)}> <.shop_layout {layout_assigns(assigns)}>
<main id="main-content" class="content-page" style="background-color: var(--t-surface-base);"> <main id="main-content" class="content-page">
<%= if assigns[:hero_background] do %> <%= if assigns[:hero_background] do %>
<.hero_section <.hero_section
title={@hero_title} title={@hero_title}
@ -14,12 +14,9 @@
/> />
<% end %> <% end %>
<div style="padding: var(--space-xl) var(--space-lg); max-width: 800px; margin: 0 auto;"> <div class="content-body">
<%= if assigns[:image_src] do %> <%= if assigns[:image_src] do %>
<div <div class="content-image">
class="content-image"
style="margin-bottom: var(--space-lg); border-radius: var(--t-radius-image); overflow: hidden;"
>
<.responsive_image <.responsive_image
src={@image_src} src={@image_src}
source_width={1200} source_width={1200}

View File

@ -1,8 +1,7 @@
<.shop_layout {layout_assigns(assigns)} active_page="error" error_page> <.shop_layout {layout_assigns(assigns)} active_page="error" error_page>
<main <main
id="main-content" id="main-content"
class="flex items-center justify-center" class="error-main 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"> <div class="max-w-2xl mx-auto px-4 sm:px-6 lg:px-8 py-16">
<.hero_section <.hero_section

View File

@ -38,8 +38,7 @@
<%!-- Fallback for products with no variant options --%> <%!-- Fallback for products with no variant options --%>
<div <div
:if={@option_types == []} :if={@option_types == []}
class="mb-6 text-sm" class="pdp-variant-fallback mb-6 text-sm"
style="color: var(--t-text-secondary);"
> >
One size One size
</div> </div>

View File

@ -173,7 +173,6 @@ defmodule SimpleshopThemeWeb.ShopComponents.Base do
<.link <.link
navigate={@href} navigate={@href}
class={["themed-button", @class]} class={["themed-button", @class]}
style="text-decoration: none; display: inline-block;"
> >
{render_slot(@inner_block)} {render_slot(@inner_block)}
</.link> </.link>
@ -206,7 +205,6 @@ defmodule SimpleshopThemeWeb.ShopComponents.Base do
<.link <.link
navigate={@href} navigate={@href}
class={["themed-button-outline", @class]} class={["themed-button-outline", @class]}
style="text-decoration: none; display: inline-block;"
> >
{render_slot(@inner_block)} {render_slot(@inner_block)}
</.link> </.link>

View File

@ -38,15 +38,9 @@ defmodule SimpleshopThemeWeb.ShopComponents.Content do
def content_body(assigns) do def content_body(assigns) do
~H""" ~H"""
<div <div class="content-body">
class="content-body"
style="padding: var(--space-xl) var(--space-lg); max-width: 800px; margin: 0 auto;"
>
<%= if @image_src do %> <%= if @image_src do %>
<div <div class="content-image about-image">
class="content-image about-image"
style="margin-bottom: var(--space-lg); border-radius: var(--t-radius-image); overflow: hidden;"
>
<.responsive_image <.responsive_image
src={@image_src} src={@image_src}
source_width={1200} source_width={1200}
@ -57,7 +51,7 @@ defmodule SimpleshopThemeWeb.ShopComponents.Content do
</div> </div>
<% end %> <% end %>
<div class="content-text" style="line-height: 1.7;"> <div class="content-text">
{render_slot(@inner_block)} {render_slot(@inner_block)}
</div> </div>
</div> </div>
@ -85,20 +79,17 @@ defmodule SimpleshopThemeWeb.ShopComponents.Content do
def contact_form(assigns) do def contact_form(assigns) do
~H""" ~H"""
<.shop_card class="p-8"> <.shop_card class="p-8">
<h2 <h2 class="t-heading text-xl font-bold mb-2">
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 %> <%= if @email || @response_time do %>
<div class="flex flex-col gap-1 mb-6 text-sm" style="color: var(--t-text-secondary);"> <div class="contact-form-meta flex flex-col gap-1 mb-6 text-sm">
<%= if @email do %> <%= if @email do %>
<p> <p>
Email me: Email me:
<a <a
href={"mailto:#{@email}"} href={"mailto:#{@email}"}
style="color: hsl(var(--t-accent-h) var(--t-accent-s) var(--t-accent-l));" class="accent-email"
> >
{@email} {@email}
</a> </a>
@ -114,28 +105,28 @@ defmodule SimpleshopThemeWeb.ShopComponents.Content do
<form class="flex flex-col gap-4"> <form class="flex flex-col gap-4">
<div> <div>
<label class="block font-medium mb-2" style="color: var(--t-text-primary);"> <label class="contact-form-label block font-medium mb-2">
Name Name
</label> </label>
<.shop_input type="text" placeholder="Your name" class="w-full px-4 py-2" /> <.shop_input type="text" placeholder="Your name" class="w-full px-4 py-2" />
</div> </div>
<div> <div>
<label class="block font-medium mb-2" style="color: var(--t-text-primary);"> <label class="contact-form-label block font-medium mb-2">
Email Email
</label> </label>
<.shop_input type="email" placeholder="your@email.com" class="w-full px-4 py-2" /> <.shop_input type="email" placeholder="your@email.com" class="w-full px-4 py-2" />
</div> </div>
<div> <div>
<label class="block font-medium mb-2" style="color: var(--t-text-primary);"> <label class="contact-form-label block font-medium mb-2">
Subject Subject
</label> </label>
<.shop_input type="text" placeholder="How can I help?" class="w-full px-4 py-2" /> <.shop_input type="text" placeholder="How can I help?" class="w-full px-4 py-2" />
</div> </div>
<div> <div>
<label class="block font-medium mb-2" style="color: var(--t-text-primary);"> <label class="contact-form-label block font-medium mb-2">
Message Message
</label> </label>
<.shop_textarea rows="5" placeholder="Your message..." class="w-full px-4 py-2" /> <.shop_textarea rows="5" placeholder="Your message..." class="w-full px-4 py-2" />
@ -159,16 +150,15 @@ defmodule SimpleshopThemeWeb.ShopComponents.Content do
def order_tracking_card(assigns) do def order_tracking_card(assigns) do
~H""" ~H"""
<.shop_card class="p-6"> <.shop_card class="p-6">
<h3 class="font-bold mb-3" style="color: var(--t-text-primary);">Track your order</h3> <h3 class="card-heading font-bold mb-3">Track your order</h3>
<p class="text-sm mb-3" style="color: var(--t-text-secondary);"> <p class="card-text text-sm mb-3">
Enter your email and I'll send you a link to check your order status. Enter your email and I'll send you a link to check your order status.
</p> </p>
<div class="flex flex-wrap gap-2"> <div class="flex flex-wrap gap-2">
<.shop_input <.shop_input
type="email" type="email"
placeholder="your@email.com" placeholder="your@email.com"
class="flex-1 min-w-0 px-3 py-2 text-sm" class="email-input flex-1 min-w-0 px-3 py-2 text-sm"
style="min-width: 150px;"
/> />
<.shop_button class="px-4 py-2 text-sm font-medium whitespace-nowrap"> <.shop_button class="px-4 py-2 text-sm font-medium whitespace-nowrap">
Send Send
@ -199,13 +189,13 @@ defmodule SimpleshopThemeWeb.ShopComponents.Content do
def info_card(assigns) do def info_card(assigns) do
~H""" ~H"""
<.shop_card class="p-6"> <.shop_card class="p-6">
<h3 class="font-bold mb-3" style="color: var(--t-text-primary);">{@title}</h3> <h3 class="card-heading font-bold mb-3">{@title}</h3>
<ul class="flex flex-col gap-2 text-sm" style="color: var(--t-text-secondary);"> <ul class="info-card-list flex flex-col gap-2 text-sm">
<%= for item <- @items do %> <%= for item <- @items do %>
<li class="flex items-start gap-2"> <li class="flex items-start gap-2">
<span style="color: var(--t-text-tertiary);"></span> <span class="info-card-bullet"></span>
<span> <span>
<strong style="color: var(--t-text-primary);">{item.label}:</strong> {item.value} <strong class="info-card-label">{item.label}:</strong> {item.value}
</span> </span>
</li> </li>
<% end %> <% end %>
@ -234,11 +224,10 @@ defmodule SimpleshopThemeWeb.ShopComponents.Content do
def contact_info_card(assigns) do def contact_info_card(assigns) do
~H""" ~H"""
<.shop_card class="p-6"> <.shop_card class="p-6">
<h3 class="font-bold mb-3" style="color: var(--t-text-primary);">{@title}</h3> <h3 class="card-heading font-bold mb-3">{@title}</h3>
<a <a
href={"mailto:#{@email}"} href={"mailto:#{@email}"}
class="flex items-center gap-2 mb-2" class="contact-info-email flex items-center gap-2 mb-2"
style="color: hsl(var(--t-accent-h) var(--t-accent-s) var(--t-accent-l)); text-decoration: none;"
> >
<svg <svg
class="w-4 h-4" class="w-4 h-4"
@ -257,7 +246,7 @@ defmodule SimpleshopThemeWeb.ShopComponents.Content do
</svg> </svg>
{@email} {@email}
</a> </a>
<p class="text-sm" style="color: var(--t-text-secondary);"> <p class="card-text text-sm">
{@response_text} {@response_text}
</p> </p>
</.shop_card> </.shop_card>
@ -291,21 +280,17 @@ defmodule SimpleshopThemeWeb.ShopComponents.Content do
def newsletter_card(%{variant: :inline} = assigns) do def newsletter_card(%{variant: :inline} = assigns) do
~H""" ~H"""
<div> <div>
<h3 <h3 class="t-heading text-xl font-bold mb-2">
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} {@title}
</h3> </h3>
<p class="text-sm mb-4" style="color: var(--t-text-secondary);"> <p class="card-text text-sm mb-4">
{@description} {@description}
</p> </p>
<form class="flex flex-wrap gap-2"> <form class="flex flex-wrap gap-2">
<.shop_input <.shop_input
type="email" type="email"
placeholder="your@email.com" placeholder="your@email.com"
class="flex-1 min-w-0 px-4 py-2 text-sm" class="email-input flex-1 min-w-0 px-4 py-2 text-sm"
style="min-width: 150px;"
/> />
<.shop_button type="submit" class="px-6 py-2 text-sm font-medium whitespace-nowrap"> <.shop_button type="submit" class="px-6 py-2 text-sm font-medium whitespace-nowrap">
{@button_text} {@button_text}
@ -318,16 +303,15 @@ defmodule SimpleshopThemeWeb.ShopComponents.Content do
def newsletter_card(assigns) do def newsletter_card(assigns) do
~H""" ~H"""
<.shop_card class="p-6"> <.shop_card class="p-6">
<h3 class="font-bold mb-2" style="color: var(--t-text-primary);">{@title}</h3> <h3 class="card-heading font-bold mb-2">{@title}</h3>
<p class="text-sm mb-4" style="color: var(--t-text-secondary);"> <p class="card-text text-sm mb-4">
{@description} {@description}
</p> </p>
<form class="flex flex-wrap gap-2"> <form class="flex flex-wrap gap-2">
<.shop_input <.shop_input
type="email" type="email"
placeholder="your@email.com" placeholder="your@email.com"
class="flex-1 min-w-0 px-3 py-2 text-sm" class="email-input flex-1 min-w-0 px-3 py-2 text-sm"
style="min-width: 150px;"
/> />
<.shop_button type="submit" class="px-4 py-2 text-sm font-medium whitespace-nowrap"> <.shop_button type="submit" class="px-4 py-2 text-sm font-medium whitespace-nowrap">
{@button_text} {@button_text}
@ -358,17 +342,16 @@ defmodule SimpleshopThemeWeb.ShopComponents.Content do
def social_links_card(assigns) do def social_links_card(assigns) do
~H""" ~H"""
<.shop_card class="p-6"> <.shop_card class="p-6">
<h3 class="font-bold mb-4" style="color: var(--t-text-primary);">{@title}</h3> <h3 class="card-heading font-bold mb-4">{@title}</h3>
<div class="flex flex-wrap gap-2"> <div class="flex flex-wrap gap-2">
<%= for link <- @links do %> <%= for link <- @links do %>
<a <a
href={link.url} href={link.url}
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
class="themed-button-outline flex items-center gap-2 px-3 py-2 text-sm transition-all hover:opacity-80" class="social-link-card-item themed-button-outline flex items-center gap-2 px-3 py-2 text-sm transition-all hover:opacity-80"
style="text-decoration: none;"
> >
<span style="color: var(--t-text-secondary);"> <span class="social-link-card-icon">
<.social_icon platform={link.platform} /> <.social_icon platform={link.platform} />
</span> </span>
<span>{link.label}</span> <span>{link.label}</span>
@ -403,7 +386,6 @@ defmodule SimpleshopThemeWeb.ShopComponents.Content do
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
class="social-link w-9 h-9 flex items-center justify-center transition-all" 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={link.label} aria-label={link.label}
> >
<.social_icon platform={link.platform} /> <.social_icon platform={link.platform} />
@ -732,21 +714,18 @@ defmodule SimpleshopThemeWeb.ShopComponents.Content do
def trust_badges(assigns) do def trust_badges(assigns) do
~H""" ~H"""
<div <div class="trust-badges flex flex-col gap-3 p-4">
class="flex flex-col gap-3 p-4"
style="background-color: var(--t-surface-sunken); border-radius: var(--t-radius-card);"
>
<%= for item <- @items do %> <%= for item <- @items do %>
<div class="flex items-start gap-3"> <div class="flex items-start gap-3">
<span style="color: hsl(var(--t-accent-h) var(--t-accent-s) var(--t-accent-l));"> <span class="trust-badge-icon">
<SimpleshopThemeWeb.CoreComponents.icon <SimpleshopThemeWeb.CoreComponents.icon
name="hero-check-circle" name="hero-check-circle"
class="size-5 mt-0.5 shrink-0" class="size-5 mt-0.5 shrink-0"
/> />
</span> </span>
<div> <div>
<p class="font-semibold" style="color: var(--t-text-primary);">{item.title}</p> <p class="trust-badge-title font-semibold">{item.title}</p>
<p class="text-sm" style="color: var(--t-text-secondary);">{item.description}</p> <p class="trust-badge-text text-sm">{item.description}</p>
</div> </div>
</div> </div>
<% end %> <% end %>
@ -789,22 +768,15 @@ defmodule SimpleshopThemeWeb.ShopComponents.Content do
<details <details
open={@open} open={@open}
class="pdp-reviews group" class="pdp-reviews group"
style="border-top: 1px solid var(--t-border-default);"
> >
<summary <summary class="reviews-summary flex justify-between items-center py-6 cursor-pointer list-none [&::-webkit-details-marker]:hidden">
class="flex justify-between items-center py-6 cursor-pointer list-none [&::-webkit-details-marker]:hidden"
style="color: var(--t-text-primary);"
>
<div class="flex flex-col sm:flex-row sm:items-center gap-2 sm:gap-4"> <div class="flex flex-col sm:flex-row sm:items-center gap-2 sm:gap-4">
<h2 <h2 class="t-heading text-2xl font-bold">
class="text-2xl font-bold"
style="font-family: var(--t-font-heading); color: var(--t-text-primary); font-weight: var(--t-heading-weight);"
>
Customer reviews Customer reviews
</h2> </h2>
<div class="flex items-center gap-2"> <div class="flex items-center gap-2">
<.star_rating rating={@average_rating} /> <.star_rating rating={@average_rating} />
<span class="text-sm" style="color: var(--t-text-secondary);">({@display_count})</span> <span class="reviews-count text-sm">({@display_count})</span>
</div> </div>
</div> </div>
<svg <svg
@ -849,24 +821,21 @@ defmodule SimpleshopThemeWeb.ShopComponents.Content do
def review_card(assigns) do def review_card(assigns) do
~H""" ~H"""
<article class="pb-6" style="border-bottom: 1px solid var(--t-border-subtle);"> <article class="review-card pb-6">
<div class="flex items-center justify-between mb-2"> <div class="flex items-center justify-between mb-2">
<.star_rating rating={@review.rating} /> <.star_rating rating={@review.rating} />
<span class="text-xs" style="color: var(--t-text-tertiary);">{@review.date}</span> <span class="review-date text-xs">{@review.date}</span>
</div> </div>
<h3 class="font-semibold mb-1" style="color: var(--t-text-primary);">{@review.title}</h3> <h3 class="review-title font-semibold mb-1">{@review.title}</h3>
<p class="text-sm mb-3" style="color: var(--t-text-secondary); line-height: 1.6;"> <p class="review-body text-sm mb-3">
{@review.body} {@review.body}
</p> </p>
<div class="flex items-center gap-2"> <div class="flex items-center gap-2">
<span class="text-sm font-medium" style="color: var(--t-text-primary);"> <span class="review-author text-sm font-medium">
{@review.author} {@review.author}
</span> </span>
<%= if @review.verified do %> <%= if @review.verified do %>
<span <span class="review-verified text-xs px-2 py-0.5 rounded">
class="text-xs px-2 py-0.5 rounded"
style="background-color: var(--t-surface-sunken); color: var(--t-text-tertiary);"
>
Verified purchase Verified purchase
</span> </span>
<% end %> <% end %>
@ -893,10 +862,7 @@ defmodule SimpleshopThemeWeb.ShopComponents.Content do
def page_title(assigns) do def page_title(assigns) do
~H""" ~H"""
<h1 <h1 class={"t-heading text-3xl md:text-4xl font-bold #{@class}"}>
class={"text-3xl md:text-4xl font-bold #{@class}"}
style="font-family: var(--t-font-heading); color: var(--t-text-primary); font-weight: var(--t-heading-weight); letter-spacing: var(--t-heading-tracking);"
>
{@text} {@text}
</h1> </h1>
""" """
@ -928,7 +894,7 @@ defmodule SimpleshopThemeWeb.ShopComponents.Content do
def rich_text(assigns) do def rich_text(assigns) do
~H""" ~H"""
<div class="rich-text" style="line-height: 1.7;"> <div class="rich-text">
<%= for block <- @blocks do %> <%= for block <- @blocks do %>
<.rich_text_block block={block} /> <.rich_text_block block={block} />
<% end %> <% end %>
@ -940,7 +906,7 @@ defmodule SimpleshopThemeWeb.ShopComponents.Content do
defp rich_text_block(%{block: %{type: :lead}} = assigns) do defp rich_text_block(%{block: %{type: :lead}} = assigns) do
~H""" ~H"""
<p class="lead-text text-lg mb-4" style="color: var(--t-text-primary);"> <p class="rich-text-lead lead-text text-lg mb-4">
{@block.text} {@block.text}
</p> </p>
""" """
@ -948,7 +914,7 @@ defmodule SimpleshopThemeWeb.ShopComponents.Content do
defp rich_text_block(%{block: %{type: :paragraph}} = assigns) do defp rich_text_block(%{block: %{type: :paragraph}} = assigns) do
~H""" ~H"""
<p class="mb-4" style="color: var(--t-text-secondary);"> <p class="rich-text-paragraph mb-4">
{@block.text} {@block.text}
</p> </p>
""" """
@ -956,10 +922,7 @@ defmodule SimpleshopThemeWeb.ShopComponents.Content do
defp rich_text_block(%{block: %{type: :heading}} = assigns) do defp rich_text_block(%{block: %{type: :heading}} = assigns) do
~H""" ~H"""
<h2 <h2 class="rich-text-heading mt-8 mb-3">
class="mt-8 mb-3"
style="font-family: var(--t-font-heading); font-weight: var(--t-heading-weight); font-size: var(--t-text-xl); color: var(--t-text-primary);"
>
{@block.text} {@block.text}
</h2> </h2>
""" """
@ -967,7 +930,7 @@ defmodule SimpleshopThemeWeb.ShopComponents.Content do
defp rich_text_block(%{block: %{type: :closing}} = assigns) do defp rich_text_block(%{block: %{type: :closing}} = assigns) do
~H""" ~H"""
<p class="mt-8" style="color: var(--t-text-secondary);"> <p class="rich-text-paragraph mt-8">
{@block.text} {@block.text}
</p> </p>
""" """
@ -975,7 +938,7 @@ defmodule SimpleshopThemeWeb.ShopComponents.Content do
defp rich_text_block(%{block: %{type: :list}} = assigns) do defp rich_text_block(%{block: %{type: :list}} = assigns) do
~H""" ~H"""
<ul class="mb-4 ml-6 list-disc" style="color: var(--t-text-secondary);"> <ul class="rich-text-list mb-4 ml-6 list-disc">
<%= for item <- @block.items do %> <%= for item <- @block.items do %>
<li class="mb-1">{item}</li> <li class="mb-1">{item}</li>
<% end %> <% end %>
@ -985,7 +948,7 @@ defmodule SimpleshopThemeWeb.ShopComponents.Content do
defp rich_text_block(assigns) do defp rich_text_block(assigns) do
~H""" ~H"""
<p class="mb-4" style="color: var(--t-text-secondary);"> <p class="rich-text-paragraph mb-4">
{@block.text} {@block.text}
</p> </p>
""" """
@ -1094,8 +1057,7 @@ defmodule SimpleshopThemeWeb.ShopComponents.Content do
<%= if msg = Phoenix.Flash.get(@flash, :info) do %> <%= if msg = Phoenix.Flash.get(@flash, :info) do %>
<div <div
id="shop-flash-info" id="shop-flash-info"
class="flex items-center gap-3 px-4 py-3 rounded-lg shadow-lg max-w-sm animate-in" class="shop-flash shop-flash--info flex items-center gap-3 px-4 py-3 rounded-lg shadow-lg max-w-sm animate-in"
style="background-color: var(--t-surface-raised, #fff); color: var(--t-text-primary); border: 1px solid var(--t-border-default);"
role="alert" role="alert"
phx-click={ phx-click={
Phoenix.LiveView.JS.push("lv:clear-flash", value: %{key: :info}) Phoenix.LiveView.JS.push("lv:clear-flash", value: %{key: :info})
@ -1106,10 +1068,9 @@ defmodule SimpleshopThemeWeb.ShopComponents.Content do
} }
> >
<svg <svg
class="w-5 h-5 shrink-0" class="shop-flash-icon--info w-5 h-5 shrink-0"
width="20" width="20"
height="20" height="20"
style="color: var(--t-accent);"
fill="none" fill="none"
viewBox="0 0 24 24" viewBox="0 0 24 24"
stroke-width="1.5" stroke-width="1.5"
@ -1123,8 +1084,7 @@ defmodule SimpleshopThemeWeb.ShopComponents.Content do
<%= if msg = Phoenix.Flash.get(@flash, :error) do %> <%= if msg = Phoenix.Flash.get(@flash, :error) do %>
<div <div
id="shop-flash-error" id="shop-flash-error"
class="flex items-center gap-3 px-4 py-3 rounded-lg shadow-lg max-w-sm animate-in" class="shop-flash shop-flash--error flex items-center gap-3 px-4 py-3 rounded-lg shadow-lg max-w-sm animate-in"
style="background-color: var(--t-surface-raised, #fff); color: var(--t-text-primary); border: 1px solid hsl(0 70% 50% / 0.3);"
role="alert" role="alert"
phx-click={ phx-click={
Phoenix.LiveView.JS.push("lv:clear-flash", value: %{key: :error}) Phoenix.LiveView.JS.push("lv:clear-flash", value: %{key: :error})
@ -1135,10 +1095,9 @@ defmodule SimpleshopThemeWeb.ShopComponents.Content do
} }
> >
<svg <svg
class="w-5 h-5 shrink-0" class="shop-flash-icon--error w-5 h-5 shrink-0"
width="20" width="20"
height="20" height="20"
style="color: hsl(0 70% 50%);"
fill="none" fill="none"
viewBox="0 0 24 24" viewBox="0 0 24 24"
stroke-width="1.5" stroke-width="1.5"