Home
Wiki
Home
Wiki
  1. 2. Components
  • Back to home
  • 1. Themes
  • Vs Code
    • Getting Started
  • Kitchenware
    • Layout
      • New Layout
      • Legacy Layout
    • Components
      • Announcement
      • Banner Carousel
      • Banner With Products Carousel
      • Blog Category List
      • Blog List
      • Brand List
      • Brands Carousel
      • Breadcrumb
      • Call To Action
      • Cart
      • Categories List
      • Change Password
      • Checkout
      • Cookie Manager
      • Filter list
      • Footer
      • Forgot Password
      • Form
      • Hero Carousel
      • Icon Block
      • Invitation
      • Last Visited Products
      • Layout
      • Login
      • Map
      • Nav Bar
      • Offer
      • Product Attachments
      • Product Attributes
      • Product Documentation
      • Product Expected
      • Product Modal
      • Products Block
      • Products Carousel
      • Product Single
      • Profile
      • Quote
      • Register
      • Related Products
      • Search
      • Stores
      • Subscribe Newsletter
      • Text with Image
      • Top Bar
      • Video
    • Reusables
      • Getting Started
    • Assets
      • Getting Started
    • SDK
      • Products
        • _findProductsByCategory
        • _findProductsByIds
        • _findProductsByTitle
        • _findProductsByFilter
        • _findProductsByCriteria
        • _findProductsAndCalculate
        • _findProductsThenCalculate
        • _getProductAttributeSet
        • _setLastVisited
      • Categories
        • _findCategoryTreeById
        • _findCategoriesByIds
        • _findCategoryByAlias
        • _findCategoryTreeByAlias
        • _getCategoryContent
      • Collections
        • _getCollectionContent
        • _findCollectionsByIds
        • _findCollectionsByIdsThenCalculate
      • Brands
        • _getBrandContent
        • _findBrandsByIds
      • Cart
        • _addToCartMulti
        • _addToCart
        • _setCart
        • _clearCart
        • _setCartListener
        • _removeFromCart
        • _calculateCart
      • Checkout
        • _startCheckout
        • _updateCheckout
        • _completeCheckout
      • Shopping Lists
        • _getShoppingLists
        • _updateShoppingList
        • _createShoppingList
        • _deleteShoppingList
        • _getShoppingListByAlias
      • Navigation
        • _getFooterMenu
        • _getHeaderMenu
      • Users
        • _getUserById
      • Utils
        • _calculateCurrency
        • _getCurrencySymbol
        • _getCulture
        • _subscribeToNewsletter
        • _findUnitsByIds
  • Noir
    • 0. Introduction
    • 6. FAQ
    • 1. Structure
      • _Overview
      • LayoutA.liquid
      • ComponentsList.liquid
      • Metas.liquid
      • CssVariables.liquid
      • Json.liquid
      • GoogleTagManager.liquid
      • StagingButton.liquid
    • 2. Components
      • _Overview
      • Announcement
      • BannerCarousel
      • BlogCategoryList
      • BlogHighlights
      • BlogList
      • BrandList
      • Breadcrumb
      • Cart
      • CategoriesList
      • ChangePassword
      • Checkout
      • CookieManager
      • CustomTable
      • FilterList
      • Footer
      • ForgotPassword
      • Form
      • IconBlock
      • Invitation
      • LastVisitedProducts
      • Login
      • Map
      • NavBar
      • Offer
      • ProductAttachments
      • ProductAttributes
      • ProductComparison
      • ProductDocumentation
      • ProductMixList
      • ProductsBlock
      • ProductsCarousel
      • ProductSingle
      • Profile
      • Quote
      • Register
      • RelatedProducts
      • SingleBlog
      • Stores
      • TextWithImage
      • ThankYouPage
      • TopBar
      • Wishlist
    • 3. Reusables
      • _Overview
      • Addresses
      • AddressForm
      • AnnouncementModal
      • BackToTop
      • BillingRetail
      • BlogPostingStructuredData
      • BrandListStructuredData
      • CollectionStructuredData
      • Company
      • General
      • Login
      • LoginModal
      • MonthlyTransactions
      • Offers
      • Orders
      • Payment
      • ProductAttachments
      • ProductAttributes
      • ProductComparisonButton
      • ProductComparisonFloatingButton
      • ProductGridItem
      • ProductGridItemClassic
      • ProductListItem
      • ProductModal
      • ProductStructuredData
      • ProfileInfo
      • PromptModal
      • Quotes
      • Register
      • Services
      • Shipping
      • ShoppingLists
      • ShoppingListsButton
      • ShoppingListsNavbar
      • StoresStructuredData
      • Toast
      • Transactions
      • Users
      • VariantContent
      • VariantContentClassic
      • WishlistButton
    • 4. Assets
      • Fonts
      • Images
      • Templates
      • Javascript
        • _Overview
        • theme.js
      • Css - Scss
        • _Overview
        • ThemeClasses
    • 5. SDK
      • _Overview
      • LiquidGlobals
      • ServicesSDK
  1. 2. Components

