Vue Storefront is now Alokai! Learn More
Product List

Product List

The Product List module is a powerful and flexible feature designed to enhance the user experience on your e-commerce platform. It provides an alternative view for product listings on category pages, replacing the traditional grid view with a sleek and efficient list view.

Features

  • List View Display: The primary function of the "Product List" module is to present your products in a clean and organized list view. This format offers a streamlined approach to product discovery, allowing users to focus on product details without the distraction of a grid layout.
  • ProductCardListView Component: A crucial element of this module is the "ProductCardListView" component. This component is responsible for rendering each product in the list view. It provides a rich, interactive, and informative display of product information, including images, titles, prices, and other relevant details.
  • Enhanced User Experience: By offering a list view, this module caters to users who prefer a more linear and concise presentation of products.
  • Responsive Design: The "Product List" module ensures that the list view is responsive and adapts to different screen sizes and devices, maintaining a seamless shopping experience on both desktop and mobile platforms.

Installation

Add the module files

To install the module, you need an enterprise license and credentials. Contact your Customer Support Manager if you're already a customer. If you're not a customer yet, contact Alokai Sales Team.

From the root of your project run the following command:

npx @vsf-enterprise/storefront-cli add-module product-list

Follow the instructions in the command line to complete the installation. To make sure the installation is finished, go to the apps/storefront-middleware/sf-modules folder and check if there's a folder named product-list inside.

Frontend Implementation

Once installed, you will be able to use the <ProductList /> component throughout your app.

The simplest usage of this module is to replace current grid view with the module on category pages. To do so, you need to import the <ProductList /> component and pass the products array to it.

// components/products-listing/products-listing-page.tsx

import { ProductList as ProductListSection } from '@sf-modules/product-list'; // ...

export default function ProductsListingPage({...}: ProductsListingPageProps) {

  return (
    <div>
      // ...
        <ProductListSection products={products}/>        <section          className={classNames(             'col-span-full mb-10 grid grid-cols-1 gap-4 2-extra-small:grid-cols-2 lg:mb-10 lg:mt-10 lg:grid-cols-3 lg:gap-6 2xl:grid-cols-4',             hideFilters ? 'lg:col-span-full' : 'lg:col-start-2 lg:row-start-1',           )}          data-testid="category-grid"        >          {products.length === 0 && slotEmptyState}          <ProductsList products={products} />          {products.length > 0 && (             <Pagination              className="col-span-full mt-4"              currentPage={currentPage}              pageSize={pageSize ?? 24}              totalResults={totalResults}            />           )}        </section>      // ...
    </div>
  );
};

More advanced usage of the module includes a switch that allows users to toggle between grid and list views. To implement this feature without any extra UI you can use the query parameter in the URL, f.e. ?view=list. Then you can use the searchParams prop for next14 to get the value of the view parameter and conditionally render the <ProductList /> component.

// app/[locale]/(default)/category/[[...slugs]]/page.tsx

export default async function CategoryPage({ params, searchParams }: CategoryPageProps) {
  // ...
  return (
    <div className="px-4 pt-4 lg:px-0">
      // ...
      <ProductsListingPage
        // ...
        title={categoryTitle}
        searchParams={searchParams}      />
    </div>
  );
}
// components/products-listing/products-listing-page.tsx

import { ProductList as ProductListSection } from '@sf-modules/product-list'; // ...
export interface ProductsListingPageProps {  searchParams: { [key: string]: string | string[] | undefined };  // ...
}
// ...

export default function ProductsListingPage({
    // ...,
    searchParams  }: ProductsListingPageProps) {
  const listPageView = searchParams?.view === 'list'; 
  return (
    <div>
      // ...
        {listPageView ? (          <ProductListSection products={products} />        ) : (          <section
            className={classNames(
              'col-span-full mb-10 grid grid-cols-1 gap-4 2-extra-small:grid-cols-2 lg:mb-10 lg:mt-10 lg:grid-cols-3 lg:gap-6 2xl:grid-cols-4',
              hideFilters ? 'lg:col-span-full' : 'lg:col-start-2 lg:row-start-1',
            )}
            data-testid="category-grid"
          >
            {products.length === 0 && slotEmptyState}
            <ProductsList products={products} />
            {products.length > 0 && (
              <Pagination
                className="col-span-full mt-4"
                currentPage={currentPage}
                pageSize={pageSize ?? 24}
                totalResults={totalResults}
              />
            )}
          </section>
        )}
      // ...
    </div>
  );
};