Fix out-of-stock CTA: replace button instead of stacking, collapse notify form
Two problems in the previous back-in-stock commit: the disabled "Ausverkauft" button and NotifyMeForm stacked, making out-of-stock cards visibly taller than in-stock siblings — and since ProductGrid's cards rely on plain CSS Grid row-stretch for equal card height, that extra height stretched sibling cards and pushed their own buttons down (screenshot: "In den Warenkorb" CTAs misaligned across a row). NotifyMeForm now replaces the button slot entirely when out of stock (matching the height of a normal button when collapsed), and only expands to the email input after a click. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -88,7 +88,9 @@ export function AddToCartButton({
|
||||
: added
|
||||
? "border border-success! bg-success-subtle! hover:bg-success-subtle! text-success!"
|
||||
: "";
|
||||
const displayLabel = currentlyOutOfStock ? "Ausverkauft" : limitReached ? "Maximale Menge im Warenkorb" : label;
|
||||
// currentlyOutOfStock has no branch here — that state renders
|
||||
// NotifyMeForm instead of this button entirely (see below).
|
||||
const displayLabel = limitReached ? "Maximale Menge im Warenkorb" : label;
|
||||
|
||||
return (
|
||||
// Low stock is deliberately NOT surfaced here as its own text line
|
||||
@@ -117,47 +119,48 @@ export function AddToCartButton({
|
||||
))}
|
||||
</select>
|
||||
)}
|
||||
<button
|
||||
ref={buttonRef}
|
||||
type="button"
|
||||
onClick={handleClick}
|
||||
disabled={disabled}
|
||||
className={`${base} ${stateClasses}`}
|
||||
>
|
||||
{/* CSS-grid text-stack, not just swapping the button's text node
|
||||
directly — this button is inline-flex/content-sized (no w-full),
|
||||
so "Hinzugefügt ✓" being shorter than most labels made the whole
|
||||
button visibly shrink while showing the success state. Stacking
|
||||
both possible texts in the same grid cell (both invisible ones
|
||||
still contribute to sizing) reserves width for whichever is
|
||||
wider, so the button's box never changes size either way. Now
|
||||
also reserves space for "Ausverkauft"/"Maximale Menge im
|
||||
Warenkorb" — the widest of the four wins regardless of which is
|
||||
showing. */}
|
||||
{/* whitespace-nowrap — inherited by every stacked span below. On a
|
||||
w-full button (e.g. this page's mobile layout), "Maximale Menge
|
||||
im Warenkorb" is long enough to wrap to two lines without this,
|
||||
and since every stacked span shares the same grid cell, that
|
||||
inflated the row height for whichever text is actually showing
|
||||
too — "Ausverkauft" rendered with a tall empty gap underneath it
|
||||
(fixed 2026-07-24). */}
|
||||
<span className="relative grid whitespace-nowrap">
|
||||
<span className="invisible [grid-area:1/1]" aria-hidden="true">
|
||||
{label}
|
||||
{currentlyOutOfStock ? (
|
||||
// Replaces the button slot entirely rather than stacking below a
|
||||
// disabled "Ausverkauft" button — same reasoning as
|
||||
// AddToCartInlineButton's identical swap.
|
||||
<NotifyMeForm productId={numericId} variantName={variants.length > 0 ? (selectedVariant ?? "") : ""} />
|
||||
) : (
|
||||
<button
|
||||
ref={buttonRef}
|
||||
type="button"
|
||||
onClick={handleClick}
|
||||
disabled={disabled}
|
||||
className={`${base} ${stateClasses}`}
|
||||
>
|
||||
{/* CSS-grid text-stack, not just swapping the button's text node
|
||||
directly — this button is inline-flex/content-sized (no w-full),
|
||||
so "Hinzugefügt ✓" being shorter than most labels made the whole
|
||||
button visibly shrink while showing the success state. Stacking
|
||||
both possible texts in the same grid cell (both invisible ones
|
||||
still contribute to sizing) reserves width for whichever is
|
||||
wider, so the button's box never changes size either way. Now
|
||||
also reserves space for "Maximale Menge im Warenkorb" — the
|
||||
widest of the three wins regardless of which is showing. */}
|
||||
{/* whitespace-nowrap — inherited by every stacked span below. On a
|
||||
w-full button (e.g. this page's mobile layout), "Maximale Menge
|
||||
im Warenkorb" is long enough to wrap to two lines without this,
|
||||
and since every stacked span shares the same grid cell, that
|
||||
inflated the row height for whichever text is actually showing
|
||||
too (fixed 2026-07-24). */}
|
||||
<span className="relative grid whitespace-nowrap">
|
||||
<span className="invisible [grid-area:1/1]" aria-hidden="true">
|
||||
{label}
|
||||
</span>
|
||||
<span className="invisible [grid-area:1/1]" aria-hidden="true">
|
||||
Hinzugefügt ✓
|
||||
</span>
|
||||
<span className="invisible [grid-area:1/1]" aria-hidden="true">
|
||||
Maximale Menge im Warenkorb
|
||||
</span>
|
||||
<span className="[grid-area:1/1]">{added ? "Hinzugefügt ✓" : displayLabel}</span>
|
||||
</span>
|
||||
<span className="invisible [grid-area:1/1]" aria-hidden="true">
|
||||
Hinzugefügt ✓
|
||||
</span>
|
||||
<span className="invisible [grid-area:1/1]" aria-hidden="true">
|
||||
Ausverkauft
|
||||
</span>
|
||||
<span className="invisible [grid-area:1/1]" aria-hidden="true">
|
||||
Maximale Menge im Warenkorb
|
||||
</span>
|
||||
<span className="[grid-area:1/1]">{added ? "Hinzugefügt ✓" : displayLabel}</span>
|
||||
</span>
|
||||
</button>
|
||||
{currentlyOutOfStock && <NotifyMeForm productId={numericId} variantName={variants.length > 0 ? (selectedVariant ?? "") : ""} />}
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user