Skip to content

React JS Components

Crystallize React components

Typed React components for rendering Crystallize content: Image, Video, Grid, and Content Transformer.

Installation

Use your favorite package manager:

Terminal window
# pnpm
pnpm add @crystallize/reactjs-components
# npm
npm install @crystallize/reactjs-components
# yarn
yarn add @crystallize/reactjs-components

All components are exported from the package root and ship with TypeScript types.

import { Image, Video, GridRenderer, GridRenderingType, ContentTransformer } from '@crystallize/reactjs-components';

Image

Responsive wrapped in a with srcset support. Pass the image object you get from Crystallize.

import { Image } from '@crystallize/reactjs-components';
const imageFromCrystallize = {
url: 'https://media.crystallize.com/.../image.jpg',
altText: 'A nice product',
variants: [
// ImageVariant[] from @crystallize/schema
{ url: '.../image@400.jpg', width: 400 },
{ url: '.../image@700.jpg', width: 700 },
{ url: '.../image@1000.webp', width: 1000 },
],
};
export function ProductImage() {
return <Image {...imageFromCrystallize} sizes="(max-width: 600px) 90vw, 700px" className="product-image" />;
}

Notes

  • If the API returns caption in json/html/plainText, the component renders it as
    .
  • You can provide width/height to avoid layout shift; otherwise the largest variant’s dimensions are used when available.

Live demo: https://crystallizeapi.github.io/libraries/reactjs-components/image

Video

Progressive video player that prefers HLS (m3u8) and falls back to MPEG-DASH (mpd). Renders a thumbnail and a play button, then hydrates the player.

Important

  • This component is client-side only (it contains ‘use client’). In Next.js, place it in a client component.
  • Include the provided styles once in your app:
import '@crystallize/reactjs-components/assets/video/styles.css';

Usage

import { Video } from '@crystallize/reactjs-components';
const videoFromCrystallize = {
playlists: ['https://media.crystallize.com/.../master.m3u8', 'https://media.crystallize.com/.../stream.mpd'],
thumbnails: [
{
url: 'https://media.crystallize.com/.../thumb.jpg',
variants: [{ url: '.../thumb@700.jpg', width: 700 }],
},
],
};
export function HeroVideo() {
return (
<Video
{...videoFromCrystallize}
autoPlay
muted
controls
className="hero-video"
videoProps={{ playsInline: true }}
/>
);
}

Live demo: https://crystallizeapi.github.io/libraries/reactjs-components/video

Grid

Render Crystallize grids in React using CSS Grid (default), a semantic table, or row/col wrappers.

Fetch the grid via GraphQL (minimum shape shown):

query grid($id: Int!, $language: String!) {
grid(id: $id, language: $language) {
rows {
columns {
layout {
rowspan
colspan
colIndex
rowIndex
}
item {
name
}
}
}
}
}

Render

import { GridRenderer, GridRenderingType } from '@crystallize/reactjs-components';
const Cell = ({ cell }: { cell: any }) => <div>{cell.item?.name}</div>;
<>
{/* CSS Grid */}
<GridRenderer grid={grid} type={GridRenderingType.Div} cellComponent={Cell} />
{/* Table */}
<GridRenderer grid={grid} type={GridRenderingType.Table} cellComponent={Cell} />
{/* Row/Col wrappers */}
<GridRenderer grid={grid} type={GridRenderingType.RowCol} cellComponent={Cell} />
</>;

Customize per cell via a render-prop or styleForCell

<GridRenderer grid={grid} type={GridRenderingType.Div} cellComponent={Cell}>
{({ cells }) =>
cells.map((cell) => (
<div
key={`${cell.layout.rowIndex}-${cell.layout.colIndex}`}
style={{ gridColumn: `span ${cell.layout.colspan}`, gridRow: `span ${cell.layout.rowspan}` }}
>
{cell.item.name}
</div>
))
}
</GridRenderer>

Live demo: https://crystallizeapi.github.io/libraries/reactjs-components/grid

Content Transformer

Render Crystallize rich text JSON to React elements with optional per-node overrides.

import { ContentTransformer, NodeContent, type Overrides, type NodeProps } from '@crystallize/reactjs-components';
const overrides: Overrides = {
link: (props: NodeProps) => (
<a href={props.metadata?.href} rel={props.metadata?.rel} target={props.metadata?.target}>
<NodeContent {...props} />
</a>
),
};
<ContentTransformer json={richTextJson} overrides={overrides} />;

Live demo: https://crystallizeapi.github.io/libraries/reactjs-components/content-transformer

Notes on SSR

  • Image, Grid, and Content Transformer are SSR-friendly.
  • Video must run on the client. In Next.js, put the usage in a Client Component.

License

MIT © Crystallize


Crystallize Librairies are distributed under the MIT License.