Content Blocks
Content Blocks allows developers to design autonomous and reusable UI elements that Content managers can use to build dynamic pages. This page explains how developers can use the tool we provide to create content-driven dynamic pages. With Content Blocks, Front-Commerce embraces the "Don't Ship Pages, Ship a Page Builder" vision. See how to make blocks a part of your authoring strategy.
Prerequisites
To create a Block library, you will require a library of exposed ContentTypes in your GraphQL schema.
How to use Blocks?
Integrating a Content Blocks Zones into your project is a 2 steps process:
Create a Block library
To ease the creation of a Block Library, Front-Commerce provides the
makeContentBlockLibrary
function. It allows developers to create a library of
Blocks for the GraphQL types declared with ContentTypes.
Independent components for each Block type
First, ensure that you have created one or more components for each Block type to display. Each one of them must have a GraphQL fragment defining the data they require.
A component must accept data of the fragment attached to it in props.data
.
Here is an example for a BlockTitleText
to be used the Home Block library
const BlockTitleText = (props) => {
const { subtitle, title, align = "center" } = props.data;
return (
<Container>
<div className="block-title-text">
{title && ( // we always check if the value is defined as "draft" data might not yet have the title set.
<h2 className={`block-title-text__title alignment-${align}`}>
{title}
</h2>
)}
{subtitle && ( // same here, we should always ensure it is defined before using it.
<h3 className={`block-title-text__subtitle alignment-${align}`}>
{subtitle}
</h3>
)}
</div>
</Container>
);
};
export default BlockTitleText;
and the related GraphQL fragment describing data dependencies:
fragment BlockTitleTextFragment on BlockTitleText {
title
subtitle
align
}
Then we can export these in the index.js
file of the block:
export { default as BlockTitleText } from "./BlockTitleText";
// We will also need the fragment to create the block library, explained below
export { BlockTitleTextFragmentFragmentDocument } from "~/graphql/graphql";
Define the Block library
Several components and their fragments can now be assembled together in a Block
library. Here is how to achieve this with the makeContentBlockLibrary
factory:
import { makeContentBlockLibrary } from "@front-commerce/contentful/react";
import {
BlockTitleText,
BlockTitleTextFragmentFragmentDocument,
} from "theme/modules/Blocks/BlockTitleText";
import {
BlockTextImage,
BlockTextImageFragmentFragmentDocument,
} from "theme/modules/Blocks/BlockTextImage";
// "HomePageBlock" is the name of the GraphQL union type exposing the Block Library
const blockLibrary = makeContentBlockLibrary("HomePageBlock", [
{ component: BlockTitleText, fragment: BlockTitleTextFragment },
{
component: BlockTextImage,
fragment: BlockTextImageFragmentFragmentDocument,
},
]);
// This export must be left unchanged. It allows the file to be imported
// as a Fragment in a `*.gql` file.
// The generated fragment will have the GraphQL type name, suffixed with "Fragment".
// In this example, it will be: HomePageBlockFragment
export const definitions = blockLibrary.fragmentDefinitions;
// This ContentBlock component is the one that will display data correctly
export default blockLibrary.ContentBlock;
The export const definitions
is required to allow importing this file as a
GraphQL fragment (see below).
Retrieve and display the content
Now that you have defined a Block library, you could use it wherever you need to display a BlockLibrary with these Blocks.
Let's continue our example and update our hypothetical <Home>
component to
display the Block library.
First, update the GraphQL query to add the Block library field (mainContent
in
our example)
#import "theme/modules/Blocks/Home"
query HomeQuery {
homepage {
mainContent {
...HomePageBlockFragment
}
}
}
Then, update the <Home>
component to display the content:
import HomeBlockLibrary from "theme/modules/Blocks/Home";
// […]
const Home = (props) => {
const homepageData = props.data.homepage;
return (
<div>
<h1>{homepageData.title}</h1>
<HomeBlockLibrary
content={homepageData.mainContent}
renderBlocks={(blocks) => <Stack size="8">{blocks}</Stack>}
/>
</div>
);
};
The renderBlocks
prop is optional. it allows to add a container around the
blocks. In this example, we use the Stack
component from Front-Commerce's
web/theme/components/atoms/Layout/Stack
to display the blocks vertically.
That's it! 🎉 You can now try to create new Blocks in Contentful or reorder them, and your page should reflect these changes after publication.