NavBar

Purpose#

NavBar renders the storefront header navigation:
Mega menus (Vertical/Horizontal)
Burger menu (desktop overlay + fixed panel)
Simple menu (classic dropdown behavior)
It’s rendered as a header component (SectionHeader).

Inputs (model contract)#

{
  "unReadAnnouncements": 0,
  "navigations": [
    {
      "navigationTitle": "Sample navigation title",
      "url": "/sample",
      "image": {},
      "banners": [],
      "bannersLink": "",
      "bannersText": "Sample text",
      "menuIcon": {},
      "navigations": [
        {
          "navigationTitle": "Sample navigation title",
          "url": "/sample",
          "image": {
            "id": "Image Id",
            "link": "https://example.com/media/sample.jpg"
          },
          "banners": [
            {
              "image": {
                "id": "Banner image Id",
                "link": "https://example.com/media/sample-banner.jpg"
              }
            },
            "..."
          ],
          "bannersLink": "",
          "bannersText": "Sample text",
          "menuIcon": {},
          "navigations": [
            {
              "navigationTitle": "Sample navigation title",
              "url": "/sample",
              "image": {
                "id": "Image Id",
                "link": "https://example.com/media/sample.jpg"
              },
              "banners": [],
              "bannersLink": "",
              "bannersText": "",
              "menuIcon": {},
              "navigations": [
                {
                  "navigationTitle": "Sample navigation title",
                  "url": "/sample",
                  "image": {
                    "id": "Image Id"
                  },
                  "banners": [],
                  "bannersLink": "",
                  "bannersText": "",
                  "menuIcon": {}
                },
                "..."
              ]
            },
            "..."
          ]
        },
        "..."
      ]
    },
    "..."
  ],
  "name": "NavBar",
  "view": "Default",
  "section": "SectionHeader",
  "settings": {
    "showSearch": true,
    "showLanguage": false,
    "showMenuIcons": false,
    "displayCategoryImages": false,
    "menuType": "Mega",
    "menuOrientation": "Vertical",
    "subMenuLevels": "AllLevels",
    "menuHelperText": "Sample text",
    "id": "Component Id",
    "section": "SectionHeader",
    "type": "NoirNavBar",
    "name": "NavBar",
    "configuredInContentApi": true,
    "view": "Default",
    "displayName": "",
    "cssClass": "",
    "header": "",
    "alignment": "Left"
  },
  "translations": {
    "navbarLogoFor": "Sample text",
    "goToHomepage": "Sample text",
    "openLoginModal": "Sample text",
    "...": "..."
  }
}

Data contract notes (what the template expects)#

