Move the search modal from ThemeLive.PreviewPages to the shared ShopComponents module. Add optional hint_text attribute - preview pages pass demo hint text while real stores can omit it. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
126 lines
4.3 KiB
Elixir
126 lines
4.3 KiB
Elixir
defmodule SimpleshopThemeWeb.ShopComponents do
|
|
@moduledoc """
|
|
Provides shop/storefront UI components.
|
|
|
|
These components are shared between the theme preview system and
|
|
the public storefront pages. They render using CSS custom properties
|
|
defined by the theme settings.
|
|
"""
|
|
use Phoenix.Component
|
|
|
|
@doc """
|
|
Renders the announcement bar.
|
|
|
|
The bar displays promotional messaging at the top of the page.
|
|
It uses CSS custom properties for theming.
|
|
|
|
## Attributes
|
|
|
|
* `theme_settings` - Required. The theme settings map.
|
|
* `message` - Optional. The announcement message to display.
|
|
Defaults to "Free delivery on orders over £40".
|
|
|
|
## Examples
|
|
|
|
<.announcement_bar theme_settings={@theme_settings} />
|
|
<.announcement_bar theme_settings={@theme_settings} message="20% off this weekend!" />
|
|
"""
|
|
attr :theme_settings, :map, required: true
|
|
attr :message, :string, default: "Free delivery on orders over £40"
|
|
|
|
def announcement_bar(assigns) do
|
|
~H"""
|
|
<div
|
|
class="announcement-bar"
|
|
style="background-color: hsl(var(--t-accent-h) var(--t-accent-s) var(--t-accent-l)); color: var(--t-text-inverse); text-align: center; padding: 0.5rem 1rem; font-size: var(--t-text-small);"
|
|
>
|
|
<p style="margin: 0;">{@message}</p>
|
|
</div>
|
|
"""
|
|
end
|
|
|
|
@doc """
|
|
Renders the skip link for keyboard navigation accessibility.
|
|
|
|
This is a standard accessibility pattern that allows keyboard users
|
|
to skip directly to the main content.
|
|
"""
|
|
def skip_link(assigns) do
|
|
~H"""
|
|
<a href="#main-content" class="skip-link">
|
|
Skip to main content
|
|
</a>
|
|
"""
|
|
end
|
|
|
|
@doc """
|
|
Renders the search modal overlay.
|
|
|
|
This is a modal dialog for searching products. Currently provides
|
|
the UI shell; search functionality will be added later.
|
|
|
|
## Attributes
|
|
|
|
* `hint_text` - Optional. Hint text shown below the search input.
|
|
Defaults to nil (no hint shown).
|
|
|
|
## Examples
|
|
|
|
<.search_modal />
|
|
<.search_modal hint_text="Try searching for \"mountain\" or \"forest\"" />
|
|
"""
|
|
attr :hint_text, :string, default: nil
|
|
|
|
def search_modal(assigns) do
|
|
~H"""
|
|
<div
|
|
id="search-modal"
|
|
class="search-modal"
|
|
style="position: fixed; inset: 0; background: rgba(0,0,0,0.5); z-index: 1001; display: none; align-items: flex-start; justify-content: center; padding-top: 10vh;"
|
|
phx-click={Phoenix.LiveView.JS.hide(to: "#search-modal")}
|
|
>
|
|
<div
|
|
class="search-modal-content w-full max-w-xl mx-4"
|
|
style="background: var(--t-surface-raised); border-radius: var(--t-radius-card); overflow: hidden; box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);"
|
|
phx-click-away={Phoenix.LiveView.JS.hide(to: "#search-modal")}
|
|
>
|
|
<div
|
|
class="flex items-center gap-3 p-4"
|
|
style="border-bottom: 1px solid var(--t-border-default);"
|
|
>
|
|
<svg class="w-5 h-5 flex-shrink-0" style="color: var(--t-text-tertiary);" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
<circle cx="11" cy="11" r="8"></circle>
|
|
<path d="M21 21l-4.35-4.35"></path>
|
|
</svg>
|
|
<input
|
|
type="text"
|
|
id="search-input"
|
|
class="flex-1 text-lg bg-transparent border-none outline-none"
|
|
style="font-family: var(--t-font-body); color: var(--t-text-primary);"
|
|
placeholder="Search products..."
|
|
phx-click={Phoenix.LiveView.JS.dispatch("stop-propagation")}
|
|
/>
|
|
<button
|
|
type="button"
|
|
class="w-8 h-8 flex items-center justify-center transition-all"
|
|
style="color: var(--t-text-tertiary); background: none; border: none; cursor: pointer; border-radius: var(--t-radius-button);"
|
|
phx-click={Phoenix.LiveView.JS.hide(to: "#search-modal")}
|
|
aria-label="Close search"
|
|
>
|
|
<svg class="w-5 h-5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
<line x1="18" y1="6" x2="6" y2="18"></line>
|
|
<line x1="6" y1="6" x2="18" y2="18"></line>
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
<%= if @hint_text do %>
|
|
<div class="p-6" style="color: var(--t-text-tertiary);">
|
|
<p class="text-sm">{@hint_text}</p>
|
|
</div>
|
|
<% end %>
|
|
</div>
|
|
</div>
|
|
"""
|
|
end
|
|
end
|