Split the editor sheet into two distinct elements:
- .editor-fab: floating action button, always a pill in the corner
- .editor-panel: sliding panel that animates in/out independently
This enables proper CSS keyframe animations (slide-up/down on mobile,
slide-in/out on desktop) with a closing class for exit transitions.
Simplified the JS hook to only handle close behaviour.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- collapsed state: floating pill button in bottom-right corner
- removed panel background when collapsed (transparent)
- violet accent colour to distinguish from shop theme
- white glow outline for visibility on any background
- consistent behaviour on mobile and desktop
- opens to bottom sheet (mobile) or side panel (desktop)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- semantic HTML: step numbers inside h2, strong provider names, details
for adapter configs, strong error messages, fieldset drawer toggle hidden
- inline field errors via flash for no-JS controller fallback
- single form POST button for test email (works with and without JS)
- admin sidebar: remove brand/view-shop, move user email to footer nav
- replace inline style with .admin-setup-step-spaced class
- clean up unused CSS (.admin-brand, .admin-sidebar-header, etc.)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Render all adapter field sections in the form with CSS :has(:checked)
controlling visibility. Selecting a provider instantly shows its config
fields — no JS, no page reload, no server round-trip needed.
- Render all 6 adapter configs with data-adapter attribute
- CSS :has(:checked) show/hide rules per adapter in admin stylesheet
- Namespace field names per adapter (email[brevo][api_key] etc)
- Drop 4 transactional-only providers (Resend, Postmark, Mailgun, MailPace)
- Remove noscript "Switch provider" button and controller redirect workaround
- Remove configured_adapter hidden input tracking
- Hide JS-only test email button for no-JS users via noscript style
- LiveView progressively enhances with async save and test email
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
show all 10 providers in three groups (popular, transactional,
advanced) with category headings. fix phx-change clobbering text
fields, async test email sending state, integer parse crash on
bad port. add keyboard focus on card radios, fieldset legend,
WCAG-compliant badge contrast, responsive grid. extract shared
save_config into Mailer, add no-JS controller fallback with
configured_adapter hidden field for adapter change detection.
remove CardRadioScroll JS hook (no longer needed).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
grouped providers by category, added per-provider key validation
with cross-provider detection, friendly delivery error messages,
retryable vs config error distinction, from-address in general
settings, and "Save settings" button to match admin conventions
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Disable checkout when Stripe isn't connected (cart drawer, cart page,
and early guard in checkout controller to prevent orphaned orders).
Show amber warning on order detail when email isn't configured.
Fix pre-existing missing vertical spacing between page blocks.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add KeyValidation module for format-checking API keys before
attempting connections. Auto-strips whitespace, detects common
mistakes (e.g. pasting a Stripe publishable key), and returns
helpful error messages.
Inline field errors across all three entry points:
- Setup wizard: provider + Stripe keys
- Admin provider form: simplified to single Connect button
- Email settings: per-field errors instead of flash toasts
Also: plain text inputs for all API keys (not password fields),
accessible error states (aria-invalid, role=alert, thick border,
bold text), inner_block slot declaration on error component.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New external_link component in core_components handles target="_blank",
rel="noopener noreferrer", external-link icon, and sr-only "(opens in
new tab)" text. Migrated admin providers form, settings (Stripe),
order tracking, onboarding setup links to use it. Fixed rel="noopener"
to "noopener noreferrer" on remaining links (email settings, product
show, core_components card radio). Added sr-only text to shop social
link cards and aria-label to page renderer tracking link.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New --t-border-input token per mood, all 3:1+ contrast against their
surface backgrounds (neutral #8c8c8c, warm #8a827a, cool #7a8591,
dark #707070). Used on admin inputs/selects/textareas and shop
themed-input/themed-select, with graceful fallback to --t-border-default.
Decorative borders on cards, dividers, panels are unchanged.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add AnalyticsHook to the coming_soon live session — the shop layout
fires an analytics:screen JS event but the session had no handler,
crashing the page on connect.
Centre the logo image (display:block from CSS reset needs
margin-inline:auto). Add a subtle "Admin" link at the bottom using
flex flow rather than fixed/absolute positioning so it works in
iframes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Wrap logo mode radios in fieldset/legend for screen reader grouping.
Hide native radio input properly (was using nonexistent .hidden class),
add aria-hidden on decorative dot spans, focus-visible ring on cards,
and IDs on each input.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- add password field and required shop name to setup wizard
- extract SetupHook for DRY redirect to /setup when no admin exists
- add ?from=checklist param to checklist hrefs with contextual banner on
email settings and theme pages for easy return to dashboard
- remove email warning banner from admin layout (checklist covers it)
- make email a required checklist item (no longer optional)
- add DevReset module for wiping dev data without restart
- rename "Theme Studio" to "Theme", drop subtitle
- lower theme editor side-by-side breakpoint from 64em to 48em
- clean up login/registration pages (remove dead registration_open code)
- fix settings.put_secret to invalidate cache after write
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
site_name and site_description are shop identity, not theme concerns.
They now live in the Settings table as first-class settings with their
own assigns (@site_name, @site_description) piped through hooks and
plugs. The setup wizard writes site_name on account creation, and the
theme editor reads/writes via Settings.put_setting. Removed the
"configure your shop" checklist item since currency/country aren't
built yet. Also adds shop name field to setup wizard step 1.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix resolve_content_image returning base path (not full URL) so
responsive_image doesn't double-append width/extension
- Remove legacy image fields (image_src, image_alt, image_url) from
block settings schemas
- Remove demo/mockup fallbacks from renderer and defaults — blank
fields stay blank instead of showing preview content
- Replace demo text in defaults with instructional placeholders that
guide new shop owners
- Remove redundant X button from editor sidebar, add unsaved-changes
confirmation to Done button
- Fix block card name overflow on mobile (display: block, flex-wrap)
- Add onboarding UX improvement plan (10 tasks)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Badge inside admin-btn-primary was inheriting white text colour
with a light grey background — unreadable. Now uses inverted
colours (accent text on near-white bg) for WCAG AA+ compliance.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
More prominent placement just below the header, removed from footer.
Footer now only has dev tools disclosure and log out.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
LiveDashboard, Errors, and Jobs are now behind a "Developer tools"
toggle, keeping View shop and Log out as the prominent footer links.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Cron-scheduled workers (retention, dead link checker, pruners) were
enqueued to the default queue which wasn't configured — they never ran.
Also add overflow-y scroll and sticky positioning to admin sidebar.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Bump oban to 2.19+, add oban_web for real-time job monitoring.
Mounted behind admin auth with sidebar link under "Jobs".
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace BEM-style &--modifier nesting (unsupported in native CSS) with
&.class-modifier in shop/components.css and page_renderer.ex. Fix
Elixir 1.19 type warnings comparing lists with != [].
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The shop header preview's absolute-positioned overlay escaped the
preview frame and covered the sidebar controls on small viewports.
Adding position: relative to .theme-preview-frame contains it.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move the 3 theme layer imports (primitives, layer2-attributes, semantic)
out of admin.css and shop.css into a new theme.css bundle loaded by all
root layouts. Eliminates 28 KB of duplication on admin pages where both
admin.css and shop.css were each embedding the same theme CSS.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Delete utilities.css (701 lines / 24 KB of Tailwind utility clones)
- Add layout.css with admin-stack, admin-row, admin-cluster, admin-grid
primitives and gap variants (sm, md, lg, xl)
- Add transitions.css import and layout.css import to admin.css entry point
- Replace all Tailwind utility classes across 26 admin templates with
semantic admin-*/theme-*/page-specific CSS classes
- Replace all non-dynamic inline styles with semantic classes
- Add ~100 new semantic classes to components.css (analytics, dashboard,
order detail, settings, theme editor, generic utilities)
- Fix stray text-error → admin-text-error in media.ex
- Add missing .truncate definition to admin CSS
- Only remaining inline styles are dynamic data values (progress bars,
chart dimensions) and one JS.toggle target
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Five missing line-height values caused pixel shifts when Tailwind
utilities (text-sm, text-lg, text-xs) were replaced with semantic
classes that only set font-size. Also remove phantom padding-bottom
on .admin-header (the old pb-4 utility was never defined).
Fixes: .admin-header, .admin-header-subtitle, .admin-error,
.admin-brand, .admin-text-secondary
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace Tailwind utility soup across admin templates with semantic
CSS classes. Add layout primitives (stack, row, cluster, grid),
extract JS transition helpers into transitions.css, and refactor
core_components, layouts, settings, newsletter, order_show, providers,
and theme editor templates.
Utility occurrences reduced from 290+ to 127 across admin files.
All 1679 tests pass.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Single activity_log table powering two views: chronological timeline
on each order detail page (replacing the old fulfilment card) and a
global feed at /admin/activity with tabs, category filters, search,
and pagination. Real-time via PubSub — new entries appear instantly,
nav badge updates across all admin pages.
Instrumented across all event points: Stripe webhooks, order notifier,
submission worker, fulfilment status worker, product sync worker, and
Oban exhausted-job telemetry. Contextual action buttons (retry
submission, retry sync, dismiss) with Oban unique constraints to
prevent double-enqueue. 90-day pruning via cron.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
URL-based offset pagination with ?page=N for bookmarkable pages.
Admin views use push_patch, shop collection uses navigate links.
Responsive on mobile with horizontal-scroll tables and stacking
pagination controls. Includes dev seed script for testing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Subscribers with double opt-in confirmation, campaign composer with
draft/scheduled/sent lifecycle, admin dashboard with overview stats,
CSV export, and shop signup form wired into page builder blocks.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Block cards now show a one-line content summary below the name.
Block picker items include SVG wireframe thumbnails. Newsletter
block marked as decorative with configurable title/description
and form submission prevented on the shop side.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- sidebar nav grouped under Shop/Content/Settings section headers with
subtle uppercase labels (#105)
- custom page settings now show inline in a collapsible panel within the
editor instead of navigating away to a separate page (#107)
- admin editor preview loads real products and categories from the DB,
falling back to PreviewData only on fresh installs (#108)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- rename "Providers" to "Print providers" in sidebar (#110)
- add LiveView navigation guard to EditorKeyboard hook — intercepts
link clicks in capture phase when editor has unsaved changes (#103)
- add description field to all 26 block types, shown as subtitle in
block picker; filter searches descriptions too (#104)
- add visible column headers (Label / Path) and proper sr-only labels
with for attributes on nav editor inputs (#106)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Legal pages (privacy, delivery, terms) now auto-populate content from
shop settings on mount, show auto-generated vs customised badges, and
have a regenerate button. Theme editor gains alt text fields for logo,
header, and icon images. Image picker in page builder now has an upload
button and alt text warning badges. Clearing unused image references
shows an orphan info flash.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New block types: spacer, divider, button/CTA, video embed (YouTube,
Vimeo with privacy-enhanced embeds, fallback for unknown URLs).
Page templates (blank, content, landing) shown when creating custom
pages. Duplicate page action on admin index with slug deduplication.
Fix block picker on shop edit sidebar being cut off on mobile by
accounting for bottom nav and making the grid scrollable.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Chrome's font boosting algorithm was applying different text size
multipliers across pages, making the announcement bar font size
inconsistent between home and collection views on mobile.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
History stacks (@history/@future) on both admin editor and live sidebar,
capped at 50 entries. All mutations routed through apply_mutation for
consistent history tracking. EditorKeyboard JS hook combines DirtyGuard
with Ctrl+Z/Ctrl+Shift+Z. Settings panel fade-in animation. 10 new tests.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace hardcoded header, footer and mobile nav with settings-driven
loops. Nav items stored as JSON via Settings, loaded in ThemeHook with
sensible defaults. New admin navigation editor at /admin/navigation
for add/remove/reorder/save/reset. Mobile bottom nav also driven from
header nav items with icon mapping by slug.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New settings form for creating and editing custom page metadata
(title, slug, meta description, published, nav settings). Pages
index shows custom pages section with draft badges and delete.
Editor shows settings button for custom pages, hides reset to
defaults. 20 new tests.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The error-main flex container was missing flex-direction: column,
which went unnoticed until the page builder added a second block
(featured_products) to the error page defaults.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Wire up image field in block settings with a modal picker that
browses the media library. Fix picker thumbnails collapsing to
14px by replacing overflow:hidden with overflow:clip on grid
items (hidden sets min-height:0 in grid context). Polish media
library mobile sheet with scrim overlay and tighter spacing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Admins can now edit pages directly on the live shop by clicking the
pencil icon in the header. A sidebar slides in with block management
controls (add, remove, reorder, edit settings, save, reset, done).
Key features:
- PageEditorHook on_mount with handle_params/event/info hooks
- BlockEditor pure functions extracted from admin editor
- Shared BlockEditorComponents with event_prefix namespacing
- Collapsible sidebar: X closes it, header pencil reopens it
- Backdrop overlay dismisses sidebar on tap
- Conditional admin.css loading for logged-in users
- content_body block now portable (textarea setting + rich text fallback)
13 integration tests, 26 unit tests, 1370 total passing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Introduces typed settings schema with SettingsField struct, replaces
the read-only JSON textarea with a full repeater UI for info_card items.
Supports add, remove, reorder and inline editing of repeater items.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Stage 6 of the page builder: admin UI at /admin/pages for managing
page layouts. Page list shows all 14 pages grouped by category.
Editor supports reorder (up/down), add, remove, duplicate, save,
and reset to defaults. DirtyGuard JS hook warns on unsaved changes.
ARIA live regions announce block operations for screen readers.
Also: regenerate admin icons (81 rules via mix task with @layer
wrapping), add gen_smtp dep for SMTP email adapter, add :key to
page renderer block loop for correct LiveView diffing.
1309 tests, 0 failures.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Home, Content (about/delivery/privacy/terms), Contact, and ErrorHTML
now render through the generic PageRenderer instead of hardcoded
templates. Block wrapper divs enable CSS grid targeting. Featured
products block supports layout/card_variant/columns settings for
different page contexts. Contact page uses CSS grid on data-block-type
attributes for two-column layout.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>