Header and footer
The Header, Footer, PageAdvertisements, Copyright and WidgetHead pieces of the master layout, and the slots you can fill.
MasterLayout is built from smaller pieces. You can place them yourself in a custom layout, or leave them alone and fill their slots.
import {
Header,
Footer,
Copyright,
WidgetHead,
PageAdvertisements,
} from '@salla.sa/twilight-theme-engine/components/layout';Header, Footer, Copyright and WidgetHead load lazily. PageAdvertisements does not, so it renders on the server without a <Suspense> boundary.
| Piece | What it is |
|---|---|
Header | The store header: the merchant's announcement bars, logo, menu, search, cart and account. |
Footer | The footer: logo and description, the store phone and email, social links, trust badges, the footer menu, app links, the copyright line and payment methods. Optional inSheet prop. |
PageAdvertisements | The merchant's announcement bars for the current page. No props. |
Copyright | A copyright line on its own, with an optional storeName prop. The footer does not use it. |
WidgetHead | Draws nothing. It runs head-level work in the browser and offers the head:start, head and head:end slots. No props. |
The footer
The engine's Footer is the shared default: the starter theme renders it as is, inside its own layout. Three things change how it looks:
- Layout: the theme setting
footer_layout.'columns'(the default) puts the brand block, the footer menu and the app links side by side.'centered'stacks everything in one centered column, with the footer menu as one inline row instead of a titled column. - Colours: the theme setting
footer_is_dark. - Text: the section titles are the translations
blocks.footer.important_linksandblocks.footer.download_apps.
It shows no contact details (phone, email). Show those your own way if your theme needs them.
Pass inSheet when you render it somewhere other than the page's footer, such as a mobile menu sheet. It then renders a <div> instead of a second <footer>, skips the footer:start and footer:end slots, and skips its footer menu.
import { Suspense } from 'react';
import { Footer } from '@salla.sa/twilight-theme-engine/layout';
export function SheetFooter() {
return (
<Suspense fallback={null}>
<Footer inSheet />
</Suspense>
);
}To change only the copyright line, register a handler for the copyright slot. It receives { storeName }, and any handler replaces the default line ("All rights reserved", the store name, the year):
import { hookRegistry } from '@salla.sa/twilight-theme-engine/hooks';
hookRegistry.register<{ storeName: string }>('copyright', ({ storeName }) => (
<>© {new Date().getFullYear()} {storeName}. All rights reserved.</>
));The announcement bar
Merchants add announcement bars in their dashboard ("free shipping this week") and choose the pages each one shows on. PageAdvertisements draws the bars that belong to the current page. The engine Header already renders it; render it yourself only in a header of your own.
import { PageAdvertisements } from '@salla.sa/twilight-theme-engine/components/layout';
export function Header() {
return (
<header>
<PageAdvertisements />
{/* the rest of your header */}
</header>
);
}- The ads load with the store settings, before the page renders, so the bar is in the server HTML and does not push the page down when it appears. If that request fails or takes more than 3 seconds, the bar loads in the browser instead.
- A bar shows when its pages list holds
allor the current page's slug. It follows client-side navigation. - A visitor who closes a bar does not see it again in that browser. Inside the theme editor every bar shows, closed or not, and inside the Salla mobile app none do.
- It uses the same classes as Salla's advertisement web component (
.s-advertisement,.s-advertisement-content,.s-advertisement-action), so you can restyle it with those.
Add content without replacing anything
The header and footer expose these slots:
| Slot | Position |
|---|---|
header:start | Before the header content |
header:end | After the header content |
footer:start | Before the footer content |
copyright | The copyright line in the footer's bottom row |
footer:end | After the footer content |
See Add content to a slot for the steps. Slots keep your changes small and your theme easy to update.
Replace the header or footer
Write your own components and use them inside your own layout:
import type { LayoutProps } from '@salla.sa/twilight-theme-engine/types';
import { Header } from './Header';
import { Footer } from './Footer';
export function ThemeLayout({ children }: LayoutProps) {
return (
<div className="app-inner flex min-h-full flex-col">
<Header />
<main id="main-content" className="flex-1">
{children}
</main>
<Footer />
</div>
);
}To replace only the header, import Footer from @salla.sa/twilight-theme-engine/layout instead of ./Footer and wrap it in <Suspense>, as the starter theme does.
Then pass the layout to the provider. See MasterLayout for the complete steps and what you must keep.