Replace PreviewData indirection in all shop LiveViews with direct
Products context queries. Home, collection, product detail and error
pages now query the database. Categories loaded once in ThemeHook.
Cart hydration no longer falls back to mock data. PreviewData kept
only for the theme editor.
Search modal gains keyboard navigation (arrow keys, Enter, Escape),
Cmd+K/Ctrl+K shortcut, full ARIA combobox pattern, LiveView navigate
links, and 150ms debounce. SearchModal JS hook manages selection
state and highlight. search.ex gets transaction safety on reindex
and a public remove_product/1. 10 new integration tests.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds SQLite FTS5 search index with BM25 ranking across product title,
category, variant attributes, and description. Search modal now has
live results with thumbnails, prices, and click-to-navigate. Index
rebuilds automatically after each provider sync.
Also fixes Access syntax on Product/ProductImage structs (Map.get
instead of bracket notation) which was causing crashes when real
products were loaded from the database.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds cheapest_price, compare_at_price, in_stock, on_sale columns to
products table (recomputed from variants after each sync). Shop
components now work with Product structs directly instead of plain
maps from PreviewData. Renames .name to .title, adds Product display
helpers (primary_image, hover_image, option_types) and ProductImage
helpers (display_url, direct_url, source_width). Adds Products context
query functions for storefront use (list_visible_products,
get_visible_product, list_categories with DB-level sort/filter).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
All internal links used plain <a href>, causing full page reloads
between pages in the same live_session. Changed to <.link navigate>
for client-side navigation across layout, product, cart, base, and
content components.
Added explicit width/height attributes to all SVG icons so they
render at sensible sizes before CSS loads on initial page visit.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- collection filter bar: horizontal scroll on mobile instead of wrapping
across 3 rows, smaller pills at mobile sizes
- add sale collection filter at /collections/sale (filters on_sale products)
- hero :page variant: add consistent top padding (var(--space-2xl))
- contact page: remove redundant top padding (hero handles it now)
- error page: fix CSS path from /assets/app.css to /assets/css/app.css
(broken in production due to asset fingerprinting)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The stretched-link ::after pseudo-element (z-index: 0) was covering
the image area, intercepting touch events. Give the image container
z-index: 1 so swipe gestures reach the scroll container.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
shop_footer now calls PreviewData.categories() itself, removing the
need to thread categories through CartHook, shop_layout, and all 8
page templates.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- add missing cta_href to hero section and error page CTAs
- replace hardcoded footer shop links with real product categories
- restructure product cards with stretched-link pattern so category
badges link to their collection page
- unify social icons: footer and contact page share the same default
links from a single source in content.ex
- add search implementation plan (docs/plans/search.md, deferred)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The drawer now has full quantity controls, remove, subtotal, and
checkout — the link to the cart page added friction without value.
Cart page remains accessible via the basket icon in nav.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move increment/decrement handlers from Cart LiveView into CartHook so
they work from any page's drawer. Enable show_quantity_controls on the
drawer's cart_item_row. Scope cart tests to #main-content to avoid
duplicate button matches.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Wire up +/− buttons with phx-click events and handle_event handlers,
clamp to 1–99, reset to 1 after add-to-cart. Trust badges now use a
single hero-check-circle icon and sentence case text.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Rewrite breadcrumb as semantic ol/li with aria-current="page", CSS
chevron separators, 0.875em font size, and ellipsis truncation on
mobile for long product names.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Mobile: swipeable carousel with dot indicators, no lightbox trigger.
Desktop: carousel with thumbnail grid, prev/next arrows, click to
open existing lightbox. Keeps all lightbox appearance and behaviour.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Product cards now use CSS scroll-snap on touch devices (mobile) for
swiping between images, with dot indicators and a JS hook for active
state. Desktop keeps the existing hover crossfade via @media (hover:
hover). Dots use size differentiation (WCAG 2.2 AA compliant) with
outline rings for contrast on any background.
Also fixes: no-image placeholder (SVG icon instead of broken img),
unnecessary wrapper div for single-image cards, and dev static asset
caching (was immutable for all envs, now only prod).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add priority attr to product_card, thread through to responsive_image
- First 2 featured products get fetchpriority="high" and eager loading
- Remove longPollFallbackMs to avoid unnecessary fallback attempt
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>