Purpose#
The WishlistButton reusable renders a toggle button that adds/removes a product from the user’s wishlist.It delegates the actual state management and API calls to the global Alpine store $store.wishlist (defined in Assets/js/theme.js).Where it's rendered#
This reusable is rendered from product cards and product pages, for example:Reusables/ProductGridItem/Default.liquid
Reusables/ProductListItem/Default.liquid
Components/ProductSingle/Default.liquid
{% render 'Reusables\\WishlistButton\\Default', id: product.id, title: product.title %}
Product id used as the wishlist key.
Human-readable product title used for the button title / aria-label.
Template behavior (Liquid + Alpine)#
Rendering is gated by the feature flag:
GlobalData.Settings.EnableWishlist
The template uses Alpine store bindings (no JS factory): :class="{'active': $store.wishlist.isInWishlist('<id>') }"
@click.stop.prevent="$store.wishlist.toggle('<id>', removeErrorMessage, addErrorMessage)"
The button title / aria-label changes depending on whether the product is already in the wishlist.
Data contract (JS runtime)#
This reusable is store-driven. The runtime contract is the existence of $store.wishlist with these methods:toggle(id, removeFromWishlistErrorMessage, addToWishlistErrorMessage)
It also depends on the following browser state:Parsed by $store.wishlist.readWishlistIds().
LocalStorage key: wishlistSync
DOM event: wishlistUpdated
JavaScript#
Global object#
Global object: wishlistbuttonreusabledefaultIt is currently an empty object ({}) and is not referenced by the Liquid template.
The real logic is implemented in the Alpine store $store.wishlist in Assets/js/theme.js.
Global Alpine stores#
$store.wishlist#
A client-side cache of wishlist product ids (items: string[]).
How this reusable uses itReads isInWishlist(id) to render active state and accessible labels.
Calls toggle(...) on click.
If window.showWishlist is false (set in Structure/LayoutA.liquid), the store is not created and the reusable is not rendered.
Services / API calls#
The reusable itself does not call APIs, but $store.wishlist.toggle(...) calls:servicesreusabledefault.addItemToWishlist(id)
servicesreusabledefault.removeItemFromWishlist(id)
On failure it shows toast errors via $store.toast.Dependencies#
Liquid: Reusables/WishlistButton/Default.liquid
Translations: Reusables/WishlistButton/Default.json
Feature flag: GlobalData.Settings.EnableWishlist
Alpine store: $store.wishlist (defined in Assets/js/theme.js)
Alpine store: $store.toast (used by $store.wishlist)
SDK wrapper: servicesreusabledefault.addItemToWishlist(...), servicesreusabledefault.removeItemFromWishlist(...)
Notes#
The button is purely a UI trigger; the wishlist contract lives in $store.wishlist.
The store reads wishlist ids from the wishlist cookie and builds the list differently depending on authentication (window.userAuthenticated, window.userId).
Modified at 2026-04-14 13:18:56