model.Settings.Id
model.Settings.showSearch
model.Settings.menuType
model.Settings.menuOrientation
model.Settings.subMenuLevels
model.Settings.enableMiniCart
model.Settings.miniCartTrigger
Used to render the wrapper id: id="comp-{{ id }}".
Values observed in template logic: Mega, Burger, Simple (and anything else treated as “not simple” in some branches).
Used when menuType == 'Mega' to change layout and which submenu types open on click. Values used: Vertical / Horizontal.
Used to decide whether deeper levels are available/laid out (values used in template: OneLevel, TwoLevels, AllLevels).
enableMiniCart turns the header cart icon into a mini-cart trigger. miniCartTrigger selects how it opens: Hover (open on pointer enter / keyboard focus, click still navigates to /cart) or Click (click toggles the panel instead of navigating). Both are passed into initComponent(...).
The mini cart is desktop-only: below the 1440px breakpoint the cart icon always falls back to the plain /cart link, regardless of these settings.
Each navigation item can contain nested navigations[] (the template supports deep nesting up to level 4).
Common fields used:
navigationTitle
url
menuIcon.link (used only for Burger menu + when showMenuIcons = true)
image.link (used for category image previews in Mega Horizontal when displayCategoryImages = true)
banners[] (used for Mega Vertical to show promotional banners to the side)
bannersText, bannersLink (note: the template checks these, but the link is referenced as nav.bannerLink in one place—see Notes)
Read at the top of the template; used later in the markup (outside the snippet we reviewed). It’s part of the header UX for announcements/notifications.
Used by the header UI to open/close the announcements drawer.
$store.announcements
$store.loginModal
$store.shoppingLists
$store.cart
model.Settings.CssClass
model.Settings.menuHelperText
model.Settings.showLanguage
model.Settings.showMenuIcons
model.Settings.displayCategoryImages
GlobalData.Settings.logo.link, logoLight.link, favicon.link
GlobalData.Settings.noImage.link (fallback) + theme fallback Assets/images/no-image.svg
GlobalData.Company.Name, GlobalData.Company.Languages
GlobalData.CurrentLanguage / GlobalData.Company.DefaultLanguage
GlobalData.Settings.EnableShoppingLists, EnableWishlist

Template behavior (Liquid + Alpine)#

Describe rendering flow, state branches, and key Liquid/Alpine behavior.

JavaScript#

Components/NavBar/Default.js defines a global Alpine factory object navbardefault.

navbardefault.initComponent(menuType, menuOrientation, enableMiniCart, miniCartTrigger)#

Creates the Alpine component state for the navbar/menu system.
State highlights:
isMenuVisible controls whether the element should be present/visible at all.
isMenuOpen controls the slide-in/out class toggles.
On mobile it hides sibling menu items when drilling down into submenu levels.
isMiniCartOpen controls the mini-cart panel; miniCartCloseTimeoutId holds the pending hover-close timer.

Lifecycle#

init(): wires resize/scroll listeners and recalculates measurements used by sticky/fixed header UI.

init#

Initializes navbar measurements and registers scroll/resize listeners to keep header offsets up to date.
On resize it also force-closes the mini cart when the viewport drops below the 1440px desktop breakpoint, so the panel can't stay open after the layout switches to mobile.

Mini cart#

Desktop-only dropdown attached to the header cart icon, gated by enableMiniCart and miniCartTrigger. Every handler below returns early when enableMiniCart is false or isMobile is true.

miniCartItems#

Getter returning Alpine.store("cart").items (or []), so the panel renders straight from the shared cart store and stays in sync with any other component that updates it.

handleCartClick#

Click handler on the cart link.
miniCartTrigger === "Click": calls preventDefault() and toggles isMiniCartOpen.
miniCartTrigger === "Hover": does nothing, letting the click navigate to /cart as normal.

handleCartMouseEnter#

Opens the mini cart on pointer enter when miniCartTrigger === "Hover", cancelling any pending close timer first.

handleCartMouseLeave#

Schedules the mini cart to close after a 200ms grace period when miniCartTrigger === "Hover", so moving the cursor from the trigger into the panel does not dismiss it.

closeMiniCart#

Clears the pending close timer and closes the panel immediately. Used by click-away, Escape, and the focus-out handler.

handleCartFocus#

Keyboard equivalent of handleCartMouseEnter: opens the panel when the trigger receives focus, but only in Hover mode — in Click mode Enter/Space already toggles it via handleCartClick, so auto-opening on focus would fight that.

handleCartFocusOut#

Closes the mini cart once focus leaves the whole cart area (trigger + panel), so tabbing through the panel's links and buttons keeps it open.
Key behaviors / edge cases
When event.relatedTarget is null the handler returns without closing. Clicking non-focusable content inside the panel, or removing the element that held focus, reports no next target; closing there would dismiss the panel on an interaction the user made inside it. Click-away, Escape or mouse-leave close it instead.
Uses event.currentTarget.contains(nextFocusTarget) so focus moving within the cart area is ignored.

removeMiniCartItem#

Removes a line from the cart directly from the mini-cart panel.
Clears existing toasts and sets item.isUpdating = true while the request is in flight.
Calls servicesreusabledefault.removeCartLineById(item.id) when the line has an id, otherwise falls back to servicesreusabledefault.removeFromCart(item.productVariantId).
Treats a missing response, a non-2xx status, or response.success === false as a failure and shows removeFromCartErrorMessage via Alpine.store("toast").
Always clears item.isUpdating afterwards.

