Skip to content

Conversation

TRomesh
Copy link
Contributor

@TRomesh TRomesh commented Sep 26, 2025

  • Add BaseRichTextRenderer abstract class with common rendering functions and add Types (Slate.js format).
  • Add options override default components with user defined components.
  • Add React specific implementation extending BaseRichTextRenderer`.
  • Update documentation (react) with <RichText/> usage and update sample site.

@TRomesh TRomesh requested a review from Copilot September 26, 2025 14:11
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR implements a native SDK RichText component for the Optimizely CMS SDK, providing a safe and customizable way to render rich text content from Slate.js JSON format.

  • Adds a framework-agnostic BaseRichTextRenderer abstract class with shared rendering logic
  • Implements a React-specific RichText component that extends the base renderer
  • Updates documentation and sample sites to demonstrate usage with custom element overrides

Reviewed Changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
packages/optimizely-cms-sdk/src/components/richText/ Core framework-agnostic rich text renderer with base class, types, and utilities
packages/optimizely-cms-sdk/src/react/richText/ React-specific implementation with component, renderer, and utilities
packages/optimizely-cms-sdk/src/model/properties.ts Removes outdated comment about RichText type
packages/optimizely-cms-sdk/src/infer.ts Updates type inference for RichText properties with proper JSON structure
packages/optimizely-cms-sdk/package.json Adds new export path for React richText module
samples/nextjs-template/src/components/AboutUs.tsx Demonstrates RichText component usage with custom element renderer
docs/6-rendering-react.md Updates documentation to showcase RichText component instead of dangerouslySetInnerHTML

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

@TRomesh TRomesh marked this pull request as ready for review September 29, 2025 09:11
Copy link
Contributor

@exacs exacs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This implementation looks good! I have some thoughts:

  • Can we add unit tests to check that the component works as expected?
  • Maybe in a future, we want to make a "JSX" abstraction between the React and the framework-independent layers. It would depend on how popular is JSX outside of React and if how easy/hard is to implement without using React-specific features.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good job modelling the JSON structure!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks a good 2-layer abstraction (generic & React-specific)!

> [!TIP]
> Using the `<RichText/>` component is the recommended way to render rich text content. It's safer than `dangerouslySetInnerHTML` as it doesn't rely on HTML parsing, and allows you to customize how elements are rendered with your own React components.
### Customizing Rich Text Elements
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to consider re-organizing the documentation, because right now we only have a "getting started tutorial".

My feeling is that this part is a bit too advanced for that.

Don't delete the documentation because it's very valuable :), we just need to think where to move it!

Copy link
Contributor

@JohanPetersson JohanPetersson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great. Great work!

url?: string; // common on 'link', 'image', 'video'
class?: string; // allow headless CMS to pass CSS classes
[key: string]: unknown; // custom attributes
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have any element types that we should create "super" types for? I get that this type covers all element types now, but e.g. our image and link elements might have attributes we want to have typed?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's an interesting question. If we opt to do so, we must define type as a set of constants (i.e. type: "paragraph" | "link" | "image"...). That will mean we need to know all possible values for type.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then we will have to maintain individual types like this right?.

export interface LinkElement extends BaseElement {
  type: 'link';
  url: string; // Required for links - will be mapped to href
  target?: '_blank' | '_self' | '_parent' | '_top';
  rel?: string;
  title?: string;
}
export interface ImageElement extends BaseElement {
  type: 'image';
  url: string; // Required for images - will be mapped to src
  alt?: string;
  title?: string;
  width?: number | string;
  height?: number | string;
}
export type Element =
  | GenericElement
  | LinkElement
  | ImageElement
  | TableCellElement;

I can add them since we kinda know what are the type we get from the RichText in CMS.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now we define the "super" types like LinkElement, ImageElement and its attributes. If by chance we get a type like 'unknown-element' from graph (CMS's RichText) we render it using a regular div (we can override with our own element) which is a fallback component.

@TRomesh TRomesh force-pushed the feature/CMS-45611-implement-richtext-component branch from 8b11060 to c4d2b5a Compare October 3, 2025 08:30
@TRomesh TRomesh had a problem deploying to Vercel preview environment October 3, 2025 08:30 — with GitHub Actions Failure
@TRomesh TRomesh merged commit 2fcb6b1 into main Oct 3, 2025
2 checks passed
@TRomesh TRomesh deleted the feature/CMS-45611-implement-richtext-component branch October 3, 2025 12:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants