2026-02-18 21:23:15 +00:00
|
|
|
defmodule BerrypodWeb.ShopComponents.Base do
|
refactor: split shop_components.ex into 5 focused sub-modules
4,487-line monolith → 23-line facade + 5 modules:
- Base (inputs, buttons, cards)
- Layout (header, footer, mobile nav, shop_layout)
- Cart (drawer, items, order summary)
- Product (cards, gallery, variant selector, hero)
- Content (rich text, images, contact, reviews)
`use SimpleshopThemeWeb.ShopComponents` imports all sub-modules.
No single file over ~1,600 lines now.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 14:30:25 +00:00
|
|
|
use Phoenix.Component
|
|
|
|
|
|
|
|
|
|
@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"""
|
|
|
|
|
<input type={@type} class={["themed-input", @class]} {@rest} />
|
|
|
|
|
"""
|
|
|
|
|
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"""
|
|
|
|
|
<textarea class={["themed-input", @class]} {@rest}></textarea>
|
|
|
|
|
"""
|
|
|
|
|
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"""
|
|
|
|
|
<select class={["themed-select", @class]} {@rest}>
|
|
|
|
|
<%= for option <- @options do %>
|
|
|
|
|
<%= case option do %>
|
|
|
|
|
<% {value, label} -> %>
|
|
|
|
|
<option value={value} selected={@selected == value}>{label}</option>
|
|
|
|
|
<% label -> %>
|
|
|
|
|
<option selected={@selected == label}>{label}</option>
|
|
|
|
|
<% end %>
|
|
|
|
|
<% end %>
|
|
|
|
|
</select>
|
|
|
|
|
"""
|
|
|
|
|
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>
|
|
|
|
|
<.shop_button type="submit" class="w-full">Subscribe</.shop_button>
|
|
|
|
|
"""
|
|
|
|
|
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"""
|
|
|
|
|
<button type={@type} class={["themed-button", @class]} {@rest}>
|
|
|
|
|
{render_slot(@inner_block)}
|
|
|
|
|
</button>
|
|
|
|
|
"""
|
|
|
|
|
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</.shop_button_outline>
|
|
|
|
|
"""
|
|
|
|
|
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"""
|
|
|
|
|
<button type={@type} class={["themed-button-outline", @class]} {@rest}>
|
|
|
|
|
{render_slot(@inner_block)}
|
|
|
|
|
</button>
|
|
|
|
|
"""
|
|
|
|
|
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</.shop_link_button>
|
|
|
|
|
"""
|
|
|
|
|
attr :href, :string, required: true
|
|
|
|
|
attr :class, :string, default: nil
|
|
|
|
|
|
|
|
|
|
slot :inner_block, required: true
|
|
|
|
|
|
|
|
|
|
def shop_link_button(assigns) do
|
|
|
|
|
~H"""
|
2026-02-11 14:46:12 +00:00
|
|
|
<.link
|
|
|
|
|
navigate={@href}
|
refactor: split shop_components.ex into 5 focused sub-modules
4,487-line monolith → 23-line facade + 5 modules:
- Base (inputs, buttons, cards)
- Layout (header, footer, mobile nav, shop_layout)
- Cart (drawer, items, order summary)
- Product (cards, gallery, variant selector, hero)
- Content (rich text, images, contact, reviews)
`use SimpleshopThemeWeb.ShopComponents` imports all sub-modules.
No single file over ~1,600 lines now.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 14:30:25 +00:00
|
|
|
class={["themed-button", @class]}
|
|
|
|
|
>
|
|
|
|
|
{render_slot(@inner_block)}
|
2026-02-11 14:46:12 +00:00
|
|
|
</.link>
|
refactor: split shop_components.ex into 5 focused sub-modules
4,487-line monolith → 23-line facade + 5 modules:
- Base (inputs, buttons, cards)
- Layout (header, footer, mobile nav, shop_layout)
- Cart (drawer, items, order summary)
- Product (cards, gallery, variant selector, hero)
- Content (rich text, images, contact, reviews)
`use SimpleshopThemeWeb.ShopComponents` imports all sub-modules.
No single file over ~1,600 lines now.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 14:30:25 +00:00
|
|
|
"""
|
|
|
|
|
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</.shop_link_outline>
|
|
|
|
|
"""
|
|
|
|
|
attr :href, :string, required: true
|
|
|
|
|
attr :class, :string, default: nil
|
|
|
|
|
|
|
|
|
|
slot :inner_block, required: true
|
|
|
|
|
|
|
|
|
|
def shop_link_outline(assigns) do
|
|
|
|
|
~H"""
|
2026-02-11 14:46:12 +00:00
|
|
|
<.link
|
|
|
|
|
navigate={@href}
|
refactor: split shop_components.ex into 5 focused sub-modules
4,487-line monolith → 23-line facade + 5 modules:
- Base (inputs, buttons, cards)
- Layout (header, footer, mobile nav, shop_layout)
- Cart (drawer, items, order summary)
- Product (cards, gallery, variant selector, hero)
- Content (rich text, images, contact, reviews)
`use SimpleshopThemeWeb.ShopComponents` imports all sub-modules.
No single file over ~1,600 lines now.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 14:30:25 +00:00
|
|
|
class={["themed-button-outline", @class]}
|
|
|
|
|
>
|
|
|
|
|
{render_slot(@inner_block)}
|
2026-02-11 14:46:12 +00:00
|
|
|
</.link>
|
refactor: split shop_components.ex into 5 focused sub-modules
4,487-line monolith → 23-line facade + 5 modules:
- Base (inputs, buttons, cards)
- Layout (header, footer, mobile nav, shop_layout)
- Cart (drawer, items, order summary)
- Product (cards, gallery, variant selector, hero)
- Content (rich text, images, contact, reviews)
`use SimpleshopThemeWeb.ShopComponents` imports all sub-modules.
No single file over ~1,600 lines now.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 14:30:25 +00:00
|
|
|
"""
|
|
|
|
|
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">
|
|
|
|
|
<h3>Card Title</h3>
|
|
|
|
|
<p>Card content...</p>
|
|
|
|
|
</.shop_card>
|
|
|
|
|
"""
|
|
|
|
|
attr :class, :string, default: nil
|
|
|
|
|
|
|
|
|
|
slot :inner_block, required: true
|
|
|
|
|
|
|
|
|
|
def shop_card(assigns) do
|
|
|
|
|
~H"""
|
|
|
|
|
<div class={["themed-card", @class]}>
|
|
|
|
|
{render_slot(@inner_block)}
|
|
|
|
|
</div>
|
|
|
|
|
"""
|
|
|
|
|
end
|
|
|
|
|
end
|