Make product card row alignment fully dynamic via CSS Grid subgrid

Replaces the fixed line-clamp-2 subline cap with real subgrid alignment:
each grid (ProductGrid/RelatedProducts/MerklisteGrid) declares 6 explicit
row-tracks (image/header/price/belowPrice/lowstock/button, last one
minmax(0,1fr)), and every card spans those same 6 tracks via
grid-template-rows: subgrid — so row heights are genuinely shared across
a row of cards. A subline can now wrap to any number of lines (3, 4, ...)
without being truncated, and the price row still starts at the same Y on
every card in that row.

ProductCard.tsx is flattened from nested flex divs into 6 direct grid-row
children so each one can be its own subgrid track; the old flex-1 spacer
is replaced by self-end on the button's row.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J1Hu5bZ1kZUgKhab6yNwCt
This commit is contained in:
Marco
2026-08-26 23:49:50 +00:00
parent 8f006b6603
commit 98b3b3b6da
4 changed files with 77 additions and 65 deletions
@@ -39,17 +39,18 @@ export function MerklisteGrid({
}
return (
// No items-start — see ProductGrid.tsx's own comment on why that
// silently defeats ProductCard's h-full equal-height design.
<RevealGroup className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6 w-full">
// No items-start, and grid-auto-rows + subgrid on each RevealItem —
// see ProductGrid.tsx's own comment on why both are needed for
// ProductCard's internal rows (price, etc.) to actually line up
// across cards, not just overall card height.
<RevealGroup className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6 [grid-auto-rows:auto_auto_auto_auto_auto_minmax(0,1fr)] w-full">
{visibleEntries.map(({ item, product }) => (
<RevealItem key={`${product.id}-${item.variant}`}>
<RevealItem key={`${product.id}-${item.variant}`} className="grid [grid-template-rows:subgrid] [grid-row:span_6]">
<ProductCard
product={product}
defaultTaxRate={defaultTaxRate}
kleinunternehmer={kleinunternehmer}
wishlistEnabled
className="h-full"
// Already-purchased takes precedence over the default
// Ausverkauft/discount badge — a customer who already bought
// this doesn't need a restock notice, they need to know they