HookSlot

Mark a place in a layout or page where handlers, installed apps and your own code can add content.

Use HookSlot when you want others (or you, later) to inject content at a spot without editing that component. It renders whatever was registered under its name with useHook, and nothing when nothing was.

Example

app/components/layout/Header.tsx
import { HookSlot } from '@salla.sa/twilight-theme-engine/hooks/HookSlot';

export function Header() {
  return (
    <header>
      <HookSlot name="header:start" />
      <nav>{/* ... */}</nav>
      <HookSlot name="header:end" />
    </header>
  );
}

Add one rule to your global CSS so the element the slot renders for installed apps takes no space:

app/styles/app.css
salla-hook { all: unset; display: none; }

API

function HookSlot(props: HookSlotProps): JSX.Element | null;
PropTypeDescription
nameHookName | stringSlot name: a HookName value or any string. Required.
context?Record<string, unknown>Extra data passed to every handler.
fallback?ReactNodeRendered when no handler is registered for this name. Default: null.
ssr?booleanAlso render the app element during server rendering. Default: false. The engine sets it for its <head> slots.

A handler receives your context plus twilight: the full Twilight context (store, theme, currency and more).

Slots the engine already renders

The engine renders about 80 slots across the page frame, the storefront pages, the cart, the account area and the blog. Slots overview lists them all, with where each one sits on its page and the context it passes.

Each of them has a HookName member (86 in all), so HookName.PRODUCT_START and 'product:start' name the same slot. A few members name slots no engine page renders: BODY_INNER, HEAD_INNER, the four SEARCH_* and the three HOMEPAGE_*. A handler there shows nothing until you render that HookSlot yourself.

Gotchas

  • Handlers run in priority order, highest first, and their results render one after another.
  • A handler that throws renders nothing. The error is logged in development only.
  • Besides your handlers, the slot renders a <salla-hook> element where apps installed on the store inject their content. It is client-only by default to avoid a hydration mismatch.
  • The slot re-renders when handlers are registered, removed or cleared for its name.
  • It passes only your context and twilight. It does not read ProductContextProvider or CartContextProvider, so pass the product or cart yourself: context={{ product }}.

Next

On this page