diff --git a/assets/css/theme-layer2-attributes.css b/assets/css/theme-layer2-attributes.css index da67fe2..2cf58d4 100644 --- a/assets/css/theme-layer2-attributes.css +++ b/assets/css/theme-layer2-attributes.css @@ -240,6 +240,57 @@ color: var(--t-text-inverse); } } + + /* Themed Form Controls */ + & .themed-input { + background-color: var(--t-surface-base); + color: var(--t-text-primary); + border: 1px solid var(--t-border-default); + border-radius: var(--t-radius-input); + + &:focus { + outline: none; + border-color: hsl(var(--t-accent-h) var(--t-accent-s) var(--t-accent-l)); + } + + &::placeholder { + color: var(--t-text-tertiary); + } + } + + & .themed-select { + background-color: var(--t-surface-raised); + color: var(--t-text-primary); + border: 1px solid var(--t-border-default); + border-radius: var(--t-radius-input); + + &:focus { + outline: none; + border-color: hsl(var(--t-accent-h) var(--t-accent-s) var(--t-accent-l)); + } + } + + & .themed-button { + background-color: hsl(var(--t-accent-h) var(--t-accent-s) var(--t-accent-l)); + color: var(--t-text-inverse); + border-radius: var(--t-radius-button); + border: none; + cursor: pointer; + } + + & .themed-button-outline { + background-color: transparent; + color: var(--t-text-primary); + border: 1px solid var(--t-border-default); + border-radius: var(--t-radius-button); + cursor: pointer; + } + + & .themed-card { + background-color: var(--t-surface-raised); + border: 1px solid var(--t-border-default); + border-radius: var(--t-radius-card); + } } /* Shop nav display - hidden on mobile, flex on md+ (via Tailwind classes in component) */ diff --git a/lib/simpleshop_theme_web/components/layouts.ex b/lib/simpleshop_theme_web/components/layouts.ex index 6a5dd0f..9359016 100644 --- a/lib/simpleshop_theme_web/components/layouts.ex +++ b/lib/simpleshop_theme_web/components/layouts.ex @@ -63,7 +63,7 @@ defmodule SimpleshopThemeWeb.Layouts do
-
+
{render_slot(@inner_block)}
diff --git a/lib/simpleshop_theme_web/components/page_templates/contact.html.heex b/lib/simpleshop_theme_web/components/page_templates/contact.html.heex index b465d0e..019cf50 100644 --- a/lib/simpleshop_theme_web/components/page_templates/contact.html.heex +++ b/lib/simpleshop_theme_web/components/page_templates/contact.html.heex @@ -17,7 +17,7 @@
<.contact_form email="hello@example.com" /> -
+
<.order_tracking_card /> <.info_card title="Handy to know" items={[ diff --git a/lib/simpleshop_theme_web/components/shop_components.ex b/lib/simpleshop_theme_web/components/shop_components.ex index 0a3e63e..80ad8bd 100644 --- a/lib/simpleshop_theme_web/components/shop_components.ex +++ b/lib/simpleshop_theme_web/components/shop_components.ex @@ -53,6 +53,246 @@ defmodule SimpleshopThemeWeb.ShopComponents do """ end + # ============================================================================= + # Themed Form Components + # ============================================================================= + # These components wrap common form elements with the themed CSS classes. + # They provide a consistent, theme-aware appearance across shop pages. + + @doc """ + Renders a themed text input. + + This component applies the `.themed-input` CSS class which inherits + colors, borders, and radii from the current theme's CSS variables. + + ## Attributes + + * `type` - Optional. Input type. Defaults to "text". + * `class` - Optional. Additional CSS classes. + * All other attributes are passed through to the input element. + + ## Examples + + <.shop_input type="email" placeholder="your@email.com" /> + <.shop_input type="text" name="name" class="flex-1" /> + """ + attr :type, :string, default: "text" + attr :class, :string, default: nil + attr :rest, :global, include: ~w(name value placeholder required disabled autocomplete readonly) + + def shop_input(assigns) do + ~H""" + + """ + end + + @doc """ + Renders a themed textarea. + + ## Attributes + + * `class` - Optional. Additional CSS classes. + * All other attributes are passed through to the textarea element. + + ## Examples + + <.shop_textarea placeholder="Your message..." rows="5" /> + """ + attr :class, :string, default: nil + attr :rest, :global, include: ~w(name rows placeholder required disabled readonly) + + def shop_textarea(assigns) do + ~H""" + + """ + end + + @doc """ + Renders a themed select dropdown. + + ## Attributes + + * `class` - Optional. Additional CSS classes. + * `options` - Required. List of options (strings or {value, label} tuples). + * `selected` - Optional. Currently selected value. + * All other attributes are passed through to the select element. + + ## Examples + + <.shop_select options={["Option 1", "Option 2"]} /> + <.shop_select options={[{"value", "Label"}]} selected="value" /> + """ + attr :class, :string, default: nil + attr :options, :list, required: true + attr :selected, :any, default: nil + attr :rest, :global, include: ~w(name required disabled aria-label) + + def shop_select(assigns) do + ~H""" + + """ + end + + @doc """ + Renders a themed primary button (accent color background). + + ## Attributes + + * `class` - Optional. Additional CSS classes. + * `type` - Optional. Button type. Defaults to "button". + * All other attributes are passed through to the button element. + + ## Slots + + * `inner_block` - Required. Button content. + + ## Examples + + <.shop_button>Send Message + <.shop_button type="submit" class="w-full">Subscribe + """ + attr :class, :string, default: nil + attr :type, :string, default: "button" + attr :rest, :global, include: ~w(disabled name value phx-click phx-value-page) + + slot :inner_block, required: true + + def shop_button(assigns) do + ~H""" + + """ + end + + @doc """ + Renders a themed outline/secondary button. + + ## Attributes + + * `class` - Optional. Additional CSS classes. + * `type` - Optional. Button type. Defaults to "button". + * All other attributes are passed through to the button element. + + ## Slots + + * `inner_block` - Required. Button content. + + ## Examples + + <.shop_button_outline>Continue Shopping + """ + attr :class, :string, default: nil + attr :type, :string, default: "button" + attr :rest, :global, include: ~w(disabled name value phx-click phx-value-page) + + slot :inner_block, required: true + + def shop_button_outline(assigns) do + ~H""" + + """ + end + + @doc """ + Renders a themed link styled as a primary button. + + ## Attributes + + * `href` - Required. Link destination. + * `class` - Optional. Additional CSS classes. + + ## Slots + + * `inner_block` - Required. Link content. + + ## Examples + + <.shop_link_button href="/checkout">Checkout + """ + attr :href, :string, required: true + attr :class, :string, default: nil + + slot :inner_block, required: true + + def shop_link_button(assigns) do + ~H""" + + {render_slot(@inner_block)} + + """ + end + + @doc """ + Renders a themed link styled as an outline button. + + ## Attributes + + * `href` - Required. Link destination. + * `class` - Optional. Additional CSS classes. + + ## Slots + + * `inner_block` - Required. Link content. + + ## Examples + + <.shop_link_outline href="/collections/all">Continue Shopping + """ + attr :href, :string, required: true + attr :class, :string, default: nil + + slot :inner_block, required: true + + def shop_link_outline(assigns) do + ~H""" + + {render_slot(@inner_block)} + + """ + end + + @doc """ + Renders a themed card container. + + ## Attributes + + * `class` - Optional. Additional CSS classes. + + ## Slots + + * `inner_block` - Required. Card content. + + ## Examples + + <.shop_card class="p-6"> +

Card Title

+

Card content...

+ + """ + attr :class, :string, default: nil + + slot :inner_block, required: true + + def shop_card(assigns) do + ~H""" +
+ {render_slot(@inner_block)} +
+ """ + end + @doc """ Renders a mobile bottom navigation bar. @@ -313,7 +553,7 @@ defmodule SimpleshopThemeWeb.ShopComponents do

Shop

-
    +
      <%= if @mode == :preview do %>
    • All products
    • New arrivals
    • @@ -329,7 +569,7 @@ defmodule SimpleshopThemeWeb.ShopComponents do

      Help

      -
        +
          <%= if @mode == :preview do %>
        • Delivery
        • Returns
        • @@ -1302,16 +1542,11 @@ defmodule SimpleshopThemeWeb.ShopComponents do """ end - defp hero_cta_classes(:primary), do: "px-8 py-3 font-semibold transition-all" - defp hero_cta_classes(:secondary), do: "px-8 py-3 font-semibold transition-all" + defp hero_cta_classes(:primary), do: "themed-button px-8 py-3 font-semibold transition-all" + defp hero_cta_classes(:secondary), do: "themed-button-outline px-8 py-3 font-semibold transition-all" - defp hero_cta_style(:primary) do - "background-color: hsl(var(--t-accent-h) var(--t-accent-s) var(--t-accent-l)); color: var(--t-text-inverse); border-radius: var(--t-radius-button); border: none; cursor: pointer;" - end - - defp hero_cta_style(:secondary) do - "border: 2px solid var(--t-border-default); color: var(--t-text-primary); border-radius: var(--t-radius-button); background: transparent; cursor: pointer;" - end + defp hero_cta_style(:primary), do: "" + defp hero_cta_style(:secondary), do: "" @doc """ Renders a row of category circles for navigation. @@ -1601,20 +1836,13 @@ defmodule SimpleshopThemeWeb.ShopComponents do <%= for category <- @categories do %> <% end %>
- + <.shop_select options={@sort_options} class="px-4 py-2" />
""" end @@ -1677,84 +1905,57 @@ defmodule SimpleshopThemeWeb.ShopComponents do def contact_form(assigns) do ~H""" -
+ <.shop_card class="p-8">

- <%= @title %> + {@title}

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

Email me: <%= @email %>

+

Email me: {@email}

<% end %> <%= if @response_time do %> -

<%= @response_time %>

+

{@response_time}

<% end %>
<% else %>
<% end %> -
+
- + <.shop_input type="text" placeholder="Your name" class="w-full px-4 py-2" />
- + <.shop_input type="email" placeholder="your@email.com" class="w-full px-4 py-2" />
- + <.shop_input type="text" placeholder="How can I help?" class="w-full px-4 py-2" />
- + <.shop_textarea rows="5" placeholder="Your message..." class="w-full px-4 py-2" />
- +
-
+ """ end @@ -1767,29 +1968,23 @@ defmodule SimpleshopThemeWeb.ShopComponents do """ def order_tracking_card(assigns) do ~H""" -
+ <.shop_card class="p-6">

Track your order

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

- - +
-
+ """ end @@ -1813,20 +2008,17 @@ defmodule SimpleshopThemeWeb.ShopComponents do def info_card(assigns) do ~H""" -
-

<%= @title %>

-
    + <.shop_card class="p-6"> +

    {@title}

    +
      <%= for item <- @items do %>
    • - <%= item.label %>: <%= item.value %> + {item.label}: {item.value}
    • <% end %>
    -
+ """ end @@ -1849,21 +2041,18 @@ defmodule SimpleshopThemeWeb.ShopComponents do def contact_info_card(assigns) do ~H""" -
-

<%= @title %>

+ <.shop_card class="p-6"> +

{@title}

- <%= @email %> + {@email}

- <%= @response_text %> + {@response_text}

-
+ """ end @@ -1892,25 +2081,21 @@ defmodule SimpleshopThemeWeb.ShopComponents do ~H"""

- <%= @title %> + {@title}

- <%= @description %> + {@description}

- - + <.shop_button type="submit" class="px-6 py-2 text-sm font-medium whitespace-nowrap"> + {@button_text} +
""" @@ -1918,30 +2103,23 @@ defmodule SimpleshopThemeWeb.ShopComponents do def newsletter_card(assigns) do ~H""" -
-

<%= @title %>

+ <.shop_card class="p-6"> +

{@title}

- <%= @description %> + {@description}

- - + <.shop_button type="submit" class="px-4 py-2 text-sm font-medium whitespace-nowrap"> + {@button_text} +
-
+ """ end @@ -1967,26 +2145,23 @@ defmodule SimpleshopThemeWeb.ShopComponents do def social_links_card(assigns) do ~H""" -
-

<%= @title %>

+ <.shop_card class="p-6"> +

{@title}

-
+ """ end @@ -2294,10 +2469,7 @@ defmodule SimpleshopThemeWeb.ShopComponents do def cart_item(assigns) do ~H""" -
+ <.shop_card class="flex gap-4 p-4">

- <%= @currency %><%= @item.product.price / 100 * @item.quantity %> + {@currency}{@item.product.price / 100 * @item.quantity}

-
+ """ end @@ -2368,65 +2540,50 @@ defmodule SimpleshopThemeWeb.ShopComponents do assigns = assign(assigns, :total, total) ~H""" -
+ <.shop_card class="p-6 sticky top-4">

Order Summary

-
+
Subtotal - <%= @currency %><%= Float.round(@subtotal / 100, 2) %> + {@currency}{Float.round(@subtotal / 100, 2)}
Delivery - <%= @currency %><%= Float.round(@delivery / 100, 2) %> + {@currency}{Float.round(@delivery / 100, 2)}
VAT (20%) - <%= @currency %><%= Float.round(@vat / 100, 2) %> + {@currency}{Float.round(@vat / 100, 2)}
Total - <%= @currency %><%= Float.round(@total / 100, 2) %> + {@currency}{Float.round(@total / 100, 2)}
- + <%= if @mode == :preview do %> - + <% else %> - + <.shop_link_outline href="/collections/all" class="block w-full px-6 py-3 font-semibold transition-all text-center"> Continue Shopping - + <% end %> -
+ """ end @@ -2578,7 +2735,7 @@ defmodule SimpleshopThemeWeb.ShopComponents do def trust_badges(assigns) do ~H""" -
+
<%= for item <- @items do %>
<.trust_badge_icon icon={item.icon} /> @@ -2666,18 +2823,15 @@ defmodule SimpleshopThemeWeb.ShopComponents do
-
+
<%= for review <- @reviews do %> <.review_card review={review} /> <% end %>
- +
""" @@ -3116,7 +3270,7 @@ defmodule SimpleshopThemeWeb.ShopComponents do <% end %> <.accordion_item title="Shipping & Returns"> -
+

Delivery

Free UK delivery on orders over £40. Standard delivery 3-5 working days. Express delivery available at checkout.

@@ -3178,7 +3332,7 @@ defmodule SimpleshopThemeWeb.ShopComponents do ~H"""
-
+
<%= for item <- @items do %> <.cart_item item={item} currency={@currency} /> <% end %> diff --git a/lib/simpleshop_theme_web/live/shop_live/collection.ex b/lib/simpleshop_theme_web/live/shop_live/collection.ex index 5c8b07d..b91766b 100644 --- a/lib/simpleshop_theme_web/live/shop_live/collection.ex +++ b/lib/simpleshop_theme_web/live/shop_live/collection.ex @@ -205,16 +205,13 @@ defmodule SimpleshopThemeWeb.ShopLive.Collection do
- + />
""" diff --git a/lib/simpleshop_theme_web/live/theme_live/index.html.heex b/lib/simpleshop_theme_web/live/theme_live/index.html.heex index 1217650..dcf6083 100644 --- a/lib/simpleshop_theme_web/live/theme_live/index.html.heex +++ b/lib/simpleshop_theme_web/live/theme_live/index.html.heex @@ -252,7 +252,7 @@
-
+
Zoom diff --git a/lib/simpleshop_theme_web/live/user_live/login.ex b/lib/simpleshop_theme_web/live/user_live/login.ex index f9bb9de..3288c70 100644 --- a/lib/simpleshop_theme_web/live/user_live/login.ex +++ b/lib/simpleshop_theme_web/live/user_live/login.ex @@ -7,7 +7,7 @@ defmodule SimpleshopThemeWeb.UserLive.Login do def render(assigns) do ~H""" -
+
<.header>

Log in