product card is now pengui ui
This commit is contained in:
File diff suppressed because one or more lines are too long
47
assets/views/penguinui/card/ecommerce-product-card.html
Normal file
47
assets/views/penguinui/card/ecommerce-product-card.html
Normal file
@@ -0,0 +1,47 @@
|
||||
<article class="group flex rounded-radius max-w-sm flex-col overflow-hidden border border-outline bg-surface-alt text-on-surface dark:border-outline-dark dark:bg-surface-dark-alt dark:text-on-surface-dark">
|
||||
<!-- Image -->
|
||||
<div class="h-44 md:h-64 overflow-hidden">
|
||||
<img src="https://penguinui.s3.amazonaws.com/component-assets/card-img-3.webp" class="object-cover transition duration-700 ease-out group-hover:scale-105" alt="CASIO G-SHOCK GA2100, Black face, black bands" />
|
||||
</div>
|
||||
<!-- Content -->
|
||||
<div class="flex flex-col gap-4 p-6">
|
||||
<!-- Header -->
|
||||
<div class="flex flex-col md:flex-row gap-4 md:gap-12 justify-between">
|
||||
<!-- Title & Rating -->
|
||||
<div class="flex flex-col">
|
||||
<h3 class="text-lg lg:text-xl font-bold text-on-surface-strong dark:text-on-surface-dark-strong" aria-describedby="productDescription">CASIO G-SHOCK GA2100</h3>
|
||||
<!-- Rating -->
|
||||
<div class="flex items-center gap-1">
|
||||
<span class="sr-only">Rated 3 stars</span>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="size-4 text-amber-500" aria-hidden="true">
|
||||
<path fill-rule="evenodd" d="M10.788 3.21c.448-1.077 1.976-1.077 2.424 0l2.082 5.007 5.404.433c1.164.093 1.636 1.545.749 2.305l-4.117 3.527 1.257 5.273c.271 1.136-.964 2.033-1.96 1.425L12 18.354 7.373 21.18c-.996.608-2.231-.29-1.96-1.425l1.257-5.273-4.117-3.527c-.887-.76-.415-2.212.749-2.305l5.404-.433 2.082-5.006z" clip-rule="evenodd" />
|
||||
</svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="size-4 text-amber-500" aria-hidden="true">
|
||||
<path fill-rule="evenodd" d="M10.788 3.21c.448-1.077 1.976-1.077 2.424 0l2.082 5.007 5.404.433c1.164.093 1.636 1.545.749 2.305l-4.117 3.527 1.257 5.273c.271 1.136-.964 2.033-1.96 1.425L12 18.354 7.373 21.18c-.996.608-2.231-.29-1.96-1.425l1.257-5.273-4.117-3.527c-.887-.76-.415-2.212.749-2.305l5.404-.433 2.082-5.006z" clip-rule="evenodd" />
|
||||
</svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="size-4 text-amber-500" aria-hidden="true">
|
||||
<path fill-rule="evenodd" d="M10.788 3.21c.448-1.077 1.976-1.077 2.424 0l2.082 5.007 5.404.433c1.164.093 1.636 1.545.749 2.305l-4.117 3.527 1.257 5.273c.271 1.136-.964 2.033-1.96 1.425L12 18.354 7.373 21.18c-.996.608-2.231-.29-1.96-1.425l1.257-5.273-4.117-3.527c-.887-.76-.415-2.212.749-2.305l5.404-.433 2.082-5.006z" clip-rule="evenodd" />
|
||||
</svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="size-4 text-on-surface/50 dark:text-on-surface-dark/50" aria-hidden="true">
|
||||
<path fill-rule="evenodd" d="M10.788 3.21c.448-1.077 1.976-1.077 2.424 0l2.082 5.007 5.404.433c1.164.093 1.636 1.545.749 2.305l-4.117 3.527 1.257 5.273c.271 1.136-.964 2.033-1.96 1.425L12 18.354 7.373 21.18c-.996.608-2.231-.29-1.96-1.425l1.257-5.273-4.117-3.527c-.887-.76-.415-2.212.749-2.305l5.404-.433 2.082-5.006z" clip-rule="evenodd" />
|
||||
</svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="size-4 text-on-surface/50 dark:text-on-surface-dark/50" aria-hidden="true">
|
||||
<path fill-rule="evenodd" d="M10.788 3.21c.448-1.077 1.976-1.077 2.424 0l2.082 5.007 5.404.433c1.164.093 1.636 1.545.749 2.305l-4.117 3.527 1.257 5.273c.271 1.136-.964 2.033-1.96 1.425L12 18.354 7.373 21.18c-.996.608-2.231-.29-1.96-1.425l1.257-5.273-4.117-3.527c-.887-.76-.415-2.212.749-2.305l5.404-.433 2.082-5.006z" clip-rule="evenodd" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<span class="text-xl"><span class="sr-only">Price</span>$99.99</span>
|
||||
</div>
|
||||
<p id="productDescription" class="mb-2 text-pretty text-sm">
|
||||
The Casio G-Shock GA2100 is simply designed for easy
|
||||
timekeeping, featuring a sleek profile and clear display.
|
||||
</p>
|
||||
<!-- Button -->
|
||||
<button type="button" class="flex items-center justify-center gap-2 whitespace-nowrap bg-primary px-4 py-2 text-center text-sm font-medium tracking-wide text-on-primary transition hover:opacity-75 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary active:opacity-100 active:outline-offset-0 dark:bg-primary-dark dark:text-on-primary-dark dark:focus-visible:outline-primary-dark rounded-radius">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true" class="size-3.5">
|
||||
<path fill-rule="evenodd" d="M5 4a3 3 0 0 1 6 0v1h.643a1.5 1.5 0 0 1 1.492 1.35l.7 7A1.5 1.5 0 0 1 12.342 15H3.657a1.5 1.5 0 0 1-1.492-1.65l.7-7A1.5 1.5 0 0 1 4.357 5H5V4Zm4.5 0v1h-3V4a1.5 1.5 0 0 1 3 0Zm-3 3.75a.75.75 0 0 0-1.5 0v1a3 3 0 1 0 6 0v-1a.75.75 0 0 0-1.5 0v1a1.5 1.5 0 1 1-3 0v-1Z" clip-rule="evenodd" />
|
||||
</svg>
|
||||
Add to Cart
|
||||
</button>
|
||||
</div>
|
||||
</article>
|
||||
@@ -1,17 +1,27 @@
|
||||
<div
|
||||
class="group flex flex-col overflow-hidden rounded-radius border border-outline bg-surface transition hover:border-primary dark:border-outline-dark dark:bg-surface-dark-alt dark:hover:border-primary-dark">
|
||||
{# Adapted from the vendored Penguin UI component
|
||||
(assets/views/penguinui/card/ecommerce-product-card.html):
|
||||
wired to our product data + i18n + htmx add-to-cart + toast. The demo rating
|
||||
stars, hardcoded title/price/description/image and the `max-w-sm` (which fights
|
||||
the shop grid) are dropped; the whole card links to the product page. #}
|
||||
<article
|
||||
class="group flex flex-col overflow-hidden rounded-radius border border-outline bg-surface-alt text-on-surface transition hover:border-primary dark:border-outline-dark dark:bg-surface-dark-alt dark:text-on-surface-dark dark:hover:border-primary-dark">
|
||||
<a href="/shop/{{ product.slug }}" class="flex flex-1 flex-col">
|
||||
<div class="aspect-square overflow-hidden bg-surface-alt dark:bg-surface-dark">
|
||||
<!-- Image -->
|
||||
<div class="h-44 overflow-hidden bg-surface-alt md:h-64 dark:bg-surface-dark">
|
||||
{% if product.image %}
|
||||
<img src="/images/{{ product.image }}" alt="{{ product.name }}" class="size-full object-cover transition group-hover:scale-105">
|
||||
<img src="/images/{{ product.image }}" alt="{{ product.name }}" class="size-full object-cover transition duration-700 ease-out group-hover:scale-105">
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="flex flex-1 flex-col gap-1 p-4 pb-2">
|
||||
<h3 class="font-medium text-on-surface-strong dark:text-on-surface-dark-strong">{{ product.name }}</h3>
|
||||
<p class="mt-auto pt-2 font-semibold text-primary dark:text-primary-dark">{{ product.price }} {{ product.currency }}</p>
|
||||
<!-- Content -->
|
||||
<div class="flex flex-1 flex-col gap-1 p-6 pb-2">
|
||||
<!-- Header: Title & Price -->
|
||||
<div class="flex justify-between gap-4">
|
||||
<h3 class="text-lg font-bold text-on-surface-strong dark:text-on-surface-dark-strong">{{ product.name }}</h3>
|
||||
<span class="whitespace-nowrap text-xl"><span class="sr-only">Price</span>{{ product.price }} {{ product.currency }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
<div class="flex flex-col gap-2 px-4 pb-4">
|
||||
<div class="flex flex-col gap-2 p-6 pt-0">
|
||||
{% if product.stock > 0 %}
|
||||
<p class="text-xs text-on-surface/60 dark:text-on-surface-dark/60">{{ t(key="in-stock", lang=lang | default(value='sk')) }}: {{ product.stock }}</p>
|
||||
<form method="post" action="/cart/add" hx-post="/cart/add" hx-swap="none"
|
||||
@@ -19,7 +29,10 @@
|
||||
<input type="hidden" name="product_id" value="{{ product.id }}">
|
||||
<input type="hidden" name="quantity" value="1">
|
||||
<button type="submit"
|
||||
class="inline-flex w-full items-center justify-center rounded-radius bg-primary px-4 py-2 text-sm font-medium tracking-wide text-on-primary transition hover:opacity-75 dark:bg-primary-dark dark:text-on-primary-dark">
|
||||
class="flex w-full items-center justify-center gap-2 whitespace-nowrap rounded-radius bg-primary px-4 py-2 text-center text-sm font-medium tracking-wide text-on-primary transition hover:opacity-75 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary active:opacity-100 active:outline-offset-0 dark:bg-primary-dark dark:text-on-primary-dark dark:focus-visible:outline-primary-dark">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true" class="size-3.5">
|
||||
<path fill-rule="evenodd" d="M5 4a3 3 0 0 1 6 0v1h.643a1.5 1.5 0 0 1 1.492 1.35l.7 7A1.5 1.5 0 0 1 12.342 15H3.657a1.5 1.5 0 0 1-1.492-1.65l.7-7A1.5 1.5 0 0 1 4.357 5H5V4Zm4.5 0v1h-3V4a1.5 1.5 0 0 1 3 0Zm-3 3.75a.75.75 0 0 0-1.5 0v1a3 3 0 1 0 6 0v-1a.75.75 0 0 0-1.5 0v1a1.5 1.5 0 1 1-3 0v-1Z" clip-rule="evenodd" />
|
||||
</svg>
|
||||
{{ t(key="add-to-cart", lang=lang | default(value='sk')) }}
|
||||
</button>
|
||||
</form>
|
||||
@@ -27,4 +40,4 @@
|
||||
<p class="inline-flex justify-center rounded-radius bg-danger/10 px-3 py-2 text-xs font-medium text-danger">{{ t(key="out-of-stock", lang=lang | default(value='sk')) }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
@@ -127,18 +127,15 @@ and then use it (instead of hand-rolling):
|
||||
|
||||
---
|
||||
|
||||
## 6. Product Card
|
||||
## 6. Product Card — ✅ DONE
|
||||
**Penguin UI: `card/ecommerce-product-card.html`**
|
||||
|
||||
| # | Location | What it is | Size |
|
||||
|---|----------|------------|------|
|
||||
| 11 | `assets/views/shop/_card.html:1-30` | E-commerce product card: image, name, price, stock, add-to-cart button | ~30 lines |
|
||||
|
||||
**Details:**
|
||||
- `aspect-square` image container with `group-hover:scale-105` zoom effect
|
||||
- Product name + price in a flex column
|
||||
- Bottom section: conditional stock text OR out-of-stock badge + `<form>` with htmx `hx-post` add-to-cart
|
||||
- Inline toast call on successful add: `hx-on::after-request="... toast()"` (toast excluded per scope)
|
||||
- Exact upstream mirror at `assets/views/penguinui/card/ecommerce-product-card.html` (reference only)
|
||||
- Adapted/rendered copy is `assets/views/shop/_card.html`: `<article>` shell + Penguin
|
||||
image/title/price layout and the cart-icon add-to-cart button, wired to our product
|
||||
data + i18n + htmx `hx-post` add-to-cart + `toast()`. Demo-only rating stars,
|
||||
hardcoded content and `max-w-sm` (fights the shop grid) were dropped; whole card
|
||||
links to the product page; out-of-stock badge kept.
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user