From f5f6374f7b94082bbcefac7fe86afc38dfebe42b Mon Sep 17 00:00:00 2001 From: jamey Date: Tue, 17 Feb 2026 19:07:15 +0000 Subject: [PATCH] replace Tailwind in content + collection, remove shop Tailwind entirely (Phase 5c) - Replace all Tailwind utilities in content.ex and collection.ex with semantic CSS classes (content body, contact form, cards, reviews, etc.) - Delete app-shop.css (Tailwind shop entry point) - Remove shop Tailwind config from config.exs, dev.exs, mix.exs - Remove shop Tailwind stylesheet link from shop_root.html.heex - Add collection filter bar, empty state, and select dropdown styles - Fix filter pill sizing (use theme font vars instead of hardcoded rem) - Fix active pill contrast (tinted accent background + dark accent text) - Fix --t-text-on-accent fallback for pill legibility - Add padding/font-size to .themed-select Shop pages now use zero Tailwind. Admin Tailwind remains for Phase 6. Co-Authored-By: Claude Opus 4.6 --- PROGRESS.md | 2 +- assets/css/app-shop.css | 59 --- assets/css/shop.css | 14 +- assets/css/shop/components.css | 387 +++++++++++++++++- assets/css/theme-layer2-attributes.css | 6 +- assets/css/theme-semantic.css | 26 +- config/config.exs | 7 - config/dev.exs | 3 +- lib/mix/tasks/screenshots.ex | 1 - .../components/layouts/shop_root.html.heex | 1 - .../components/shop_components/content.ex | 301 ++++++-------- .../live/shop/collection.ex | 30 +- mix.exs | 2 - 13 files changed, 530 insertions(+), 309 deletions(-) delete mode 100644 assets/css/app-shop.css diff --git a/PROGRESS.md b/PROGRESS.md index 405e1fc..1cb6e8c 100644 --- a/PROGRESS.md +++ b/PROGRESS.md @@ -66,7 +66,7 @@ Plans: [admin-redesign.md](docs/plans/admin-redesign.md) | [setup-wizard.md](doc | ~~34~~ | ~~Phase 2: Extract product inline styles~~ | 33 | 3h | done | | ~~35~~ | ~~Phase 3: Extract layout + cart inline styles~~ | 33 | 3h | done | | ~~36~~ | ~~Phase 4: Extract content + template inline styles~~ | 33 | 2.5h | done | -| 37 | Phase 5: Remove Tailwind from shop | 34-36 | 3h | | +| ~~37~~ | ~~Phase 5: Remove Tailwind from shop pages~~ | 34-36 | 3h | done | | 38 | Phase 6: Replace DaisyUI (admin) | 37 | 3h | | | 39 | Phase 7: Remove Tailwind entirely | 38 | 1.5h | | | 40 | Phase 8: Optimisation + modern enhancements | 39 | 2.5h | | diff --git a/assets/css/app-shop.css b/assets/css/app-shop.css deleted file mode 100644 index 7fa646c..0000000 --- a/assets/css/app-shop.css +++ /dev/null @@ -1,59 +0,0 @@ -/* Shop CSS - Tailwind without daisyUI - This is the CSS bundle for public shop pages (localhost:4001). - It excludes daisyUI which is only needed for admin pages. - See app.css for the full admin version. */ - -@import "tailwindcss" source(none); -@source "../css"; -@source "../js"; -/* Only scan shop-specific files, not admin pages */ -@source "../../lib/simpleshop_theme_web/live/shop"; -@source "../../lib/simpleshop_theme_web/components/shop_components.ex"; -@source "../../lib/simpleshop_theme_web/components/shop_components"; -@source "../../lib/simpleshop_theme_web/components/page_templates"; -@source "../../lib/simpleshop_theme_web/components/layouts/shop.html.heex"; -@source "../../lib/simpleshop_theme_web/components/layouts/shop_root.html.heex"; - -/* Heroicons plugin */ -@plugin "../vendor/heroicons"; - -/* NO daisyUI - shop pages use the custom .themed system instead */ - -/* Add variants based on LiveView classes */ -@custom-variant phx-click-loading (.phx-click-loading&, .phx-click-loading &); -@custom-variant phx-submit-loading (.phx-submit-loading&, .phx-submit-loading &); -@custom-variant phx-change-loading (.phx-change-loading&, .phx-change-loading &); - -/* Make LiveView wrapper divs transparent for layout */ -[data-phx-session], [data-phx-teleported-src] { display: contents } - -/* Theme CSS - Layer 1: Primitives (fixed CSS variables) */ -@import "./theme-primitives.css"; - -/* Theme CSS - Layer 2: Shared styles only (.themed selectors) - Note: .preview-frame rules are still included but unused on shop pages. - This is acceptable as it's only ~5KB and splitting adds complexity. */ -@import "./theme-layer2-attributes.css"; - -/* Theme CSS - Layer 3: Semantic aliases */ -@import "./theme-semantic.css"; - -/* Cart drawer open state styles */ -.cart-drawer.open { - right: 0 !important; -} - -.cart-drawer-overlay.open { - opacity: 1 !important; - visibility: visible !important; -} - -/* Product gallery thumbnail styles */ -.pdp-thumbnail { - border: 2px solid var(--t-border-default); - transition: border-color 0.15s ease; -} - -.pdp-thumbnail-active { - border-color: hsl(var(--t-accent-h) var(--t-accent-s) var(--t-accent-l)); -} diff --git a/assets/css/shop.css b/assets/css/shop.css index f254cb5..c7e98b7 100644 --- a/assets/css/shop.css +++ b/assets/css/shop.css @@ -1,16 +1,16 @@ /* Shop CSS — hand-written, zero-framework stylesheet. - Layered cascade: later layers beat earlier ones, no !important needed. - - This file runs alongside app-shop.css during migration (Phases 1-4). - After Phase 5 it replaces app-shop.css entirely. */ + Layered cascade: later layers beat earlier ones, no !important needed. */ @layer reset, primitives, tokens, components, layout, utilities, overrides; @import "./shop/reset.css"; -/* Theme CSS stays in the existing files (loaded via app-shop.css). - Primitives and tokens will be wrapped in @layer when - app-shop.css is removed in Phase 5. */ +/* Theme CSS — unlayered so it overrides component layers (intentional). + Primitives set CSS custom properties, layer2 sets theme-aware rules, + semantic sets base styles on .themed containers. */ +@import "./theme-primitives.css"; +@import "./theme-layer2-attributes.css"; +@import "./theme-semantic.css"; @import "./shop/components.css"; @import "./shop/layout.css"; diff --git a/assets/css/shop/components.css b/assets/css/shop/components.css index 3360a7d..ec40b54 100644 --- a/assets/css/shop/components.css +++ b/assets/css/shop/components.css @@ -293,7 +293,7 @@ .category-nav { display: grid; - grid-template-columns: repeat(3, 1fr); + grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 1rem; max-width: 48rem; margin-inline: auto; @@ -317,7 +317,8 @@ .category-image { width: 6rem; - height: 6rem; + max-width: 100%; + aspect-ratio: 1; border-radius: 9999px; background-color: #e5e7eb; background-size: cover; @@ -435,7 +436,7 @@ flex-wrap: wrap; align-items: center; justify-content: space-between; - gap: 1rem; + gap: 0.75rem; margin-bottom: 1.5rem; } @@ -445,6 +446,21 @@ overflow-x: auto; } + /* ── Collection empty state ── */ + + .collection-empty { + text-align: center; + padding-block: 4rem; + color: var(--t-text-secondary); + } + + .collection-empty-link { + display: inline-block; + margin-top: 1rem; + color: var(--t-text-accent, hsl(var(--t-accent-h) var(--t-accent-s) var(--t-accent-l))); + text-decoration: underline; + } + /* ── Breadcrumb ── */ .breadcrumb { @@ -501,6 +517,10 @@ object-fit: cover; } + .pdp-thumbnail-active { + border: 2px solid hsl(var(--t-accent-h) var(--t-accent-s) var(--t-accent-l)); + } + /* ── Variant selector ── */ .variant-selector { @@ -827,6 +847,7 @@ justify-content: center; position: relative; color: var(--t-text-secondary); + text-decoration: none; border-radius: var(--t-radius-button); transition: all 0.2s ease; @@ -1124,6 +1145,7 @@ .footer-link { color: var(--t-text-secondary); + text-decoration: none; cursor: pointer; transition: opacity 0.15s ease; @@ -1158,6 +1180,11 @@ opacity: 0; visibility: hidden; transition: opacity 0.3s ease, visibility 0.3s ease; + + &.open { + opacity: 1; + visibility: visible; + } } .cart-drawer { @@ -1174,6 +1201,10 @@ flex-direction: column; transition: right 0.3s ease; box-shadow: -4px 0 20px rgba(0, 0, 0, 0.15); + + &.open { + right: 0; + } } .cart-drawer-header { @@ -1265,6 +1296,7 @@ .cart-item-image { display: block; + text-decoration: none; border-radius: var(--t-radius-card); background-size: cover; background-position: center; @@ -1589,6 +1621,12 @@ margin-bottom: var(--space-lg); border-radius: var(--t-radius-image); overflow: hidden; + + & img { + width: 100%; + height: 300px; + object-fit: cover; + } } .content-text { @@ -1601,14 +1639,56 @@ /* ── Contact form ── */ + .contact-form-card { + padding: 2rem; + } + + .contact-form-heading { + font-family: var(--t-font-heading); + font-weight: 700; + font-size: var(--t-text-xl); + color: var(--t-text-primary); + margin-bottom: 0.5rem; + } + .contact-form-meta { + display: flex; + flex-direction: column; + gap: 0.25rem; + margin-bottom: 1.5rem; + font-size: var(--t-text-small); color: var(--t-text-secondary); } + .contact-form-spacer { + margin-bottom: 1rem; + } + + .contact-form { + display: flex; + flex-direction: column; + gap: 1rem; + } + .contact-form-label { + display: block; + font-weight: 500; + margin-bottom: 0.5rem; color: var(--t-text-primary); } + .contact-form .shop-input, + .contact-form .shop-textarea { + width: 100%; + padding: 0.5rem 1rem; + } + + .contact-form-submit { + width: 100%; + padding: 0.75rem 1.5rem; + font-weight: 600; + } + /* ── Accent email link ── */ .accent-email { @@ -1617,20 +1697,61 @@ /* ── Card shared styles (info, tracking, newsletter, social cards) ── */ + .card-section { + padding: 1.5rem; + } + .card-heading { + font-weight: 700; + margin-bottom: 0.75rem; color: var(--t-text-primary); } .card-text { + font-size: var(--t-text-small); color: var(--t-text-secondary); } + .card-text--spaced { + margin-bottom: 1rem; + } + + .card-inline-form { + display: flex; + flex-wrap: wrap; + gap: 0.5rem; + + & .themed-input { + flex: 1; + min-width: 0; + padding: 0.5rem 0.75rem; + font-size: var(--t-text-small); + } + + & .themed-button { + padding: 0.5rem 1rem; + font-size: var(--t-text-small); + font-weight: 500; + white-space: nowrap; + } + } + /* ── Info card ── */ .info-card-list { + display: flex; + flex-direction: column; + gap: 0.5rem; + font-size: var(--t-text-small); color: var(--t-text-secondary); } + .info-card-item { + display: flex; + align-items: flex-start; + gap: 0.5rem; + } + .info-card-bullet { color: var(--t-text-tertiary); } @@ -1642,52 +1763,150 @@ /* ── Contact info card ── */ .contact-info-email { + display: flex; + align-items: center; + gap: 0.5rem; + margin-bottom: 0.5rem; color: hsl(var(--t-accent-h) var(--t-accent-s) var(--t-accent-l)); text-decoration: none; + + & svg { + width: 1rem; + height: 1rem; + } } - /* ── Email input min-width ── */ + /* ── Newsletter card ── */ - .email-input { - min-width: 150px; + .newsletter-heading { + font-family: var(--t-font-heading); + font-weight: 700; + font-size: var(--t-text-xl); + color: var(--t-text-primary); + margin-bottom: 0.5rem; } /* ── Social links card ── */ + .social-link-card-list { + display: flex; + flex-wrap: wrap; + gap: 0.5rem; + } + .social-link-card-item { + display: flex; + align-items: center; + gap: 0.5rem; + padding: 0.5rem 0.75rem; + font-size: var(--t-text-small); text-decoration: none; + transition: opacity 0.15s ease; + + &:hover { + opacity: 0.8; + } } .social-link-card-icon { color: var(--t-text-secondary); + + & svg { + width: 1.25rem; + height: 1.25rem; + } } /* ── Social links (footer) ── */ + .social-links { + display: flex; + gap: 1rem; + justify-content: center; + } + .social-link { + width: 2.25rem; + height: 2.25rem; + display: flex; + align-items: center; + justify-content: center; + text-decoration: none; + transition: opacity 0.15s ease; color: var(--t-text-secondary); border-radius: var(--t-radius-button); + + & svg { + width: 1.25rem; + height: 1.25rem; + } + } + + /* ── Star rating ── */ + + .star-rating { + display: flex; + gap: 0.125rem; + + & svg { + width: 1rem; + height: 1rem; + } + + &[data-size="md"] svg { + width: 1.25rem; + height: 1.25rem; + } } /* ── Trust badges ── */ .trust-badges { + display: flex; + flex-direction: column; + gap: 0.75rem; + padding: 1rem; background-color: var(--t-surface-sunken); border-radius: var(--t-radius-card); } + .trust-badge-item { + display: flex; + align-items: flex-start; + gap: 0.75rem; + } + .trust-badge-icon { + flex-shrink: 0; + margin-top: 0.125rem; color: hsl(var(--t-accent-h) var(--t-accent-s) var(--t-accent-l)); + + & svg { + width: 1.25rem; + height: 1.25rem; + } } .trust-badge-title { + font-weight: 600; color: var(--t-text-primary); } .trust-badge-text { + font-size: var(--t-text-small); color: var(--t-text-secondary); } + /* ── Page title ── */ + + .page-title { + font-family: var(--t-font-heading); + font-weight: var(--t-heading-weight); + font-size: var(--t-heading-lg); + color: var(--t-text-primary); + margin-bottom: 2rem; + } + /* ── Reviews section ── */ .pdp-reviews { @@ -1695,37 +1914,121 @@ } .reviews-summary { + display: flex; + justify-content: space-between; + align-items: center; + padding-block: 1.5rem; + cursor: pointer; + list-style: none; + color: var(--t-text-primary); + + &::-webkit-details-marker { + display: none; + } + } + + .reviews-header-left { + display: flex; + flex-direction: column; + gap: 0.5rem; + } + + .reviews-heading { + font-family: var(--t-font-heading); + font-weight: 700; + font-size: var(--t-text-2xl); color: var(--t-text-primary); } + .reviews-rating-group { + display: flex; + align-items: center; + gap: 0.5rem; + } + .reviews-count { + font-size: var(--t-text-small); color: var(--t-text-secondary); } + .reviews-chevron { + width: 1.25rem; + height: 1.25rem; + flex-shrink: 0; + transition: transform 0.2s ease; + } + + details[open] > .reviews-summary .reviews-chevron { + transform: rotate(180deg); + } + + .reviews-body { + padding-bottom: 2rem; + } + + .reviews-list { + display: flex; + flex-direction: column; + gap: 1.5rem; + } + + .reviews-load-more { + display: block; + margin-top: 1.5rem; + margin-inline: auto; + padding: 0.5rem 1.5rem; + font-size: var(--t-text-small); + font-weight: 500; + } + /* ── Review card ── */ .review-card { + padding-bottom: 1.5rem; border-bottom: 1px solid var(--t-border-subtle); } + .review-header { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 0.5rem; + } + .review-date { + font-size: var(--t-text-caption); color: var(--t-text-tertiary); } .review-title { + font-weight: 600; + margin-bottom: 0.25rem; color: var(--t-text-primary); } .review-body { + font-size: var(--t-text-small); + margin-bottom: 0.75rem; color: var(--t-text-secondary); line-height: 1.6; } + .review-footer { + display: flex; + align-items: center; + gap: 0.5rem; + } + .review-author { + font-size: var(--t-text-small); + font-weight: 500; color: var(--t-text-primary); } .review-verified { + font-size: var(--t-text-caption); + padding: 0.125rem 0.5rem; + border-radius: var(--t-radius-sm, 4px); background-color: var(--t-surface-sunken); color: var(--t-text-tertiary); } @@ -1737,10 +2040,13 @@ } .rich-text-lead { + font-size: var(--t-text-large); + margin-bottom: 1rem; color: var(--t-text-primary); } .rich-text-paragraph { + margin-bottom: 1rem; color: var(--t-text-secondary); } @@ -1749,17 +2055,54 @@ font-weight: var(--t-heading-weight); font-size: var(--t-text-xl); color: var(--t-text-primary); + margin-top: 2rem; + margin-bottom: 0.75rem; + } + + .rich-text-closing { + margin-top: 2rem; + color: var(--t-text-secondary); } .rich-text-list { + margin-bottom: 1rem; + margin-left: 1.5rem; + list-style: disc; color: var(--t-text-secondary); + + & li { + margin-bottom: 0.25rem; + } } /* ── Flash messages ── */ + .shop-flash-group { + position: fixed; + top: 1rem; + right: 1rem; + z-index: 200; + display: flex; + flex-direction: column; + gap: 0.5rem; + } + .shop-flash { + display: flex; + align-items: center; + gap: 0.75rem; + padding: 0.75rem 1rem; + border-radius: var(--t-radius-card); + box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1); + max-width: 24rem; + animation: flash-in 0.3s ease-out; background-color: var(--t-surface-raised, #fff); color: var(--t-text-primary); + + & p { + font-size: var(--t-text-small); + margin: 0; + } } .shop-flash--info { @@ -1770,6 +2113,12 @@ border: 1px solid hsl(0 70% 50% / 0.3); } + .shop-flash-icon { + flex-shrink: 0; + width: 1.25rem; + height: 1.25rem; + } + .shop-flash-icon--info { color: var(--t-accent); } @@ -1778,6 +2127,16 @@ color: hsl(0 70% 50%); } + @keyframes flash-in { + from { opacity: 0; transform: translateX(1rem); } + to { opacity: 1; transform: translateX(0); } + } + + /* Transition classes for JS.hide flash dismiss */ + .fade-out { transition: opacity 200ms ease-out; } + .fade-out-from { opacity: 1; } + .fade-out-to { opacity: 0; } + /* ── Link buttons (make links styled as buttons) ── */ .themed-button:where(a), @@ -2067,20 +2426,6 @@ margin-inline: auto; } - /* ── Screen reader only ── */ - - .sr-only { - position: absolute; - width: 1px; - height: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - clip: rect(0, 0, 0, 0); - white-space: nowrap; - border-width: 0; - } - /* ── Responsive breakpoints ── */ @media (min-width: 640px) { @@ -2093,9 +2438,11 @@ grid-template-columns: repeat(2, 1fr); } .hero-cta-group { flex-direction: row; } + .reviews-header-left { flex-direction: row; align-items: center; gap: 1rem; } } @media (min-width: 768px) { + .page-title { font-size: var(--t-heading-xl); } .shop-container[data-bottom-nav] { padding-bottom: 0; } .shop-header { padding: 1rem 2rem; } .shop-nav { display: flex; gap: 1.5rem; } diff --git a/assets/css/theme-layer2-attributes.css b/assets/css/theme-layer2-attributes.css index 9a59495..bff30c7 100644 --- a/assets/css/theme-layer2-attributes.css +++ b/assets/css/theme-layer2-attributes.css @@ -263,6 +263,9 @@ color: var(--t-text-primary); border: 1px solid var(--t-border-default); border-radius: var(--t-radius-input); + padding: 0.375rem 0.75rem; + font-size: var(--t-text-small); + font-family: var(--t-font-body); &:focus { outline: none; @@ -293,8 +296,7 @@ } } -/* Shop nav display - hidden on mobile, flex on md+ (via Tailwind classes in component) */ -/* Note: Removed explicit display:flex here as it overrides Tailwind's hidden class */ +/* Shop nav display - handled by components.css (hidden on mobile, flex on md+) */ /* ============================================= STANDALONE COMPONENTS (Context-independent) diff --git a/assets/css/theme-semantic.css b/assets/css/theme-semantic.css index 8762e43..124a17a 100644 --- a/assets/css/theme-semantic.css +++ b/assets/css/theme-semantic.css @@ -210,23 +210,30 @@ .collection-filter-pills { display: flex; flex-wrap: wrap; - gap: 0.375rem; + gap: 0.5rem; } .collection-filter-pill { display: inline-block; padding: 0.375rem 0.75rem; border-radius: 9999px; - font-size: 0.75rem; + font-size: var(--t-text-small); white-space: nowrap; + text-decoration: none; transition: opacity 0.15s; background-color: var(--t-surface-raised); color: var(--t-text-primary); + border: 1px solid var(--t-border-default); + + &:hover:not(.active) { + opacity: 0.8; + } &.active { - background-color: var(--t-accent); - color: var(--t-text-on-accent); - font-weight: 500; + background-color: hsl(var(--t-accent-h) var(--t-accent-s) var(--t-accent-l) / 0.12); + color: hsl(var(--t-accent-h) var(--t-accent-s) calc(var(--t-accent-l) - 15%)); + border-color: hsl(var(--t-accent-h) var(--t-accent-s) var(--t-accent-l) / 0.25); + font-weight: 600; } } @@ -248,15 +255,6 @@ } @media (min-width: 640px) { - .collection-filter-pills { - gap: 0.5rem; - } - - .collection-filter-pill { - padding: 0.5rem 1rem; - font-size: 0.875rem; - } - /* Desktop always wraps — no scroll needed */ .collection-filters.is-scrollable { overflow-x: visible; diff --git a/config/config.exs b/config/config.exs index ee0c66f..6b9b752 100644 --- a/config/config.exs +++ b/config/config.exs @@ -68,13 +68,6 @@ config :tailwind, --output=priv/static/assets/css/app.css ), cd: Path.expand("..", __DIR__) - ], - simpleshop_theme_shop: [ - args: ~w( - --input=assets/css/app-shop.css - --output=priv/static/assets/css/app-shop.css - ), - cd: Path.expand("..", __DIR__) ] # Configures Elixir's Logger diff --git a/config/dev.exs b/config/dev.exs index 675af24..e4967ec 100644 --- a/config/dev.exs +++ b/config/dev.exs @@ -27,8 +27,7 @@ config :simpleshop_theme, SimpleshopThemeWeb.Endpoint, esbuild: {Esbuild, :install_and_run, [:simpleshop_theme, ~w(--sourcemap=inline --watch)]}, esbuild_shop_css: {Esbuild, :install_and_run, [:simpleshop_theme_shop_css, ~w(--sourcemap=inline --watch)]}, - tailwind: {Tailwind, :install_and_run, [:simpleshop_theme, ~w(--watch)]}, - tailwind_shop: {Tailwind, :install_and_run, [:simpleshop_theme_shop, ~w(--watch)]} + tailwind: {Tailwind, :install_and_run, [:simpleshop_theme, ~w(--watch)]} ] # ## SSL Support diff --git a/lib/mix/tasks/screenshots.ex b/lib/mix/tasks/screenshots.ex index d5494dd..777e311 100644 --- a/lib/mix/tasks/screenshots.ex +++ b/lib/mix/tasks/screenshots.ex @@ -159,7 +159,6 @@ defmodule Mix.Tasks.Screenshots do Mix.shell().info("Building production assets...") Mix.Task.run("tailwind", ["simpleshop_theme", "--minify"]) - Mix.Task.run("tailwind", ["simpleshop_theme_shop", "--minify"]) Mix.Task.run("esbuild", ["simpleshop_theme", "--minify"]) Mix.Task.run("esbuild", ["simpleshop_theme_shop_css", "--minify"]) Mix.Task.run("phx.digest") diff --git a/lib/simpleshop_theme_web/components/layouts/shop_root.html.heex b/lib/simpleshop_theme_web/components/layouts/shop_root.html.heex index 7ba53e6..d0c0571 100644 --- a/lib/simpleshop_theme_web/components/layouts/shop_root.html.heex +++ b/lib/simpleshop_theme_web/components/layouts/shop_root.html.heex @@ -23,7 +23,6 @@ - diff --git a/lib/simpleshop_theme_web/components/shop_components/content.ex b/lib/simpleshop_theme_web/components/shop_components/content.ex index 5d36f99..d21013c 100644 --- a/lib/simpleshop_theme_web/components/shop_components/content.ex +++ b/lib/simpleshop_theme_web/components/shop_components/content.ex @@ -46,7 +46,7 @@ defmodule SimpleshopThemeWeb.ShopComponents.Content do source_width={1200} alt={@image_alt} sizes="(max-width: 800px) 100vw, 800px" - class="w-full h-[300px] object-cover" + class="content-hero-image" /> <% end %> @@ -78,19 +78,16 @@ defmodule SimpleshopThemeWeb.ShopComponents.Content do def contact_form(assigns) do ~H""" - <.shop_card class="p-8"> -

+ <.shop_card class="contact-form-card"> +

{@title}

<%= if @email || @response_time do %> -
+
<%= if @email do %>

Email me: - + {@email}

@@ -100,39 +97,31 @@ defmodule SimpleshopThemeWeb.ShopComponents.Content do <% end %>
<% else %> -
+
<% end %> -
+
- - <.shop_input type="text" placeholder="Your name" class="w-full px-4 py-2" /> + + <.shop_input type="text" placeholder="Your name" />
- - <.shop_input type="email" placeholder="your@email.com" class="w-full px-4 py-2" /> + + <.shop_input type="email" placeholder="your@email.com" />
- - <.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?" />
- - <.shop_textarea rows="5" placeholder="Your message..." class="w-full px-4 py-2" /> + + <.shop_textarea rows="5" placeholder="Your message..." />
- <.shop_button type="submit" class="w-full px-6 py-3 font-semibold transition-all"> + <.shop_button type="submit" class="contact-form-submit"> Send Message
@@ -149,20 +138,14 @@ defmodule SimpleshopThemeWeb.ShopComponents.Content do """ def order_tracking_card(assigns) do ~H""" - <.shop_card class="p-6"> -

Track your order

-

+ <.shop_card class="card-section"> +

Track your order

+

Enter your email and I'll send you a link to check your order status.

-
- <.shop_input - type="email" - placeholder="your@email.com" - class="email-input flex-1 min-w-0 px-3 py-2 text-sm" - /> - <.shop_button class="px-4 py-2 text-sm font-medium whitespace-nowrap"> - Send - +
+ <.shop_input type="email" placeholder="your@email.com" class="email-input" /> + <.shop_button>Send
""" @@ -188,11 +171,11 @@ defmodule SimpleshopThemeWeb.ShopComponents.Content do def info_card(assigns) do ~H""" - <.shop_card class="p-6"> -

{@title}

-