Search sub-component#

searchComponent(): returns a nested Alpine object used by the search UI.

searchComponent#

Returns a nested Alpine object holding search input state and search handlers.
From searchComponent#
search(): debounced product search.
Side effects: calls servicesreusabledefault.findProductsByCriteria(criteria).
Notes: always sets searchLoading = false in finally.
redirectToSearch(): navigates to /search?s=<encoded query>.
triggerVoiceSearch(): starts voice input (when supported by the browser).

search#

Performs debounced search via servicesreusabledefault.findProductsByCriteria(criteria) and updates resultProducts.

redirectToSearch#

Navigates to the search page with the current input as query parameter.

triggerVoiceSearch#

Uses the Web Speech API to fill the search input from voice.

sendSelectEvent#

Reports GA select-item events for search results / product clicks (product, listName, position).

Height/measurement helpers#

The component contains a few measurement helpers used to keep sticky/fixed UI offsets correct:
menuHeight: the current computed menu height.
menuPaddingTop: the current computed padding/top offset used in menu positioning.
updateNavbarHeight(): re-measures the navbar element height.
updateTopbarHeight(): re-measures the topbar height.
updateLanguageHeight(): re-measures the language selector section height.

menuHeight#

Computed getter returning the available menu height based on viewport and topbar height.

menuPaddingTop#

Computed getter returning the top padding offset used for positioning the menu.

updateNavbarHeight#

Measures the .navbar element height and stores it in state.

updateTopbarHeight#

Measures the .topbar height and stores it in state.

updateLanguageHeight#

Measures the language selector wrapper height (used in mobile menu layout).
Other internal helpers referenced by this component’s JS:
action(...): generic wrapper used by click handlers.
handler(...): event handler used by menu interactions.
run(...): small runner used to sequence DOM measurement updates.

handler#

Internal event handler used by menu interactions (hover/click/transition cases depending on menu type).

run#

Internal runner used to sequence DOM measurement updates over multiple animation frames.

toggleMenu#

Handles open/close of the entire menu.
Behaviors:
sets isMenuVisible = true
on mobile:
waits one tick + RAF, then sets isMenuOpen = true
locks body scroll (document.body.style.overflow = "hidden")
measures languageHeight
on desktop, sets isMenuOpen = true immediately
sets isMenuOpen = false
on mobile: waits for transitionend (menu slide-out), then:
resets submenu states
clears hiddenSiblings
unlocks body scroll
sets isMenuVisible = false
on desktop: just hides (isMenuVisible = false)
Notes:

childHover(submenuIndex, hovered)#

(Used by template sections not shown in our snippet; it’s the standard pattern to avoid closing panels while moving the cursor inside complex mega menus.)

remeasureDesktopMenu#

Re-measures submenu and banner heights for the Mega menu across several animation frames (desktop only).
No-ops on mobile, for non-Mega menus, or when index is missing.
Runs after the next DOM update and refreshes submenuHeight / bannersHeight.

getMaxSubmenuHeight(index)#

Purpose:
Measures the maximum height needed to display the submenu panel for submenu${index} (including nested .navbar__menu__sub elements).
Implementation approach:
clones each submenu element off-screen with height: auto / maxHeight: none
reads clone.scrollHeight
returns the max height (+1px “padding” adjustment)
Important note:
In Components/NavBar/Default.js this function wraps its work in setTimeout(..., 300) and the return is inside that callback.
That means the function does not return a height synchronously (callers currently receive undefined).
If you want this.submenuHeight to actually get a numeric value, refactor to either:
compute synchronously (no setTimeout), or
accept a callback / return a Promise and await it.

getMaxBannersHeight(index)#

