Was this page helpful?

Register custom components

Table of contents

What are custom components?

You can import your own design system components into Experiences to create on-brand digital experiences.

After the setup in Contentful is completed, once you open the experience entry in the Contentful web app, you can see the canvas view with your page rendered in the iframe.

In this step, let’s register some custom components to further use them in Experiences.

Registering a component consists of the following steps:

  • Importing a component from the source package or folder.
  • Writing a component definition - a JSON object that Contentful uses to pass necessary properties to the component.
  • Passing the component definition to the SDK via a provided function.
Important: The source code of each registered custom component stays in your application and nothing besides the component definition (a JSON object) is sent to Contentful over postMessage. Any change made to the component source code has immediate effect on its representation in the Experiences.

Component requirements

In order to fully support Experiences, your registered components must match the following requirements:

  • Handle className property, to enable Experiences to apply styles to the instance of a registered component
  • Handle onMouseDown, onClick props. Experiences prevents native click events (to avoid unnecessary redirects)
  • Handle the following props which enable canvas interactions to function properly:
    • data-cf-node-id
    • data-cf-node-block-id
    • data-cf-node-block-type

As we develop this product, the list of required props might change, so it is recommended to register components that support props spreading as in the example below (experiencesProps):

import React, { ReactNode } from 'react';

type AnchorProps = {
  href: string;
  rel?: string;
  target?: string;
  chilren: ReactNode
};

export const Anchor = ({ href, rel, target = '_self', children, ...experiencesProps }: AnchorProps) => {
  return (
    <a href={href} rel={rel} target={target} {...experiencesProps}>
       {children}
    </a>
  );
}

Component registration

To register a custom component, import the defineComponents function directly from our side SDK:

import { defineComponents } from '@contentful/experiences-sdk-react';

import { Component1, Component2 } from '/components';
import { component1Definition, component2Definition } from '/componentDefinitions';

defineComponents([
  {
    component: Component1,
    definition: component1Definition
  },
  {
    component: Component2,
    definition: component2Definition
  }
]);

Enable tooltips for registered components

Notice how in the ComponentDefinition type that there's an optional tooltip field defined as

  tooltip?: {
    imageUrl?: string;
    description: string;
  };

When defining a tooltip, only the description is required. However, you are also able to provide your editors with a visual description of the registered component along with the description. With these options, you are enabled to customize a powerful educational experience for your users.

Defining just the description outputs a tooltip like:

Tooltip description

Providing an image URL along with a description outputs a tooltip like:

Tooltip with image

Component wrapper

Components that are registered will be encapsulated within a <div> element, serving as a wrapping container for the component.

All the styles generated from Experiences will be applied to the wrapping container instead of the component itself. This will make it so the additional styles don't interfere with your component's styles.

Disabling the wrapping container

The wrapping container can be disabled by setting the wrapComponent option to false in the component registration.

import { defineComponents } from '@contentful/experiences-sdk-react';

import { Component } from '/components';
import { componentDefinition } from '/componentDefinitions';

defineComponents([
  {
    component: Component,
    definition: componentDefinition,
    options: { wrapComponent: false }
  }
]);

Changing the wrapping container tag

The wrapping container tag can be changed by setting the wrapContainerTag option in the component registration.

import { defineComponents } from '@contentful/experiences-sdk-react';

import { Component } from '/components';
import { componentDefinition } from '/componentDefinitions';

defineComponents([
  {
    component: Component,
    definition: componentDefinition,
    options: { wrapContainerTag: 'span' }
  }
]);

Built-in components

Contentful provides some built-in basic components such as Heading, Text, Rich Text, Image, and Button. These basic components are enabled by default. If desired, you can disable these components when defining your custom components using the defineComponents function.

Disabling all built-in components

To disable all built-in components, pass an options object to defineComponents with enabledBuiltInComponents set to an empty array.

defineComponents(
  [
    /* custom component definitions */
  ],
  {
    enabledBuiltInComponents: [],
  }
);

Enabling specific built-in components

You can also choose to enable only specific built-in components. To do this, pass an array of the IDs of the components you want to enable to enabledBuiltInComponents.

In the following example, all built-in components except the Image component are enabled:

import { CONTENTFUL_COMPONENTS } from '@contentful/experiences-sdk-react';

defineComponents(
  [
    /* custom component definitions */
  ],
  {
    enabledBuiltInComponents: [
      CONTENTFUL_COMPONENTS.button.id,
      CONTENTFUL_COMPONENTS.heading.id,
      CONTENTFUL_COMPONENTS.richText.id,
      CONTENTFUL_COMPONENTS.text.id,
    ],
  }
);
The Image component is disabled in this example because its ID (CONTENTFUL_COMPONENTS.image.id) is not included in the enabledBuiltInComponents array.