Building Variant Card Components in Sitecore XM Cloud with Next.js

Building Variant Card Components in Sitecore XM Cloud with Next.js

By admin August 8, 2024

As more organizations move towards headless architecture, Sitecore XM Cloud paired with Next.js offers an excellent combination for building modern, scalable websites. One of the key benefits of Sitecore XM Cloud is its ability to dynamically manage content while Next.js provides fast rendering, client-side routing, and flexibility.

In this tutorial, we’ll walk through an example of how to create reusable and dynamic card components in Sitecore XM Cloud using Next.js. We will explore different variations of the same card component: a default card, a static card, and a card with an image.

Prerequisites

To follow along, you need the following:

  • A Sitecore XM Cloud instance with JSS setup.
  • A Next.js application connected to the Sitecore XM Cloud instance.

Step 1: Define the Card Component

First, let’s define a base card component in React. This component will receive fields and params as props, which represent the content data (fields) and the rendering parameters (params) from Sitecore.

Here’s a cleaned-up version of the card component:

import React from 'react';
import { Text, Field, RichText, Image as JssImage, Link as JssLink, ImageField, LinkField } from '@sitecore-jss/sitecore-jss-nextjs';

interface Fields {
  heading: Field<string>;
  body: Field<string>;
  link: LinkField;
  image: ImageField;
  index?: number;
}

export type CardProps = {
  params: { [key: string]: string };
  fields: Fields;
  index: number;
};

const CardDefaultComponent = (props: CardProps): JSX.Element => (
  <div className={`component card ${props.params.styles}`}>
    <div className="component-content">
      <span className="is-empty-hint">Card</span>
    </div>
  </div>
);

This is a simple CardDefaultComponent that acts as a fallback when no data is available. It can be used when fields are missing or in the process of building a card variant.

Step 2: Create the Default Card Variant

In this step, we’ll create a default card variant. The card will render the heading and body from the provided Sitecore fields.

export const Default = (props: CardProps): JSX.Element => {
  const id = props.params.RenderingIdentifier;
  if (props.fields) {
    return (
      <div className={`component card ${props.params.styles}`} id={id ? id : undefined}>
        <div className="article-wrapper">
          <article>
            <div className="article-body">
              <h3>
                <Text field={props.fields.heading} />
              </h3>
              <RichText field={props.fields.body} />
            </div>
          </article>
        </div>
      </div>
    );
  }
  return <CardDefaultComponent {...props} />;
};

In this default card, we are displaying:

  • The heading as an H3 element.
  • The body as rich text (using Sitecore’s RichText component).

Step 3: Create the Static Card Variant

The static card variant will have a structured layout with a header, body, and footer. This variant is useful for cards with a more predefined and fixed structure.

export const Static = (props: CardProps): JSX.Element => {
  const id = props.params.RenderingIdentifier;
  if (props.fields) {
    return (
      <div className={`component card ${props.params.styles}`} id={id ? id : undefined}>
        <div className="card-header">
          <Text field={props.fields.heading} />
        </div>
        <div className="card-body">
          <h5 className="card-title">
            <RichText field={props.fields.body} />
          </h5>
          <div className="card-text">
            <RichText field={props.fields.body} />
          </div>
        </div>
        <div className="card-footer">Contact number:</div>
      </div>
    );
  }
  return <CardDefaultComponent {...props} />;
};

This variant adds a bit more structure by:

  • Displaying a card-header with the heading.
  • Displaying a card-body with the title and body content.
  • Adding a card-footer for additional information.

Step 4: Create the Card with Image Variant

This variant introduces an image, making it useful for cards that require a visual element along with the text content.

export const CardWithImage = (props: CardProps): JSX.Element => {
  const id = props.params.RenderingIdentifier;
  if (props.fields) {
    return (
      <div className={`component card ${props.params.styles}`} id={id ? id : undefined}>
        <div className="article-wrapper">
          <article>
            <figure>
              <JssImage field={props.fields.image} />
            </figure>
            <div className="article-body">
              <h3>
                <Text field={props.fields.heading} />
              </h3>
              <RichText field={props.fields.body} />
              <JssLink field={props.fields.link} className="read-more">
                Read more <span className="sr-only">about <Text field={props.fields.heading} /></span>
                <svg xmlns="http://www.w3.org/2000/svg" className="icon" viewBox="0 0 20 20" fill="currentColor">
                  <path fillRule="evenodd" d="M12.293 5.293a1 1 0 011.414 0l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414-1.414L14.586 11H3a1 1 0 110-2h11.586l-2.293-2.293a1 1 0 010-1.414z" clipRule="evenodd" />
                </svg>
              </JssLink>
            </div>
          </article>
        </div>
      </div>
    );
  }
  return <CardDefaultComponent {...props} />;
};

Here we:

  • Add a <figure> to display the image using JssImage from Sitecore.
  • Include a link (JssLink) to allow users to navigate to more detailed content.
  • Use an SVG icon to enhance the link visually.

Step 5: Use the Card Components in the Next.js Application

Once you’ve created these variants, you can now use them within your Next.js application. Sitecore’s JSS platform will allow you to switch between these card components dynamically based on the rendering parameters or content structure defined in Sitecore.

You can map the card component variants to Sitecore renderings and configure them from the Experience Editor. This flexibility enables you to control how each card should appear, giving marketers the ability to swap between card layouts or content effortlessly.

Live demo: https://nona-local.vercel.app/ND-Test-Page

Featured Blogs