Purpose:
Measures the height of the banners column inside the submenu (#submenu${index} .banners-wrap > div) using scrollHeight.
Important note:
Same as above: it returns from inside setTimeout(..., 300) so it does not return a value synchronously.

toggleSubmenuLevel1(index)#

toggleSubmenuLevel2(index), toggleSubmenuLevel3(index), toggleSubmenuLevel4(index)#

requires the parent level to be open
maintains:
submenuVisibleLevelN (controls display)
submenuOpenLevelN (controls the slide transition state)
on mobile, it waits for transitionend when closing so it can clear submenuVisibleLevelN.

closeSubmenuLevel1(index), closeSubmenuLevel2(index), closeSubmenuLevel3(index), closeSubmenuLevel4(index)#

used by the mobile "back" controls, which only ever render inside an already-open panel
delegates to the matching toggleSubmenuLevelN(index), so the close branch (including the
level 2-4 transitionend cleanup) runs unchanged
named for the action rather than reusing the toggle, because a back control is not a disclosure
for the region it sits inside and so must not carry aria-expanded
Notes:
visible keeps the element in the DOM for animation.
open controls translate classes.

handleResize#

Resets menu state on resize, and:
if mobile: false
if desktop and menuType == Burger: false
else: true

resetMenu#

Resets the menu when clicking outside (@click.away="resetMenu" in Liquid).
Very similar to handleResize() but doesn’t recompute isMobile.

navbardefault.handleLogout(logout, modalMessageText, modalButtonCancel)#

Opens a confirmation modal using Alpine.store("modal").open(...).
If user confirms:
cartToken, cartData, checkoutToken
Advice:

navbardefault.handleMultiCustomer(modalTranslationsMultiCustomer, multiCustomerList, currentCustomerId)#

Opens the multi-customer selection modal (step 2 of login) when the authenticated user has more than one linked customer account.
Preselects currentCustomerId when it exists in multiCustomerList; otherwise leaves the radio group unselected.
Renders the modal via Alpine.store("modal").open(...) with a required radio-group input built from multiCustomerList.
On confirm, calls servicesreusabledefault.accountLoginWithCustomerId(selectedCustomerId).
On failure: shows an error via Alpine.store("toast").add(...) and re-enables the login button.
On success: shows a success toast, then redirects to the safe redirect URL, /checkout (when returning from checkout), / (from the login page), or reloads the current page.

Global Alpine stores (used by NavBar)#

From JS + template conventions, NavBar relies on these global items being present in the theme runtime:
Used by navbardefault.handleLogout(...) to show a confirmation modal.
Used by search live results (findProductsByCriteria).
Must exist globally before NavBar JS runs.
sendGAEvent(...)
prepareListProducts(...)
Additionally, based on common Noir patterns, the header may interact with other global stores in adjacent header components.

Web Speech API (optional voice search)
GlobalData: logo, company, languages, feature flags (wishlist/shopping lists)

Notes#

There’s a likely typo in the banners CTA section:
If a promo banner CTA isn’t working, verify the correct property name and fix the Liquid accordingly.
If the storefront language isn’t English, this can feel inconsistent; consider routing the error and messaging through the toast store and mapping language.
Menu breakpoint is hardcoded at 1440px.
If design breakpoints change, update both Liquid responsiveness assumptions and this JS constant.

Extras#

If GlobalData.Settings.logo.link or logoLight.link exists, the navbar renders <img> logo(s).
If no logo exists, it falls back to showing the company name.
The root Alpine scope is created via:
x-data="navbardefault.initComponent('{{ menuType }}','{{ menuOrientation }}',{{ enableMiniCart }},'{{ miniCartTrigger }}')"
There’s one “menu button” that toggles visibility, and a wrapper that:
behaves differently on mobile vs desktop (isMobile = window.innerWidth < 1440)
changes layout based on menuOrientation and subMenuLevels
Submenus:
The template supports (and the JS tracks) open/visible state for:
level 1: submenuOpenLevel1, submenuVisibleLevel2
level 2: submenuOpenLevel2, submenuVisibleLevel3
level 3: submenuOpenLevel3, submenuVisibleLevel4
level 4: submenuOpenLevel4
On mobile, submenus slide horizontally and show a “Back” button per level.
On desktop, submenus are shown/hidden by setting inline display: styles based on open/visible properties.
A search button toggles a search panel.
The search panel contains an <input type="search"> bound to searchText.
Typing triggers a debounced API search and shows up to 5 items (+1 extra is fetched so the UI can decide “show all” behavior).

Language switcher (mobile)#

If there are multiple languages (GlobalData.Company.Languages.size > 1):
A mobile-only language listbox is rendered inside the menu wrapper.
It uses a small local Alpine scope: x-data="{ open: false }".
Modified at 2026-09-21 08:29:56
Previous
Map
Next
Offer
Built with