Make mobile wishlist hearts smaller/subtler instead of full-size everywhere

Full-size, always-visible hearts on touch devices recreated the exact "a heart on every card" visual noise revealOnHover exists to avoid. Touch devices now get a smaller, backgroundless, slightly transparent heart instead — present and tappable everywhere, but visually quiet. Desktop hover-reveal behavior is unchanged.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Marco
2026-07-31 20:49:25 +00:00
parent 9bf6e3f4f2
commit 92c6953724
+17 -5
View File
@@ -26,10 +26,16 @@ export function WishlistButton({
* filled heart stays as a permanent status indicator) — right for a
* multi-card grid (ProductGrid.tsx), where a heart on every single card
* reads as visual noise. Relies on the parent card already carrying
* `group`/`focus-within` (see ProductGrid.tsx). Always visible on
* coarse-pointer (touch) devices regardless of hover/focus state —
* `group`/`focus-within` (see ProductGrid.tsx).
*
* On coarse-pointer (touch) devices, hover-reveal can't work at all —
* touch has no persistent `:hover`, so a tap on the card never reliably
* reveals a `group-hover`-gated element the way a mouse hover does. */
* reveals a `group-hover`-gated element the way a mouse hover does.
* Rather than falling back to "always visible at full size" (which
* recreates the exact "a heart on every card" visual noise this mode
* exists to avoid), touch devices get a smaller, backgroundless variant
* instead — present and tappable everywhere, but visually quiet enough
* not to read as a wall of hearts. */
revealOnHover?: boolean;
}) {
const { isWishlisted, toggle } = useWishlist();
@@ -62,11 +68,17 @@ export function WishlistButton({
disabled={pending}
className={`flex h-9 w-9 items-center justify-center rounded-full bg-bg-base/90 backdrop-blur-sm transition-all active:scale-90 disabled:opacity-60 ${
revealOnHover && !wishlisted
? "opacity-0 group-hover:opacity-100 group-focus-within:opacity-100 focus-visible:opacity-100 pointer-coarse:opacity-100"
? "opacity-0 group-hover:opacity-100 group-focus-within:opacity-100 focus-visible:opacity-100 pointer-coarse:opacity-100 pointer-coarse:h-7 pointer-coarse:w-7 pointer-coarse:bg-transparent pointer-coarse:backdrop-blur-none"
: ""
} ${className}`}
>
<svg width="20" height="18" viewBox="0 0 20 18" fill={wishlisted ? "currentColor" : "none"} className={wishlisted ? "text-brand" : "text-text-primary"}>
<svg
width="20"
height="18"
viewBox="0 0 20 18"
fill={wishlisted ? "currentColor" : "none"}
className={`${wishlisted ? "text-brand" : "text-text-primary"} ${revealOnHover && !wishlisted ? "pointer-coarse:scale-75 pointer-coarse:opacity-70" : ""}`}
>
<path
d="M10 17S1 11.5 1 5.8C1 2.6 3.4 1 5.8 1c1.6 0 3.2.9 4.2 2.4C11 1.9 12.6 1 14.2 1 16.6 1 19 2.6 19 5.8 19 11.5 10 17 10 17Z"
stroke="currentColor"