replace Tailwind utilities in layout + page templates with CSS (Phase 5a)
Absorb ~100 Tailwind utility classes from layout.ex and all page templates into semantic CSS rules in components.css. Uses theme font-size vars (--t-text-small, --t-text-caption) instead of rem to respect the theme's em-based scaling system. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -100,7 +100,8 @@ defmodule SimpleshopThemeWeb.ShopComponents.Layout do
|
||||
<div
|
||||
id={unless @error_page, do: "shop-container"}
|
||||
phx-hook={unless @error_page, do: "CartPersist"}
|
||||
class={["shop-container min-h-screen", !@error_page && "pb-20 md:pb-0"]}
|
||||
class="shop-container"
|
||||
data-bottom-nav={!@error_page || nil}
|
||||
>
|
||||
<.skip_link />
|
||||
|
||||
@@ -177,10 +178,10 @@ defmodule SimpleshopThemeWeb.ShopComponents.Layout do
|
||||
def mobile_bottom_nav(assigns) do
|
||||
~H"""
|
||||
<nav
|
||||
class="mobile-bottom-nav md:hidden"
|
||||
class="mobile-bottom-nav"
|
||||
aria-label="Main navigation"
|
||||
>
|
||||
<ul class="flex justify-around items-center h-16">
|
||||
<ul>
|
||||
<.mobile_nav_item
|
||||
icon={:home}
|
||||
label="Home"
|
||||
@@ -233,26 +234,26 @@ defmodule SimpleshopThemeWeb.ShopComponents.Layout do
|
||||
assigns = assign(assigns, :is_current, is_current)
|
||||
|
||||
~H"""
|
||||
<li class="flex-1">
|
||||
<li>
|
||||
<%= if @mode == :preview do %>
|
||||
<a
|
||||
href="#"
|
||||
phx-click="change_preview_page"
|
||||
phx-value-page={@page}
|
||||
class="mobile-nav-link flex flex-col items-center justify-center gap-1 py-2 mx-1 rounded-lg min-h-[56px]"
|
||||
class="mobile-nav-link"
|
||||
aria-current={if @is_current, do: "page", else: nil}
|
||||
>
|
||||
<.nav_icon icon={@icon} size={if @is_current, do: "w-6 h-6", else: "w-5 h-5"} />
|
||||
<span class="text-xs">{@label}</span>
|
||||
<.nav_icon icon={@icon} />
|
||||
<span>{@label}</span>
|
||||
</a>
|
||||
<% else %>
|
||||
<.link
|
||||
navigate={@href}
|
||||
class="mobile-nav-link flex flex-col items-center justify-center gap-1 py-2 mx-1 rounded-lg min-h-[56px]"
|
||||
class="mobile-nav-link"
|
||||
aria-current={if @is_current, do: "page", else: nil}
|
||||
>
|
||||
<.nav_icon icon={@icon} size={if @is_current, do: "w-6 h-6", else: "w-5 h-5"} />
|
||||
<span class="text-xs">{@label}</span>
|
||||
<.nav_icon icon={@icon} />
|
||||
<span>{@label}</span>
|
||||
</.link>
|
||||
<% end %>
|
||||
</li>
|
||||
@@ -260,11 +261,8 @@ defmodule SimpleshopThemeWeb.ShopComponents.Layout do
|
||||
end
|
||||
|
||||
defp nav_icon(%{icon: :home} = assigns) do
|
||||
assigns = assign_new(assigns, :size, fn -> "w-5 h-5" end)
|
||||
|
||||
~H"""
|
||||
<svg
|
||||
class={@size}
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
@@ -281,11 +279,8 @@ defmodule SimpleshopThemeWeb.ShopComponents.Layout do
|
||||
end
|
||||
|
||||
defp nav_icon(%{icon: :shop} = assigns) do
|
||||
assigns = assign_new(assigns, :size, fn -> "w-5 h-5" end)
|
||||
|
||||
~H"""
|
||||
<svg
|
||||
class={@size}
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
@@ -304,11 +299,8 @@ defmodule SimpleshopThemeWeb.ShopComponents.Layout do
|
||||
end
|
||||
|
||||
defp nav_icon(%{icon: :about} = assigns) do
|
||||
assigns = assign_new(assigns, :size, fn -> "w-5 h-5" end)
|
||||
|
||||
~H"""
|
||||
<svg
|
||||
class={@size}
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
@@ -326,11 +318,8 @@ defmodule SimpleshopThemeWeb.ShopComponents.Layout do
|
||||
end
|
||||
|
||||
defp nav_icon(%{icon: :contact} = assigns) do
|
||||
assigns = assign_new(assigns, :size, fn -> "w-5 h-5" end)
|
||||
|
||||
~H"""
|
||||
<svg
|
||||
class={@size}
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
@@ -385,12 +374,12 @@ defmodule SimpleshopThemeWeb.ShopComponents.Layout do
|
||||
phx-click={Phoenix.LiveView.JS.dispatch("close-search", to: "#search-modal")}
|
||||
>
|
||||
<div
|
||||
class="search-panel w-full max-w-xl mx-4"
|
||||
class="search-panel"
|
||||
onclick="event.stopPropagation()"
|
||||
>
|
||||
<div class="search-bar flex items-center gap-3 p-4">
|
||||
<div class="search-bar">
|
||||
<svg
|
||||
class="search-icon w-5 h-5 flex-shrink-0"
|
||||
class="search-icon"
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 24 24"
|
||||
@@ -405,7 +394,7 @@ defmodule SimpleshopThemeWeb.ShopComponents.Layout do
|
||||
type="text"
|
||||
id="search-input"
|
||||
name="query"
|
||||
class="search-input flex-1 text-lg bg-transparent border-none outline-none"
|
||||
class="search-input"
|
||||
placeholder="Search products..."
|
||||
value={@search_query}
|
||||
phx-keyup="search"
|
||||
@@ -417,19 +406,18 @@ defmodule SimpleshopThemeWeb.ShopComponents.Layout do
|
||||
aria-autocomplete="list"
|
||||
/>
|
||||
<div
|
||||
class="search-kbd hidden sm:flex items-center gap-1 text-xs px-1.5 py-0.5 rounded"
|
||||
class="search-kbd"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<kbd>⌘</kbd><kbd>K</kbd>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
class="search-close w-8 h-8 flex items-center justify-center transition-all"
|
||||
class="search-close"
|
||||
phx-click={Phoenix.LiveView.JS.dispatch("close-search", to: "#search-modal")}
|
||||
aria-label="Close search"
|
||||
>
|
||||
<svg
|
||||
class="w-5 h-5"
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 24 24"
|
||||
@@ -446,7 +434,7 @@ defmodule SimpleshopThemeWeb.ShopComponents.Layout do
|
||||
<div class="search-results">
|
||||
<%= cond do %>
|
||||
<% @search_results != [] -> %>
|
||||
<ul id="search-results-list" class="py-2" role="listbox" aria-label="Search results">
|
||||
<ul id="search-results-list" role="listbox" aria-label="Search results">
|
||||
<li
|
||||
:for={item <- @results_with_images}
|
||||
id={"search-result-#{item.idx}"}
|
||||
@@ -455,27 +443,26 @@ defmodule SimpleshopThemeWeb.ShopComponents.Layout do
|
||||
>
|
||||
<.link
|
||||
navigate={"/products/#{item.product.slug || item.product.id}"}
|
||||
class="search-result flex items-center gap-3 px-4 py-3 transition-colors"
|
||||
class="search-result"
|
||||
phx-click={Phoenix.LiveView.JS.dispatch("close-search", to: "#search-modal")}
|
||||
>
|
||||
<div
|
||||
:if={item.image_url}
|
||||
class="search-result-thumb w-12 h-12 flex-shrink-0 rounded overflow-hidden"
|
||||
class="search-result-thumb"
|
||||
>
|
||||
<img
|
||||
src={item.image_url}
|
||||
alt={item.product.title}
|
||||
class="w-full h-full object-cover"
|
||||
loading="lazy"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex-1 min-w-0">
|
||||
<p class="search-result-title text-sm font-medium truncate">
|
||||
<div class="search-result-details">
|
||||
<p class="search-result-title">
|
||||
{item.product.title}
|
||||
</p>
|
||||
<p class="search-result-meta text-xs">
|
||||
<p class="search-result-meta">
|
||||
{item.product.category}
|
||||
<span class="ml-2">
|
||||
<span>
|
||||
{Cart.format_price(item.product.cheapest_price)}
|
||||
</span>
|
||||
</p>
|
||||
@@ -484,12 +471,12 @@ defmodule SimpleshopThemeWeb.ShopComponents.Layout do
|
||||
</li>
|
||||
</ul>
|
||||
<% String.length(@search_query) >= 2 -> %>
|
||||
<div class="search-hint p-6">
|
||||
<p class="text-sm">No products found for "{@search_query}"</p>
|
||||
<div class="search-hint">
|
||||
<p>No products found for "{@search_query}"</p>
|
||||
</div>
|
||||
<% @hint_text != nil -> %>
|
||||
<div class="search-hint p-6">
|
||||
<p class="text-sm">{@hint_text}</p>
|
||||
<div class="search-hint">
|
||||
<p>{@hint_text}</p>
|
||||
</div>
|
||||
<% true -> %>
|
||||
<% end %>
|
||||
@@ -522,24 +509,23 @@ defmodule SimpleshopThemeWeb.ShopComponents.Layout do
|
||||
|
||||
~H"""
|
||||
<footer class="shop-footer">
|
||||
<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="shop-footer-inner">
|
||||
<div class="footer-grid">
|
||||
<.newsletter_card variant={:inline} />
|
||||
|
||||
<!-- Links -->
|
||||
<div class="grid grid-cols-2 gap-8">
|
||||
|
||||
<div class="footer-links">
|
||||
<div>
|
||||
<h4 class="footer-heading font-semibold mb-4 text-sm">
|
||||
<h4 class="footer-heading">
|
||||
Shop
|
||||
</h4>
|
||||
<ul class="flex flex-col gap-2 text-sm">
|
||||
<ul class="footer-nav">
|
||||
<%= if @mode == :preview do %>
|
||||
<li>
|
||||
<a
|
||||
href="#"
|
||||
phx-click="change_preview_page"
|
||||
phx-value-page="collection"
|
||||
class="footer-link transition-colors hover:opacity-80"
|
||||
class="footer-link"
|
||||
>
|
||||
All products
|
||||
</a>
|
||||
@@ -550,7 +536,7 @@ defmodule SimpleshopThemeWeb.ShopComponents.Layout do
|
||||
href="#"
|
||||
phx-click="change_preview_page"
|
||||
phx-value-page="collection"
|
||||
class="footer-link transition-colors hover:opacity-80"
|
||||
class="footer-link"
|
||||
>
|
||||
{category.name}
|
||||
</a>
|
||||
@@ -560,7 +546,7 @@ defmodule SimpleshopThemeWeb.ShopComponents.Layout do
|
||||
<li>
|
||||
<.link
|
||||
navigate="/collections/all"
|
||||
class="footer-link transition-colors hover:opacity-80"
|
||||
class="footer-link"
|
||||
>
|
||||
All products
|
||||
</.link>
|
||||
@@ -569,7 +555,7 @@ defmodule SimpleshopThemeWeb.ShopComponents.Layout do
|
||||
<li>
|
||||
<.link
|
||||
navigate={"/collections/#{category.slug}"}
|
||||
class="footer-link transition-colors hover:opacity-80"
|
||||
class="footer-link"
|
||||
>
|
||||
{category.name}
|
||||
</.link>
|
||||
@@ -579,17 +565,17 @@ defmodule SimpleshopThemeWeb.ShopComponents.Layout do
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<h4 class="footer-heading font-semibold mb-4 text-sm">
|
||||
<h4 class="footer-heading">
|
||||
Help
|
||||
</h4>
|
||||
<ul class="flex flex-col gap-2 text-sm">
|
||||
<ul class="footer-nav">
|
||||
<%= if @mode == :preview do %>
|
||||
<li>
|
||||
<a
|
||||
href="#"
|
||||
phx-click="change_preview_page"
|
||||
phx-value-page="delivery"
|
||||
class="footer-link transition-colors hover:opacity-80"
|
||||
class="footer-link"
|
||||
>
|
||||
Delivery & returns
|
||||
</a>
|
||||
@@ -599,7 +585,7 @@ defmodule SimpleshopThemeWeb.ShopComponents.Layout do
|
||||
href="#"
|
||||
phx-click="change_preview_page"
|
||||
phx-value-page="privacy"
|
||||
class="footer-link transition-colors hover:opacity-80"
|
||||
class="footer-link"
|
||||
>
|
||||
Privacy policy
|
||||
</a>
|
||||
@@ -609,7 +595,7 @@ defmodule SimpleshopThemeWeb.ShopComponents.Layout do
|
||||
href="#"
|
||||
phx-click="change_preview_page"
|
||||
phx-value-page="terms"
|
||||
class="footer-link transition-colors hover:opacity-80"
|
||||
class="footer-link"
|
||||
>
|
||||
Terms of service
|
||||
</a>
|
||||
@@ -619,7 +605,7 @@ defmodule SimpleshopThemeWeb.ShopComponents.Layout do
|
||||
href="#"
|
||||
phx-click="change_preview_page"
|
||||
phx-value-page="contact"
|
||||
class="footer-link transition-colors hover:opacity-80"
|
||||
class="footer-link"
|
||||
>
|
||||
Contact
|
||||
</a>
|
||||
@@ -628,7 +614,7 @@ defmodule SimpleshopThemeWeb.ShopComponents.Layout do
|
||||
<li>
|
||||
<.link
|
||||
navigate="/delivery"
|
||||
class="footer-link transition-colors hover:opacity-80"
|
||||
class="footer-link"
|
||||
>
|
||||
Delivery & returns
|
||||
</.link>
|
||||
@@ -636,7 +622,7 @@ defmodule SimpleshopThemeWeb.ShopComponents.Layout do
|
||||
<li>
|
||||
<.link
|
||||
navigate="/privacy"
|
||||
class="footer-link transition-colors hover:opacity-80"
|
||||
class="footer-link"
|
||||
>
|
||||
Privacy policy
|
||||
</.link>
|
||||
@@ -644,7 +630,7 @@ defmodule SimpleshopThemeWeb.ShopComponents.Layout do
|
||||
<li>
|
||||
<.link
|
||||
navigate="/terms"
|
||||
class="footer-link transition-colors hover:opacity-80"
|
||||
class="footer-link"
|
||||
>
|
||||
Terms of service
|
||||
</.link>
|
||||
@@ -652,7 +638,7 @@ defmodule SimpleshopThemeWeb.ShopComponents.Layout do
|
||||
<li>
|
||||
<.link
|
||||
navigate="/contact"
|
||||
class="footer-link transition-colors hover:opacity-80"
|
||||
class="footer-link"
|
||||
>
|
||||
Contact
|
||||
</.link>
|
||||
@@ -664,8 +650,8 @@ defmodule SimpleshopThemeWeb.ShopComponents.Layout do
|
||||
</div>
|
||||
|
||||
<!-- Bottom Bar -->
|
||||
<div class="footer-bottom mt-12 pt-8 flex flex-col md:flex-row justify-between items-center gap-4">
|
||||
<p class="footer-copyright text-xs">
|
||||
<div class="footer-bottom">
|
||||
<p class="footer-copyright">
|
||||
© {@current_year} {@theme_settings.site_name}
|
||||
</p>
|
||||
<.social_links />
|
||||
@@ -702,7 +688,7 @@ defmodule SimpleshopThemeWeb.ShopComponents.Layout do
|
||||
|
||||
def shop_header(assigns) do
|
||||
~H"""
|
||||
<header class="shop-header px-2 py-2 sm:px-4 sm:py-3 md:px-8 md:py-4">
|
||||
<header class="shop-header">
|
||||
<%= if @theme_settings.header_background_enabled && @header_image do %>
|
||||
<div style={header_background_style(@theme_settings, @header_image)} />
|
||||
<% end %>
|
||||
@@ -716,7 +702,7 @@ defmodule SimpleshopThemeWeb.ShopComponents.Layout do
|
||||
/>
|
||||
</div>
|
||||
|
||||
<nav class="shop-nav hidden md:flex md:gap-6">
|
||||
<nav class="shop-nav">
|
||||
<%= if @mode == :preview do %>
|
||||
<.nav_item label="Home" page="home" active_page={@active_page} mode={:preview} />
|
||||
<.nav_item
|
||||
@@ -742,15 +728,14 @@ defmodule SimpleshopThemeWeb.ShopComponents.Layout do
|
||||
<% end %>
|
||||
</nav>
|
||||
|
||||
<div class="shop-actions flex items-center">
|
||||
<div class="shop-actions">
|
||||
<.link
|
||||
:if={@is_admin}
|
||||
href="/admin"
|
||||
class="header-icon-btn w-9 h-9 flex items-center justify-center transition-all"
|
||||
class="header-icon-btn"
|
||||
aria-label="Admin"
|
||||
>
|
||||
<svg
|
||||
class="w-5 h-5"
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 24 24"
|
||||
@@ -772,12 +757,11 @@ defmodule SimpleshopThemeWeb.ShopComponents.Layout do
|
||||
</.link>
|
||||
<button
|
||||
type="button"
|
||||
class="header-icon-btn w-9 h-9 flex items-center justify-center transition-all"
|
||||
class="header-icon-btn"
|
||||
phx-click={Phoenix.LiveView.JS.dispatch("open-search", to: "#search-modal")}
|
||||
aria-label="Search"
|
||||
>
|
||||
<svg
|
||||
class="w-5 h-5"
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 24 24"
|
||||
@@ -791,12 +775,11 @@ defmodule SimpleshopThemeWeb.ShopComponents.Layout do
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="header-icon-btn w-9 h-9 flex items-center justify-center transition-all relative"
|
||||
class="header-icon-btn"
|
||||
phx-click={open_cart_drawer_js()}
|
||||
aria-label="Cart"
|
||||
>
|
||||
<svg
|
||||
class="w-5 h-5"
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 24 24"
|
||||
@@ -875,7 +858,7 @@ defmodule SimpleshopThemeWeb.ShopComponents.Layout do
|
||||
<img
|
||||
src={logo_url(@logo_image, @theme_settings)}
|
||||
alt={@theme_settings.site_name}
|
||||
class="shop-logo-img mr-2"
|
||||
class="shop-logo-img"
|
||||
style={"height: #{@theme_settings.logo_size}px;"}
|
||||
/>
|
||||
<% end %>
|
||||
|
||||
Reference in New Issue
Block a user