Skip to content

Commit 45637a6

Browse files
committed
CMS-46481 Enhance RichText component documentation with detailed attribute and CSS property support, including conversion rules and examples for React compatibility.
1 parent fbc1d92 commit 45637a6

File tree

1 file changed

+295
-1
lines changed

1 file changed

+295
-1
lines changed

docs/6.1-richtext-component-react.md

Lines changed: 295 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ function Article({ content }) {
2626
>
2727
> When rich text content is created through Optimizely's Integration API (REST API) rather than the CMS editor interface, certain features may not function correctly:
2828
>
29-
> - **Inline styles** will not be processed or rendered
29+
> - **Inline styles** - Some inline CSS properties might not work as expected. See [Attribute and CSS Property Support](#attribute-and-css-property-support) for details on supported CSS properties
3030
> - **HTML validation** is bypassed, which can result in malformed or invalid HTML that causes rendering issues
3131
> - **Advanced formatting** that relies on TinyMCE editor processing may be missing
3232
> - **Custom attributes or props** might not be mapped properly from raw HTML to React components
@@ -425,6 +425,300 @@ function Article({ content }) {
425425
}
426426
```
427427

428+
## Attribute and CSS Property Support
429+
430+
The RichText component provides comprehensive support for HTML attributes and CSS properties, automatically converting them to React-compatible formats and handling styling appropriately.
431+
432+
### HTML Attributes (Converted to React Props)
433+
434+
The following HTML attributes are automatically converted to React props with proper camelCase naming:
435+
436+
#### **Form & Input Attributes**
437+
438+
- `class``className`
439+
- `for``htmlFor`
440+
- `tabindex`, `tab-index``tabIndex`
441+
- `readonly``readOnly`
442+
- `maxlength``maxLength`
443+
- `minlength``minLength`
444+
- `autocomplete``autoComplete`
445+
- `autofocus``autoFocus`
446+
- `autoplay``autoPlay`
447+
- `contenteditable`, `content-editable``contentEditable`
448+
449+
#### **Table Attributes**
450+
451+
- `colspan``colSpan`
452+
- `rowspan``rowSpan`
453+
- `cellpadding``cellPadding`
454+
- `cellspacing``cellSpacing`
455+
456+
#### **Media Attributes**
457+
458+
- `crossorigin``crossOrigin`
459+
- `usemap``useMap`
460+
- `playsinline``playsInline`
461+
- `allowfullscreen``allowFullScreen`
462+
- `frameborder``frameBorder`
463+
464+
#### **Meta Attributes**
465+
466+
- `accept-charset``acceptCharset`
467+
- `http-equiv``httpEquiv`
468+
- `charset``charSet`
469+
- `datetime``dateTime`
470+
- `hreflang``hrefLang`
471+
472+
#### **Accessibility Attributes (Preserved as-is)**
473+
474+
All ARIA attributes are preserved in their original kebab-case format as required by React:
475+
476+
- `aria-label`
477+
- `aria-labelledby`
478+
- `aria-describedby`
479+
- `aria-hidden`
480+
- `aria-expanded`
481+
- `aria-*` (all ARIA attributes)
482+
483+
#### **Data Attributes (Preserved as-is)**
484+
485+
- `data-*` (all data attributes are preserved in kebab-case)
486+
487+
### CSS Properties (Moved to Style Object)
488+
489+
CSS properties are automatically detected and moved to the React `style` object with camelCase conversion:
490+
491+
#### **Layout & Sizing**
492+
493+
- `min-width``style.minWidth`
494+
- `max-width``style.maxWidth`
495+
- `min-height``style.minHeight`
496+
- `max-height``style.maxHeight`
497+
498+
#### **Spacing**
499+
500+
- `margin`, `margin-top`, `margin-right`, `margin-bottom`, `margin-left`
501+
- `padding`, `padding-top`, `padding-right`, `padding-bottom`, `padding-left`
502+
503+
#### **Typography**
504+
505+
- `font`, `font-family`, `font-size`, `font-weight`, `font-style`, `font-variant`
506+
- `line-height`, `letter-spacing`, `word-spacing`
507+
- `text-align`, `text-decoration`, `text-transform`, `text-indent`, `text-shadow`
508+
- `vertical-align`
509+
510+
#### **Colors & Backgrounds**
511+
512+
- `color`
513+
- `background`, `background-color`, `background-image`, `background-repeat`
514+
- `background-position`, `background-size`, `background-attachment`
515+
- `background-clip`, `background-origin`
516+
517+
#### **Borders**
518+
519+
- `border-width`, `border-style`, `border-color`, `border-radius`
520+
- `border-top`, `border-right`, `border-bottom`, `border-left`
521+
- `border-*-width`, `border-*-style`, `border-*-color` (all directional variants)
522+
- `border-*-radius` (all corner variants)
523+
524+
#### **Positioning**
525+
526+
- `position`, `top`, `right`, `bottom`, `left`, `z-index`
527+
- `float`, `clear`
528+
529+
#### **Display & Visibility**
530+
531+
- `display`, `visibility`, `opacity`
532+
- `overflow`, `overflow-x`, `overflow-y`
533+
- `clip`, `clip-path`
534+
535+
#### **Flexbox**
536+
537+
- `flex`, `flex-direction`, `flex-wrap`, `flex-flow`
538+
- `justify-content`, `align-items`, `align-content`, `align-self`
539+
- `flex-grow`, `flex-shrink`, `flex-basis`
540+
541+
#### **Grid Layout**
542+
543+
- `grid`, `grid-template`, `grid-template-rows`, `grid-template-columns`
544+
- `grid-template-areas`, `grid-area`, `grid-row`, `grid-column`
545+
- `grid-gap`, `gap`, `row-gap`, `column-gap`
546+
547+
#### **Text & Content**
548+
549+
- `white-space`, `word-wrap`, `word-break`, `overflow-wrap`
550+
- `hyphens`, `text-overflow`, `direction`, `unicode-bidi`, `writing-mode`
551+
552+
#### **Visual Effects**
553+
554+
- `box-shadow`, `text-shadow`
555+
- `filter`, `backdrop-filter`
556+
- `transform`, `transform-origin`
557+
- `perspective`, `perspective-origin`
558+
559+
#### **Animation & Transitions**
560+
561+
- `transition`, `transition-property`, `transition-duration`
562+
- `transition-timing-function`, `transition-delay`
563+
- `animation`, `animation-name`, `animation-duration`
564+
- `animation-timing-function`, `animation-delay`
565+
- `animation-iteration-count`, `animation-direction`
566+
- `animation-fill-mode`, `animation-play-state`
567+
568+
#### **Interaction**
569+
570+
- `cursor`, `pointer-events`, `user-select`, `resize`
571+
572+
#### **Modern CSS**
573+
574+
- `aspect-ratio`, `object-fit`, `object-position`
575+
- `scroll-behavior`, `overscroll-behavior`
576+
- `scroll-snap-type`, `scroll-snap-align`
577+
- `scroll-margin`, `scroll-padding`
578+
579+
### Special Handling
580+
581+
#### **HTML Attributes vs CSS Properties**
582+
583+
Some properties can be both HTML attributes and CSS properties. The component intelligently handles these:
584+
585+
- **`width`, `height`**: Treated as HTML attributes for tables and images, CSS properties for other elements
586+
- **`border`**: Treated as HTML attribute for tables, CSS property for other elements
587+
588+
#### **Table-Specific Attributes**
589+
590+
Table elements receive special handling for HTML attributes:
591+
592+
```tsx
593+
// These remain as HTML attributes for tables
594+
<table border="1" cellpadding="5" cellspacing="0" width="100%">
595+
<tr>
596+
<td colspan="2" rowspan="1">
597+
Content
598+
</td>
599+
</tr>
600+
</table>
601+
```
602+
603+
#### **Style Object Conversion**
604+
605+
CSS properties are automatically converted to React style objects:
606+
607+
```tsx
608+
// Input: Slate.js node with CSS properties as attributes
609+
{
610+
type: 'div',
611+
'font-size': '16px',
612+
'background-color': 'blue',
613+
'margin-top': '10px',
614+
children: [{ text: 'Styled content' }]
615+
}
616+
617+
// Output: React element with style object
618+
<div style={{
619+
fontSize: '16px',
620+
backgroundColor: 'blue',
621+
marginTop: '10px'
622+
}}>
623+
Styled content
624+
</div>
625+
```
626+
627+
### Unsupported CSS Properties
628+
629+
While comprehensive, some advanced CSS properties are not included in the automatic detection:
630+
631+
#### **Print-Specific Properties**
632+
633+
- `page-break-before`, `page-break-after`, `page-break-inside`
634+
- `orphans`, `widows`
635+
636+
#### **Advanced Layout Features**
637+
638+
- Multi-column layout properties (`columns`, `column-count`, etc.)
639+
- CSS Masking properties (`mask`, `mask-image`, etc.)
640+
- Ruby text properties (`ruby-align`, `ruby-position`, etc.)
641+
642+
#### **Logical Properties**
643+
644+
- `margin-inline-start`, `margin-block-end`, etc.
645+
- `border-inline-start`, `border-block-end`, etc.
646+
647+
#### **CSS Custom Properties**
648+
649+
- CSS variables (`--custom-property`) are not automatically detected
650+
651+
### Extending Support
652+
653+
You can extend attribute and CSS property support by:
654+
655+
1. **Adding to CSS_PROPERTIES set** for CSS properties
656+
2. **Adding to HTML_TO_REACT_ATTRS mapping** for HTML attributes
657+
3. **Using custom element components** to handle specific cases
658+
659+
```tsx
660+
// Custom handling for unsupported properties
661+
const CustomDiv = ({ children, element, attributes }: ElementProps) => {
662+
const customStyle = {
663+
// Handle unsupported CSS properties manually
664+
'--custom-property': attributes['--custom-property'],
665+
columnCount: attributes['column-count'],
666+
};
667+
668+
return <div style={customStyle}>{children}</div>;
669+
};
670+
671+
<RichText
672+
content={content}
673+
elements={{
674+
div: CustomDiv,
675+
}}
676+
/>;
677+
```
678+
679+
### Example: Complete Attribute Handling
680+
681+
```tsx
682+
// Rich text content in Slate.js format with mixed attributes
683+
const richTextContent = {
684+
type: 'richText',
685+
children: [
686+
{
687+
type: 'div',
688+
class: 'content-block',
689+
'data-testid': 'rich-content',
690+
'aria-label': 'Article content',
691+
width: '100%', // HTML attribute for some elements
692+
'font-size': '16px', // CSS property → style.fontSize
693+
'background-color': 'lightblue', // CSS property → style.backgroundColor
694+
'margin-top': '20px', // CSS property → style.marginTop
695+
border: '1px solid #ccc', // CSS property → style.border
696+
children: [
697+
{ text: 'This content has mixed HTML attributes and CSS properties' },
698+
],
699+
},
700+
],
701+
};
702+
703+
// Rendered as:
704+
<div
705+
className="content-block"
706+
data-testid="rich-content"
707+
aria-label="Article content"
708+
width="100%"
709+
style={{
710+
fontSize: '16px',
711+
backgroundColor: 'lightblue',
712+
marginTop: '20px',
713+
border: '1px solid #ccc',
714+
}}
715+
>
716+
This content has mixed HTML attributes and CSS properties
717+
</div>;
718+
```
719+
720+
This comprehensive attribute and CSS property support ensures that rich text content from Optimizely CMS renders correctly in React applications while maintaining proper HTML semantics and React compatibility.
721+
428722
## Best Practices
429723

430724
1. **Performance**: Only override elements/leafs you need to customize

0 commit comments

Comments
 (0)