Purpose#
The ShoppingListsNavbar reusable provides the slide-in “Shopping Lists” panel that opens from the site navigation. It lists the user’s shopping lists and links into the Profile → Shopping Lists pages.It relies on the global Alpine Shopping Lists store for:visibility ($store.shoppingLists.visible)
list data ($store.shoppingLists.list)
open/close actions ($store.shoppingLists.close())
Where it's rendered#
This reusable is rendered from Components/NavBar/Default.liquid:{% render 'Reusables\\ShoppingListsNavbar\\Default' %}
This reusable is rendered without Liquid parameters.Model shape (storefront example)#
Sanitized real storefront example (provided by the user) of the shopping lists data used by the navbar.This corresponds to the shape of $store.shoppingLists.list.[
{
"id": "Shopping List Id",
"title": "Sample text",
"alias": "sample",
"items": [
{
"productId": "Product Id",
"productVariantId": "Product Variant Id",
"quantity": 1,
"product": {
"id": "Product Id",
"title": "Sample text",
"alias": "sample"
}
},
...
]
},
...
]
In this theme, the Shopping Lists store often contains a final “pseudo list” entry that is excluded from UI rendering via .slice(0, -1).
Template behavior (Liquid + Alpine)#
Feature flag#
GlobalData.Settings.EnableShoppingLists is truthy.
Visibility + transitions#
The overlay container is shown when $store.shoppingLists.visible is true.
Clicking outside the slide-in panel closes it:
@click.outside="$store.shoppingLists.close()"
Height is bound as inline style:
List rendering#
Renders a items for each shopping list in:
$store.shoppingLists.list.slice(0, -1)
/profile/shoppingLists/${shoppingList.alias}
Item count text uses singular/plural translations: Empty state#
When $store.shoppingLists.list.length == 1, it shows the “no lists found” message. This matches the convention that the store may contain only the pseudo-list entry.The CTA links to /profile/shoppingLists.If list length is 1 → shows “Create New List”.
If list length > 1 → shows “See all”.
JavaScript#
Global object#
Global object: shoppinglistsnavbarreusabledefault (in Reusables/ShoppingListsNavbar/Default.js).It is used directly as an Alpine component object:x-data="shoppinglistsnavbarreusabledefault"
State#
shoppingLists: local copy of Alpine.store('shoppingLists').list
height: computed overlay height (string, e.g. "600px")
Methods#
init()#
Waits for the Shopping Lists store to be ready via waitForShoppingListsReady().
Copies the list into this.shoppingLists.
Recalculates height on resize and scroll.
Polls until Alpine.store('shoppingLists') exists and has: If fetchIfEmpty is true and the store is not loading and has fetch(), it triggers store.fetch() once when the list is empty.
Times out after timeout ms (default 8000) and returns the store (or null).
calculateHeight()#
Measures the header height and sets:
height = window.innerHeight - headerHeight
This ensures the overlay fills the viewport below the header.Global Alpine stores#
fetch() (optional but used)
Services / API calls#
This reusable does not call services directly.It delegates fetching to $store.shoppingLists.fetch() when the store is empty.Dependencies#
Liquid: Reusables/ShoppingListsNavbar/Default.liquid
JS: Reusables/ShoppingListsNavbar/Default.js
Translations: Reusables/ShoppingListsNavbar/Default.json
Components/NavBar/Default.liquid
Notes#
The overlay and panel both use x-show="$store.shoppingLists.visible". This is intentional to animate both the backdrop and the slide-in content.
The empty state check list.length == 1 assumes the Shopping Lists store always includes a final pseudo-list entry.
Modified at 2026-04-14 13:18:56