Skip to content
Twilight React Playground
ثيم رائدaren

FeaturedProductsStyle1, 2 and 3

componentBeginnerserverbrowserlive demo

Three featured-products home blocks: tabs with a main product, tabs that load their own products, and a large card beside small ones.

import { FeaturedProductsStyle1, FeaturedProductsStyle2, FeaturedProductsStyle3 } from '@salla.sa/twilight-theme-engine/components/home';

In plain words

Three looks for the same idea, a highlighted group of products. The API says which one a block wants with its view_style.

  • Style 1: tabs of products, with an optional large "main product" beside them. Products come inside the data.
  • Style 2: tabs where each tab loads its own products from a source, as a slider or a grid.
  • Style 3: sections with one big card for a featured product and up to three small ones. Products come inside the data.

Signature

const FeaturedProductsStyle1: MemoExoticComponent<(props: { data: {
  items: { id?: string; title?: string; name?: string; products?: Product[] }[];
  main_product?: { title?: string; product?: Product };
  [key: string]: unknown;
} }) => JSX.Element | null>

const FeaturedProductsStyle2: MemoExoticComponent<(props: { data: {
  items: { id?: string; title?: string; name?: string;
           products: { source: ProductsListSource; source_value?: number | number[]; limit?: number } }[];
  is_slider?: boolean;   // true
  [key: string]: unknown;
} }) => JSX.Element | null>

const FeaturedProductsStyle3: MemoExoticComponent<(props: { data: {
  items: { id?: string; title?: string; featured_product?: Product; products?: Product[] }[];
  [key: string]: unknown;
} }) => JSX.Element | null>

Try it live

The three featured-products blocks with real products from this store. The API picks one through the block’s view_style.Try this: style3 is the one to reach for: with the featured product it shows one large card and three small ones, and unticking it gives every product a small card. style1 keeps its tabs but draws no cards, and style2 is shown as a grid — each says why underneath.
Storefront canvas · en · LTR

Loading products…

Controls
featured / main productstyle1: main_product. style3: featured_product.
What a theme writes
import { FeaturedProductsStyle3 } from '@salla.sa/twilight-theme-engine/components/home';
import type { Product } from '@salla.sa/twilight-theme-engine/types';

export function Picks({ hero, others }: { hero: Product; others: Product[] }) {
  return (
    <FeaturedProductsStyle3
      data={{
        items: [{ id: 'picks', title: 'Staff picks', featured_product: hero, products: others }],
      }}
    />
  );
}

Example

app/components/home/Tabs.tsx
import { FeaturedProductsStyle2 } from '@salla.sa/twilight-theme-engine/components/home';

// Module scope: the same data object on every render.
const TABS = {
  is_slider: false,
  items: [
    { id: 'latest', title: 'Latest', products: { source: 'latest' as const, limit: 8 } },
    { id: 'offers', title: 'Offers', products: { source: 'offers' as const, limit: 8 } },
  ],
};

export function ProductTabs() {
  return <FeaturedProductsStyle2 data={TABS} />;
}

How it behaves

  • They are registered as featured-products:style1, :style2 and :style3, so a block needs view_style set to exactly that. With no items, each renders null.

  • Style 1 shows 4 products per tab when there is a main product, 8 otherwise. Tabs switch by id (the first item's is active); give every item a distinct id.

  • Style 2 renders ProductCards in SallaProductsSlider (default) or SallaProductsList with is_slider: false. Every tab is rendered at once and hidden with CSS, so every tab fetches when the block mounts.

  • Style 3 renders ProductCard with layout="fullImage" for featured_product and layout="minimal" for the others (the first three when a featured product exists, all otherwise), all withShadow.

Gotchas

  • Style 1 draws each product as a custom-salla-product-card element, which nothing in the engine or the reference theme defines (the Salla SDK only uses that tag when a theme defined it). In a React theme its cards are empty; prefer Style 3, or register your own component for featured-products:style1.

  • In slider mode (the default), Style 2 builds each tab's loader during render, and SallaProductsSlider fetches again whenever its loader changes: every re-render of the block, a tab click included, fetches every tab again. The grid (is_slider: false) loads once. Style 2 also reads item.products.source without a guard, so an item without products throws.

  • The demo store sends its featured block with view_style: "products_without_special_product", which none of the three keys match. See DefaultHomeComponents.

  • packages/theme-engine/docs/HOME_COMPONENTS.md spells the styles style-1, style-2 and style-3, and shows items as bare products. The registered keys are style1 to style3, and every style reads items as sections ({ id, title, products }); a block written from that page matches nothing.

Related

Source and docs