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
    • 1. Structure
      • Overview
      • LayoutA.liquid
      • ComponentsList.liquid
      • Metas.liquid
      • CssVariables.liquid
      • Json.liquid
      • GoogleTagManager.liquid
      • StagingButton.liquid
    • 2. Components
      • Overview
      • Announcement
      • BannerCarousel
      • BlogCategoryList
      • BlogList
      • BrandList
      • Breadcrumb
      • Cart
      • CategoriesList
      • ChangePassword
      • Checkout
      • CookieManager
      • FilterList
      • Footer
      • ForgotPassword
      • Form
      • IconBlock
      • Invitation
      • LastVisitedProducts
      • Login
      • Map
      • NavBar
      • ProductAttachments
      • ProductAttributes
      • ProductComparison
      • ProductDocumentation
      • ProductMixList
      • ProductsBlock
      • ProductsCarousel
      • ProductSingle
      • Profile
      • Register
      • RelatedProducts
      • SingleBlog
      • Stores
      • TextWithImage
      • ThankYouPage
      • TopBar
      • Wishlist
    • 3. Reusables
      • Overview
      • Addresses
      • BillingRetail
      • AddressForm
      • AnnouncementModal
      • BackToTop
      • Company
      • General
      • Login
      • LoginModal
      • Orders
      • Payment
      • ProductAttachments
      • ProductAttributes
      • ProductComparisonButton
      • ProductComparisonFloatingButton
      • ProductGridItem
      • ProductListItem
      • ShoppingListsButton
      • ProductModal
      • ProfileInfo
      • PromptModal
      • Register
      • Shipping
      • ShoppingLists
      • ShoppingListsNavbar
      • Toast
      • Users
      • VariantContent
      • WishlistButton
      • Services
    • 4. Assets
      • Fonts
      • Images
      • Templates
      • Javascript
        • Overview
        • theme.js
      • Css / Scss
        • Overview
        • ThemeClasses
    • 5. SDK
      • Overview
      • LiquidGlobals
      • ServicesSDK
  1. 2. Components

Footer

Purpose#

The Footer component renders the storefront footer area, including:
Optional newsletter subscription form (email input + validation)
Footer logo (normal + optional “light” variant for dark mode)
Company info block (address, phone/working hours, email) using GlobalData.Company and GlobalData.Settings
Navigation columns (multi-level links) using model.Navigations
Social links (icons + external links)
Payment method logos
Dark mode toggle (driven by $store.darkMode)
Copyright line

Inputs (model contract)#

Model shape (storefront example)#

{
  "navigations": [
    {
      "navigationTitle": "Sample navigation title",
      "navigationType": "Link",
      "url": "/sample",
      "navigations": [
        {
          "navigationTitle": "Sample navigation item",
          "navigationType": "Category",
          "relativeId": "Navigation Relative Id",
          "url": "/category/sample",
          "image": {
            "id": "Image Id",
            "link": "https://example.com/media/sample.jpg",
            "mediaType": "Image"
          },
          "navigations": [],
          "isMegaMenu": false,
          "megaMenuWithImages": false,
          "megaMenuPosition": "Horizontal",
          "banners": []
        },
        "..."
      ],
      "isMegaMenu": false,
      "megaMenuWithImages": false,
      "megaMenuPosition": "Horizontal",
      "banners": []
    },
    "..."
  ],
  "name": "Footer",
  "view": "Default",
  "section": "SectionFooter",
  "settings": {
    "showNewsletterSubcription": true,
    "socialBlock": {
      "socials": [
        {
          "link": "https://example.com/social",
          "socialName": "Sample"
        },
        "..."
      ]
    },
    "paymentMethods": [
      {
        "name": "Sample payment method",
        "image": {
          "link": "https://example.com/media/sample-payment.svg"
        }
      },
      "..."
    ],
    "id": "Component Id",
    "section": "SectionFooter",
    "type": "NoirFooter",
    "name": "Footer",
    "configuredInContentApi": true,
    "view": "Default",
    "displayName": "",
    "cssClass": "",
    "header": "",
    "alignment": "Left"
  },
  "translations": {
    "allRightsReserved": "Sample text",
    "poweredBy": "Sample text",
    "subscribeNewsletter": "Sample text",
    "...": "..."
  }
}

Required fields#

settings.id
Used for wrapper id: comp-{{ id }}.
navigations[]
Used to render the footer menu columns.

Optional fields#

settings.cssClass
Applied only when non-empty and not (UNDEFINED).
settings.showNewsletterSubcription (boolean)
If true, the newsletter subscription block is rendered.
settings.socialBlock.socials[]
If present, renders social icon links.
settings.paymentMethods[]
If present, renders accepted payment method logos.
translations.*
Used for button labels, input placeholders, accessibility labels, and newsletter messages.

JavaScript#

Global object#

The newsletter form behavior is provided by a global Alpine-ready object:
[start_code]
const footerdefault = {
validateField(field) { ... },
updateSubmissionStatus() { ... },
submitSubscribeForm() { ... }
}
[end_code]
It’s used only when the newsletter block is enabled (showNewsletterSubcription).

State fields#

