Content Blocks
Web store
The contentBlocks object is a supported web store named export that
Sana expects an add-on to provide from its entry JavaScript module.
The contentBlocks object is a record whose keys are content block identifiers defined on the server,
and whose values are React components responsible for rendering the corresponding content blocks in the web store.
The contentBlocks object has the following signature:
contentBlocks?: Record<string, ContentBlock>;
Important
The key in the contentBlocks object must match the content block identifiers
defined using the ContentBlockIdAttribute in the extension classes on the server.
ContentBlock component
The ContentBlock<M> component takes as a parameter an object with props of type ContentBlockProps<M>,
where M is a generic type representing the specific content block model, defaulting to any if no custom model is provided.
The ContentBlockProps<M> type contains the following properties:
| Property | Type | Description |
|---|---|---|
| id | string | Content block unique identifier. |
| isDesignerMode | boolean | undefined | Specifies if visual designer mode is activated. |
| model | M | Content block data model. |
| fullWidthRow | boolean | Specifies if content block parent row occupies full viewport width. |
| bounds | { sm: ColumnCount; md: ColumnCount; lg: ColumnCount } | Specifies amount of columns in 12-column grid layout occupied by content block parent column. |
| styleWrapperProps | { horizontalAlignment: HorizontalAlignment } | Styles related props that can be passed to container HTML element that wraps content block. |
The bounds object contains the following properties:
| Property | Type | Description |
|---|---|---|
| sm | ColumnCount | Number of columns on devices with small screen. |
| md | ColumnCount | Number of columns on devices with medium screen. |
| lg | ColumnCount | Number of columns on devices with large and subsequent screens. |
ColumnCount is a union type that represents the number of columns in a 12-column grid layout and has the following definition:
type ColumnCount = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
The styleWrapperProps object contains the following properties:
| Property | Type | Description |
|---|---|---|
| horizontalAlignment | HorizontalAlignment | Content block text horizontal alignment. |
HorizontalAlignment is a union type that represents the horizontal alignment modes and has the following definition:
type HorizontalAlignment = 'LEFT' | 'CENTER' | 'RIGHT' | 'JUSTIFY';
Server-Side Rendering Support
Content blocks can optionally provide server-side rendering (SSR) support to preload data during the server rendering process.
For detailed information about implementing server-side rendering for content blocks, including type definitions, examples, see Server-Side Rendering.
Example
import { memo } from 'react';
import { DomHead, DomElement, DomBody } from 'sana/elements';
type Props = {
model?: {
codeContent: string | null;
headContent: string | null;
bodyEndContent: string | null;
};
};
const Code = ({ model }: Props) => {
if (!model)
return null;
const { codeContent, headContent, bodyEndContent } = model;
if (!codeContent && !headContent && !bodyEndContent)
return null;
return (
<>
{headContent && <DomHead content={headContent} />}
{codeContent && <DomElement content={codeContent} />}
{bodyEndContent && <DomBody content={bodyEndContent} />}
</>
);
};
export default memo(Code);
Admin
The contentBlocks object is a supported admin named export that
Sana expects an add-on to provide from its entry JavaScript module.
The contentBlocks object is a record whose keys are content block identifiers defined on the server,
and whose values are ContentBlock<M> objects that define how each block can be configured in Sana Admin.
The contentBlocks object has the following signature:
contentBlocks?: Record<string, ContentBlock>;
Important
The key in the contentBlocks object must match the content block identifiers
defined using the ContentBlockIdAttribute in the extension classes on the server.
This one looks the same as for the web store, but internally it's a different contract.
The ContentBlock<M> type contains the following properties:
| Property | Type | Description |
|---|---|---|
| editor | (optional) ModelEditor<M> |
The React component used to edit the content block model. |
| translator | (optional) ModelTranslator<M> |
The React component used to translate the content block model. |
| logoUrl | (optional) string |
A path or URL to the content block logo shown in the Sana Admin content block explorer. |
| defaultSettings | (optional) Partial<ContentBlockVisualSettings> |
Default visual settings applied to the content block. |
If the translator property is omitted, the content block is considered to be non-translatable.
The ContentBlockVisualSettings type contains the following properties:
| Property | Type | Description |
|---|---|---|
| minDesktopHeight | string |
Minimum height of the content block on desktop devices. |
| minTabletHeight | string |
Minimum height of the content block on tablet devices. |
| minMobileHeight | string |
Minimum height of the content block on mobile devices. |
| minDesktopWidth | string |
Minimum width of the content block on desktop devices. |
| minTabletWidth | string |
Minimum width of the content block on tablet devices. |
| minMobileWidth | string |
Minimum width of the content block on mobile devices. |
| stretchHeight | boolean |
Determines whether the content block should stretch to fill available vertical space. |
| stretchWidth | boolean |
Determines whether the content block should stretch to fill available horizontal space. |
| margin | string |
Margin. |
| padding | string |
Padding. |
| horizontalAlignment | 'LEFT' | 'CENTER' | 'RIGHT' | 'JUSTIFY' |
Content block horizontal alignment. |
| verticalSelfAlignment | 'INHERITED' | 'TOP' | 'MIDDLE' | 'BOTTOM' | 'JUSTIFY' |
Content block vertical alignment relative to neighboring elements. |
ModelEditor component
The ModelEditor<M> component is a React component used to edit the content block model properties in Sana Admin.
It takes as a parameter an object with props of type ModelEditorProps<M>,
where M is a generic type representing the specific content block model,
defaulting to any if no custom model is provided.
The ModelEditorProps<M> type contains the following properties:
| Property | Type | Description |
|---|---|---|
| initialModel | M | The initial content block model. |
| onChange | (event: ModelChangedEvent |
The callback called when the model changes. |
The ModelChangedEvent<M> type contains the following properties:
| Property | Type | Description |
|---|---|---|
| model | M | undefined | The model. |
| valid | boolean | undefined | Indicates whether the model is valid. |
| dirty | boolean | undefined | Indicates whether the model has been changed from its initial state. |
Example:
import type { ModelEditorProps } from 'sana/types';
import {
Form,
FormGroup,
TextAreaField,
} from 'sana/forms';
import { useResourceTexts } from 'sana/texts';
type Model = {
headContent: string | null;
codeContent: string | null;
bodyEndContent: string | null;
};
const CodeEditor = ({ initialModel, onChange }: ModelEditorProps<Model>) => {
const texts = useResourceTexts();
return (
<Form initialModel={initialModel} onChange={onChange}>
<FormGroup>
<TextAreaField name="headContent" label={texts.HeadContent} codeView />
</FormGroup>
<FormGroup>
<TextAreaField name="codeContent" label={texts.CodeContent} codeView />
</FormGroup>
<FormGroup>
<TextAreaField name="bodyEndContent" label={texts.BodyEndContent} codeView />
</FormGroup>
</Form>
);
};
export default CodeEditor;
ModelTranslator component
The ModelTranslator<M> component is a React component used to translate the content block model properties in Sana Admin.
It takes as a parameter an object with props of type ModelTranslatorProps<M>,
where M is a generic type representing the specific content block model,
defaulting to any if no custom model is provided.
The ModelTranslatorProps<M> type contains the following properties:
| Property | Type | Description |
|---|---|---|
| initialModel | Partial<M> | undefined |
The initial content block model. |
| onChange | (event: ModelChangedEvent<Partial<M>>) => void |
The callback called when the model changes. |
| language | TranslationLanguage |
The language being translated to. |
| defaultModel | M |
The default content block model. |
| defaultLanguage | TranslationLanguage |
The default language. |
The TranslationLanguage type contains the following properties:
| Property | Type | Description |
|---|---|---|
| id | number | The unique language identifier. |
| title | string | The language title. |
Example:
import type { ModelTranslatorProps } from 'sana/types';
import { Row, Col } from 'sana/elements';
import {
Form,
FormGroup,
TextArea,
TextAreaField,
} from 'sana/forms';
import { useResourceTexts } from 'sana/texts';
type Model = {
headContent: string | null;
codeContent: string | null;
bodyEndContent: string | null;
};
const CodeTranslator = ({ initialModel, language, defaultModel, defaultLanguage, onChange }: ModelTranslatorProps<Model>) => {
const texts = useResourceTexts();
return (
<Form initialModel={initialModel} onChange={onChange}>
<Row>
<Col>
<h5>{defaultLanguage.title}</h5>
</Col>
<Col>
<h5>{language.title}</h5>
</Col>
</Row>
<FormGroup>
<Row>
<Col>
<TextArea name="headContentDefault" label={texts.HeadContent} value={defaultModel.headContent} readOnly codeView />
</Col>
<Col>
<TextAreaField name="headContent" label={texts.HeadContent} codeView />
</Col>
</Row>
</FormGroup>
<FormGroup>
<Row>
<Col>
<TextArea name="codeContentDefault" label={texts.CodeContent} value={defaultModel.codeContent} readOnly codeView />
</Col>
<Col>
<TextAreaField name="codeContent" label={texts.CodeContent} codeView />
</Col>
</Row>
</FormGroup>
<FormGroup>
<Row>
<Col>
<TextArea name="bodyEndContentDefault" label={texts.BodyEndContent} value={defaultModel.bodyEndContent} readOnly codeView />
</Col>
<Col>
<TextAreaField name="bodyEndContent" label={texts.BodyEndContent} codeView />
</Col>
</Row>
</FormGroup>
</Form>
);
};
export default CodeTranslator;
"Generic UI" feature
If a content block does not provide a custom editor or translator,
or the Sana Admin client bundle is missing, Sana will render a generic form UI.
This UI is generated based on the System.ComponentModel.Annotations applied to the .NET content block model on the server.
The "generic UI" feature works for both the editor and translator parts and is especially useful for simple models with one-level properties, helping to reduce implementation time.
Note
The "generic UI" feature is available only in Sana Admin and is not supported for any of the web store components.