ProductsSlider
A carousel block that loads products from a source you name (latest, offers, a category…) and draws a ProductCard for each.
import { ProductsSlider } from '@salla.sa/twilight-theme-engine/components/home';In plain words
You do not hand this block any products. You tell it where they come from, products: { source: 'latest' }, and it asks the Salla API for them itself, then shows them in a sliding row with an optional title and a "View All" link.
Every setting goes in one prop called data, because that is how the merchant's home page arrives from the API: one object per block. The engine's product page uses this same block for "similar products".
Signature
function ProductsSlider(props: {
data: {
products: { source: ProductsListSource; source_value?: number | number[] | null };
title?: string;
display_all_url?: string; // empty or missing: no "View All" link
position?: number; // 1: part of the element ids
priority?: boolean; // eager images for the first two cards
show_controls?: boolean;
controls_outer?: boolean;
loop?: boolean;
centered?: boolean;
slides_per_view?: number | 'auto';
direction?: 'rtl' | 'ltr';
autoplay?: boolean;
[key: string]: unknown;
};
}): JSX.ElementTry it live
import { ProductsSlider } from '@salla.sa/twilight-theme-engine/components/home';
export function NewArrivals() {
return (
<ProductsSlider
data={{
products: { source: 'latest' },
title: 'New arrivals',
display_all_url: '/products',
show_controls: true,
}}
/>
);
}
Example
import { ProductsSlider } from '@salla.sa/twilight-theme-engine/components/home';
export function NewArrivals() {
return (
<ProductsSlider
data={{
products: { source: 'latest' },
title: 'New arrivals',
display_all_url: '/latest-products',
autoplay: true,
}}
/>
);
}
How it behaves
It calls
product.list({ source, sourceValue })from@salla.sa/twilight-theme-engine/api/product(noperPage, so 16 products) insideSallaProductsSlider, in an effect. The server render shows the products skeleton; products arrive in the browser. It is not a TanStack Query, so nothing is cached or dehydrated, and each mount fetches again.ProductsListSource(from/api/product) islatest,offers,top-rated,best_selling,categories,brands,tags,selected,related,wishlist,recently,searchand a few more.source_valuecarries the ids the source needs, as an array such as[708738657]for a category.Slider options are forwarded only when set, so the slider keeps its own defaults otherwise. The "View All" label is the translation
blocks.home.display_all.priorityis read from insidedata, which is whereHomeComponentRendererputs it for the first three blocks of the home page.Not lazy, despite the
Lazy*names in the engine source: no<Suspense>of yours is needed.
Gotchas
A source with no products renders nothing at all, title included (
SallaProductsSliderreturnsnullfor an empty list). Plan the page for a missing block.The fetch reruns whenever its
loaderchanges, and the loader depends onproducts.source_value. An array written inline,source_value: [1, 2], is a new array on every render of the parent, so every parent render fetches again. Keep suchdataat module scope or inuseMemo.Element ids come from
position(best-offers-<position>-slider,slider-<position>). Two sliders with the samepositionon one page share ids; give each its own.
Related
A home block that fetches products from a source and shows up to four ProductCards in a fixed grid, with an optional title.
ProductCardThe product tile of every grid: image, badge, name, price, rating, wishlist heart and a real Add to cart button, in five layouts.
HomeComponentRendererDraws one home page block from its API data: finds its registered component, wraps it in an error boundary, and defers it until visible.