errors: {}
Stores validation errors, keyed by "footer-subscribe".
isSending: false
Intended to disable the submit button while submitting (currently not used because API call is missing).
successSubmission, errorSubmission
Strings that act like flags ("show" / "hide") and drive updateSubmissionStatus().
navigations: []
Currently unused (navigation rendering is done in Liquid).
Advice
If you expand newsletter behavior, keep errors as the single source of truth for inline validation.

validateField(field)#

What it does
Validates the newsletter email input with 2 rules:
1.
required (empty → "required")
2.
email format (regex fail → "invalidEmail")
Resets this.errors = {} before validating (so only one error is shown at a time).
Sets:
this.errors["footer-subscribe"] = errorType
Adds/removes CSS classes on the input:
.invalid when invalid
.valid when valid
Returns true if valid, otherwise false.
Advice
The regex is a simple email check. If you need stricter validation, keep UX in mind (overly strict email regex often rejects valid emails).
The function toggles classes on field.closest("div"). If markup changes, validation styling may break.

updateSubmissionStatus()#

What it does
Finds success/error status elements inside the footer:
"footer .submission-status .success"
"footer .submission-status .error"
Removes show class from both.
Adds show based on:
this.successSubmission === "show"
this.errorSubmission === "show"
Advice
This method uses direct DOM queries instead of Alpine x-show for submission status. That’s okay, but it means:
changes to markup/class names must be kept in sync with this selector.
If you prefer consistency, you can replace this with Alpine-driven x-show + state only (no DOM querying).

submitSubscribeForm() (async)#

What it does
Reads the email input:
#footer-subscribe
Calls validateField(emailInput).
If valid, it currently does nothing besides a TODO comment.
There is an explicit TODO in code:
“Actual API call is missing here… For now, we will simulate a successful submission…”
Advice
Right now the newsletter form won’t actually submit anything to the backend.
If you integrate an API later, implement this pattern:
set isSending = true
try calling a service method (e.g. servicesreusabledefault.subscribeNewsletter(email))
on success: set successSubmission = "show" and clear input
on failure: set errorSubmission = "show"
finally: isSending = false
call updateSubmissionStatus()
Also consider adding toast feedback ($store.toast) for consistent theme messaging.

Global Alpine stores (used by Footer)#

The Footer component is mostly Liquid-rendered, but it does rely on one global Alpine store for a theme-wide behavior.

$store.darkMode (theme color mode)#

This store controls whether the theme is rendered in dark mode and provides the action to toggle it.
How the Footer uses it
Toggle action:
@click="$store.darkMode.toggle()"
Current state:
:aria-checked="$store.darkMode.on"
:class="{ 'active': $store.darkMode.on }"
Accessible label text switches based on the state:
:aria-label="$store.darkMode.on ? 'Disable...' : 'Enable...'"
same text also rendered via x-text inside an .sr-only element
What it means in practice
The Footer button doesn’t “own” dark mode state—changing mode affects the entire site.
Because it’s global, the same state can be toggled from other places too (header, popup, etc.), and the Footer UI stays consistent.
Notes
If $store.darkMode is not initialized in Assets/js/theme.js, the toggle will not work and Alpine will throw errors when clicking.
If you ever rename the CSS classes that implement dark mode, keep the store’s implementation in sync rather than changing Footer markup.

Dependencies#

Alpine.js (for newsletter component x-data and for dark mode toggle bindings)
Global Alpine store: $store.darkMode
GlobalData (company/settings info)
Icons CSS classes (e.g. ic-facebook, ic-instagram, etc.)

Notes#

Navigation rendering is handled in Liquid; JS does not control menus in the footer.
Newsletter submission currently has validation UI, but no backend integration.
Social links open in a new tab (target="_blank"). Consider adding rel="noopener noreferrer" if you want the strictest security posture for external links.

Extras#

Template behavior (Liquid + Alpine)#

Newsletter rendering#

Rendered only when settings.showNewsletterSubcription is truthy.
Newsletter wrapper uses:
x-data="footerdefault"
Form uses:
@submit.prevent="submitSubscribeForm()"
Shows inline field errors using:
x-show="errors['footer-subscribe'] === 'required'"
x-show="errors['footer-subscribe'] === 'invalidEmail'"
Shows submission status placeholders:
successSubmission
errorSubmission

Logo behavior#

Uses global logos (footerLogo/footerLogoLight).
If none exist, renders the company name as text.
Both logos use loading="lazy".

Navigation columns#

For each model.navigations[]:
renders a title link
renders a submenu list if nav.navigations.size > 0

Social links#

Renders icon class based on social name:
ic-{{ social.SocialName | downcase }}
Uses target="_blank" (external).

Payment methods#

Renders list of images from settings.paymentMethods[].
alt falls back to:
provided image alt OR <paymentMethod.Name> + translations.logo

Dark mode toggle#

The toggle is a switch-like button tied to the global store:
@click="$store.darkMode.toggle()"
:aria-checked="$store.darkMode.on"
:class="{ 'active': $store.darkMode.on }"
Modified at 2026-04-14 13:18:56
Previous
FilterList
Next
ForgotPassword
Built with