diff --git a/docs/source/_static/add-document.svg b/docs/source/_static/add-document.svg
new file mode 100644
index 0000000000..29594b298e
--- /dev/null
+++ b/docs/source/_static/add-document.svg
@@ -0,0 +1,6 @@
+
diff --git a/docs/source/_static/pen.svg b/docs/source/_static/pen.svg
new file mode 100644
index 0000000000..3c535f378e
--- /dev/null
+++ b/docs/source/_static/pen.svg
@@ -0,0 +1,3 @@
+
diff --git a/docs/source/blocks/anatomy.md b/docs/source/blocks/anatomy.md
index 4c17b89ce9..4ac83fa9d9 100644
--- a/docs/source/blocks/anatomy.md
+++ b/docs/source/blocks/anatomy.md
@@ -82,7 +82,7 @@ You can use all these props to render your edit block and model its behavior.
Volto later then 16.0.0 ships with a set of default Edit and View components.
The view component is mostly a placeholder, with an auto-generated listing of
the block fields, while the default Edit component is the most interesting, as
-it can use the `schema` that you can specify in the block configuration to
+it can use the `blockSchema` that you can specify in the block configuration to
automatically render a form for the Block settings, in the Volto Sidebar. In
the main editing area, it will render the view component, so for many blocks
you can just develop a schema and the View component.
diff --git a/docs/source/blocks/editcomponent.md b/docs/source/blocks/editcomponent.md
index d1f0191711..46b52a1831 100644
--- a/docs/source/blocks/editcomponent.md
+++ b/docs/source/blocks/editcomponent.md
@@ -11,7 +11,7 @@ myst:
The edit component part of a block anatomy is specially different to the view component because they have to support the UX for editing the block.
This UX can be very complex depending on the kind of block and the feature that it is trying to provide.
-The project requirements will tell how far you should go with the UX story of each tile, and how complex it will become.
+The project requirements will tell how far you should go with the UX story of each block, and how complex it will become.
You can use all the props that the edit component is receiving to model the UX for the block and how it will render.
See the complete list of {ref}`block-edit-component-props-label`.
@@ -28,22 +28,36 @@ You need to instantiate it this way:
```jsx
import { SidebarPortal } from '@plone/volto/components';
-[...]
+const Edit = (props) => {
+ const { selected } = props;
+ return (
+
+ [...]
-
- // ...
-
+
+ // ...
+
+ )
+
+}
```
Everything that's inside the `SidebarPortal` component will be rendered in the sidebar. If you need an extra layer of configuration within `SidebarPortal`, you can use `SidebarPopup`.
```jsx
-
import { SidebarPopup } from '@plone/volto/components';
-
- ...
-
+const Edit = (props) => {
+ const { sidebarOpen } = props;
+
+ return (
+ [...]
+
+
+ ...
+
+ )
+}
```
## Schema driven automated block settings forms
@@ -107,24 +121,30 @@ import schema from './schema';
import BlockDataForm from '@plone/volto/components/manage/Form/BlockDataForm';
import { Icon } from '@plone/volto/components';
-
- }
- schema={schema}
- title={schema.title}
- headerActions={}
- footer={
}
+ onChangeField={(id, value) => {
+ onChangeBlock(block, {
+ ...data,
+ [id]: value,
+ });
+ }}
+ onChangeBlock={onChangeBlock}
+ formData={data}
+ block={block}
+ />
+ ;
+ )
+}
```
## Object Browser
diff --git a/docs/source/blocks/examples/custom-schema-and-view.md b/docs/source/blocks/examples/custom-schema-and-view.md
new file mode 100644
index 0000000000..cf099fc554
--- /dev/null
+++ b/docs/source/blocks/examples/custom-schema-and-view.md
@@ -0,0 +1,154 @@
+---
+myst:
+ html_meta:
+ 'description': 'Volto block with custom schema and view components'
+ 'property=og:description': 'Volto block with custom schema and view components'
+ 'property=og:title': 'Volto block with custom schema and view components'
+ 'keywords': 'Volto, React, blocks, grid, container, Plone'
+---
+
+(custom-schema-and-view)=
+
+# Block with a custom schema
+
+You can create a block with several settings defined using a schema, and let Volto render the edit form by itself.
+
+To do so, define the schema, the view component, and configure the block settings.
+
+## Preparations
+
+In your Volto add-on, create a subfolder {file}`ExampleBlock01` inside the {file}`components` folder to save all the files required to create a block.
+
+## Schema
+
+Create a {file}`Schema.js` file inside the {file}`ExampleBlock01` folder, with the following contents.
+
+```js
+import messages from './messages';
+
+const Schema = ({ intl }) => {
+ return {
+ title: intl.formatMessage(messages.block01),
+ block: 'block01',
+ fieldsets: [
+ {
+ id: 'default',
+ title: intl.formatMessage(messages.default),
+ fields: ['url', 'title'],
+ },
+ ],
+
+ properties: {
+ url: {
+ title: intl.formatMessage(messages.URL),
+ widget: 'url',
+ },
+ title: {
+ title: intl.formatMessage(messages.title),
+ },
+ },
+ required: [],
+ };
+};
+
+export default Schema;
+```
+
+## Messages
+
+As you may have noted, you prepared the block for internationalization.
+{term}`Internationalization` (i18n) is the process of creating user interfaces which are suitable for different languages and cultural contexts.
+To add translatable messages, create a file {file}`messages.js` in the same {file}`ExampleBlock01` folder with the following contents.
+
+```js
+import { defineMessages } from 'react-intl';
+
+const messages = defineMessages({
+ block01: {
+ id: 'block01',
+ defaultMessage: 'Block 01',
+ },
+ default: {
+ id: 'default',
+ defaultMessage: 'Default',
+ },
+ URL: {
+ id: 'URL',
+ defaultMessage: 'URL',
+ },
+ title: {
+ id: 'title',
+ defaultMessage: 'Title',
+ },
+});
+
+export default messages;
+```
+
+## View component
+
+The view component will have all the required logic to show the information saved on the block.
+It will be a small HTML fragment.
+
+Create a file {file}`View.jsx` in the {file}`ExampleBlock01` folder with the following contents.
+
+```jsx
+import cx from 'classnames';
+import React from 'react';
+
+const View = (props) => {
+ // - `data` holds the values entered in the block edit form.
+ // - `className` holds the CSS class names injected into this block
+ // by Volto's `styleClassNameExtenders`.
+ // - `style` holds the CSS properties injected into this block
+ // by Volto's `Block Style Wrapper`.
+ const { data, className, style } = props;
+ return (
+
+ I am the Block view component!
+
+
Title: {data.title}
+
URL: {data.url}
+
+
+ );
+};
+
+export default View;
+```
+
+## Block configuration
+
+With all the block components ready, you need to register the block into Volto.
+
+To do so, open your add-on's {file}`index.js` file, and insert the following contents before the last `return config;` statement.
+
+```js
+config.blocks.blocksConfig.block01 = {
+ id: 'block01', // this is the block id, it must match the id on the previous line
+ title: 'Block 01', // this is the block title
+ view: View01, // this is the block's view component
+ // We do not need a specific edit component, Volto will use the default
+ // edit: null;
+ blockSchema: Schema01, // this is the schema that will be used to render the edit form
+ icon: imagesSVG, // this is the image that will be shown in the block selector
+ sidebarTab: 1, // this is set to 1 to have the `Block` tab selected in the sidebar
+ // editor when editing this block
+};
+```
+
+At the top of the file, import the relevant components as follows.
+
+```js
+import View01 from './components/ExampleBlock01/View';
+import Schema01 from './components/ExampleBlock01/Schema';
+
+// This is the icon we use for the example, use a meaningful one or provide your own image.
+import imagesSVG from '@plone/volto/icons/images.svg';
+```
+
+## See it in action
+
+Your block is ready to be used in your site.
+
+Restart your Volto site, and now you can add the new block from the block chooser found in the {guilabel}`Edit` or {guilabel}`Add` content views.
diff --git a/docs/source/blocks/examples/custom-schema-view-and-edit.md b/docs/source/blocks/examples/custom-schema-view-and-edit.md
new file mode 100644
index 0000000000..a5fd7d57e1
--- /dev/null
+++ b/docs/source/blocks/examples/custom-schema-view-and-edit.md
@@ -0,0 +1,212 @@
+---
+myst:
+ html_meta:
+ "description": "Volto block with custom schema and edit components"
+ "property=og:description": "Volto block with custom schema and edit components"
+ "property=og:title": "Volto block with custom schema and edit components"
+ "keywords": "Volto, React, blocks, custom, schema, edit, component, Plone"
+---
+
+(custom-schema-edit-and-view)=
+
+# Block with a custom schema and edit components
+
+You can create a block with several settings defined using a schema, and write a custom edit form instead of using the one provided by Volto.
+
+To do so, define the schema, the view component, the edit component, and configure the block settings.
+
+## Preparations
+
+In your Volto add-on, create a subfolder {file}`ExampleBlock02` inside the {file}`components` folder to save all the files required to create a block.
+
+## Schema
+
+Create a {file}`Schema.js` file inside the {file}`ExampleBlock02` folder, with the following contents.
+
+```js
+import messages from './messages';
+
+const Schema = ({ intl }) => {
+ return {
+ title: intl.formatMessage(messages.block02),
+ block: 'block02',
+ fieldsets: [
+ {
+ id: 'default',
+ title: intl.formatMessage(messages.default),
+ fields: ['url', 'title'],
+ },
+ ],
+
+ properties: {
+ url: {
+ title: intl.formatMessage(messages.URL),
+ widget: 'url',
+ },
+ title: {
+ title: intl.formatMessage(messages.title),
+ },
+ },
+ required: [],
+ };
+};
+
+export default Schema;
+```
+
+## Messages
+
+As you may have noted, you prepared the block for internationalization.
+{term}`Internationalization` (i18n) is the process of creating user interfaces which are suitable for different languages and cultural contexts.
+To add translatable messages, create a file {file}`messages.js` in the same {file}`ExampleBlock02` folder with the following contents.
+
+```js
+import { defineMessages } from 'react-intl';
+
+const messages = defineMessages({
+ block02: {
+ id: 'block02',
+ defaultMessage: 'Block 02',
+ },
+ default: {
+ id: 'default',
+ defaultMessage: 'Default',
+ },
+ URL: {
+ id: 'URL',
+ defaultMessage: 'URL',
+ },
+ title: {
+ id: 'title',
+ defaultMessage: 'Title',
+ },
+});
+
+export default messages;
+```
+
+## View component
+
+The view component will have all the required logic to show the information saved on the block.
+It will be a small HTML fragment.
+
+Create a file {file}`View.jsx` in the {file}`ExampleBlock02` folder with the following contents.
+
+```jsx
+import cx from 'classnames';
+import React from 'react';
+
+const View = (props) => {
+ // - `data` holds the values entered in the block edit form.
+ // - `className` holds the CSS class names injected into this block
+ // by Volto's `styleClassNameExtenders`.
+ // - `style` holds the CSS properties injected into this block
+ // by Volto's `Block Style Wrapper`.
+ const { data, className, style } = props;
+ return (
+
+ I am the Block view component!
+
+
Title: {data.title}
+
URL: {data.url}
+
+
+ );
+};
+
+export default View;
+```
+
+## Edit component
+
+The edit component renders a form where the editor can change the block settings.
+This edit component is a minimal component that renders the block and the same edit form as the one rendered automatically.
+
+Create a file {file}`Edit.jsx` in the {file}`ExampleBlock02` folder with the following contents.
+
+```jsx
+
+// manually import the schema
+import schema from './Schema';
+import BlockDataForm from '@plone/volto/components/manage/Form/BlockDataForm';
+import { SidebarPortal } from '@plone/volto/components';
+// The edit component also renders the view of the block,
+// not only the form.
+// So you must import the view component that you just wrote
+// to render its contents.
+import View from './View';
+
+
+const Edit = (props) => {
+ const { onChangeBlock, block, data, selected, className, style } = props;
+
+ // The schema is a function. Call it to get its definition.
+ const blockSchema = schema(props);
+
+ return (
+ <>
+
+
+
+ {
+ onChangeBlock(block, {
+ ...data,
+ [id]: value,
+ });
+ }}
+ onChangeBlock={onChangeBlock}
+ formData={data}
+ block={block}
+ />
+
+ >
+ );
+};
+
+export default Edit;
+```
+
+## Block configuration
+
+With all the block components ready, you need to register the block into Volto.
+
+To do so, open your add-on's {file}`index.js` file, and insert the following contents before the last `return config;` statement.
+
+```js
+config.blocks.blocksConfig.block02 = {
+ id: 'block02', // this is the block id, it must match the id on the previous line
+ title: 'Block 02', // this is the block title
+ view: View02, // this is the block's view component
+ edit: Edit02, // this is the block's edit component
+ // You do not need to define the schema here,
+ // because you are using a custom edit component
+ // blockSchema: Schema02,
+
+ // this is the image that will be shown in the block selector
+ icon: imagesSVG,
+ // this is set to 1, which selects the `Block` tab in the sidebar editor
+ // when editing this block
+ sidebarTab: 1,
+ };
+```
+
+At the top of the file, import the relevant components as follows.
+
+```js
+import View02 from './components/ExampleBlock02/View';
+import Edit02 from './components/ExampleBlock02/Edit';
+import Schema02 from './components/ExampleBlock02/Schema';
+
+// This is the icon to use for this example.
+// Use a meaningful one or provide your own image.
+import imagesSVG from '@plone/volto/icons/images.svg';
+```
+
+## See it in action
+
+Your block is ready to use in your site.
+
+Restart your Volto site, and now you can add the new block from the block chooser found in the {guilabel}`Edit` or {guilabel}`Add` content views.
diff --git a/docs/source/blocks/examples/custom-view-and-variations.md b/docs/source/blocks/examples/custom-view-and-variations.md
new file mode 100644
index 0000000000..5fc95e3e97
--- /dev/null
+++ b/docs/source/blocks/examples/custom-view-and-variations.md
@@ -0,0 +1,239 @@
+---
+myst:
+ html_meta:
+ 'description': 'Volto block with custom schema and view components using variations'
+ 'property=og:description': 'Volto block with custom schema and view components using variations'
+ 'property=og:title': 'Volto block with custom schema and view components using variations'
+ 'keywords': 'Volto, React, blocks, schema, variation, view component, Plone'
+---
+
+(custom-schema-view-and-variations)=
+
+# Block with a custom schema and variations
+
+We can create a block that uses `variations`.
+A {term}`variation` is an alternative view of a block.
+This variation is shown as an additional option in the block settings sidebar and lets the editor change how this block is rendered.
+
+To do so, define the schema, view component, and variations, then configure the block settings.
+
+## Preparations
+
+In your Volto add-on, create a subfolder {file}`ExampleBlock03` inside the {file}`components` folder to save all the files required to create a block and its variations.
+
+## Schema
+
+Create a {file}`Schema.js` file inside the {file}`ExampleBlock03` folder, with the following contents.
+
+```js
+import messages from './messages';
+
+const Schema = ({ intl }) => {
+ return {
+ title: intl.formatMessage(messages.block03),
+ block: 'block03',
+ fieldsets: [
+ {
+ id: 'default',
+ title: intl.formatMessage(messages.default),
+ fields: ['url', 'title'],
+ },
+ ],
+
+ properties: {
+ url: {
+ title: intl.formatMessage(messages.URL),
+ widget: 'url',
+ },
+ title: {
+ title: intl.formatMessage(messages.title),
+ },
+ },
+ required: [],
+ };
+};
+
+export default Schema;
+```
+
+## Messages
+
+As you may have noted, you prepared the block for internationalization.
+{term}`Internationalization` (i18n) is the process of creating user interfaces which are suitable for different languages and cultural contexts.
+
+To do so, create a file {file}`messages.js` in the same {file}`ExampleBlock03` folder with the following contents.
+
+```js
+import { defineMessages } from 'react-intl';
+
+const messages = defineMessages({
+ block03: {
+ id: 'block03',
+ defaultMessage: 'Block 03',
+ },
+ default: {
+ id: 'default',
+ defaultMessage: 'Default',
+ },
+ URL: {
+ id: 'URL',
+ defaultMessage: 'URL',
+ },
+ title: {
+ id: 'title',
+ defaultMessage: 'Title',
+ },
+});
+
+export default messages;
+```
+
+## View component
+
+For variations, the view component needs to use the variation template to render the contents of the block.
+You can do so using the `variation` from the `props` of the block.
+
+Create a file {file}`View.jsx` in the {file}`ExampleBlock03` folder with the following contents.
+
+```jsx
+import withBlockExtensions from '@plone/volto/helpers/Extensions/withBlockExtensions';
+import cx from 'classnames';
+import React from 'react';
+
+const View = (props) => {
+ // - `data` holds the values entered in the block edit form.
+ // - `className` holds the CSS class names injected into this block
+ // by Volto's `styleClassNameExtenders`.
+ // - `style` holds the CSS properties injected into this block
+ // by Volto's `Block Style Wrapper`.
+ // - `variation` holds the variation selected in the block editor,
+ // and it is an object as defined in the block configuration.
+ const { data, className, style, variation } = props;
+
+ const BodyTemplate = variation?.template;
+
+ return (
+
+
+
+ );
+};
+
+export default withBlockExtensions(View);
+```
+
+The `withBlockExtensions` {term}`HOC` makes the variation selector available in the block edit form and provides the `variation` property in the props.
+
+## Variations
+
+Next create one or more variations that will be available for this block.
+
+Create a file {file}`VariationView01.jsx` in the {file}`ExampleBlock03` folder with the following contents.
+
+```jsx
+import React from 'react';
+
+const View = (props) => {
+ const { data } = props;
+ return (
+ <>
+
Variation View 01
+
+
+
Title: {data.title}
+
URL: {data.url}
+
+
+ >
+ );
+};
+
+export default View;
+```
+
+Create a file {file}`VariationView02.jsx` in the {file}`ExampleBlock03` folder with the following contents.
+
+```jsx
+import React from 'react';
+
+const View = (props) => {
+ const { data } = props;
+ return (
+ <>
+
Variation View 02
+
+
+
Title: {data.title}
+
URL: {data.url}
+
+
+ >
+ );
+};
+
+export default View;
+```
+
+As you can see in this basic example, the variations are pretty much the same.
+The only difference is the text that is rendered in the `
` tag.
+But it can be anything.
+
+## Block configuration
+
+With all the block components ready, you need to register the block into Volto.
+
+To do so, open your add-on's {file}`index.js` file, and insert the following contents before the last `return config;` statement.
+
+```js
+config.blocks.blocksConfig.block03 = {
+ id: 'block03', // this is the block id, it must match the id on the previous line
+ title: 'Block 03', // this is the block title
+ view: View03, // this is the block's view component
+ // We do not need a specific edit component, Volto will use the default
+ // edit: null,
+ blockSchema: Schema03, // this is the schema that will be used to render the edit form
+ icon: imagesSVG, // this is the image that will be shown in the block selector
+ sidebarTab: 1, // this is set to 1 to have the `Block` tab selected in the sidebar
+ // editor when editing this block these are the variations available for this block
+ variations: [
+ {
+ id: 'variation01', // this is the id of the variation
+ title: 'Variation 01', // this is the title of the variation
+ isDefault: true, // this signals if this is the default variation for this block
+ template: VariationView0301, // this is the component that will render the variation
+ },
+ {
+ id: 'variation02',
+ title: 'Variation 02',
+ isDefault: false,
+ template: VariationView0302,
+ },
+ ],
+};
+```
+
+At the top of the file, import the relevant components as follows.
+
+```js
+import View03 from './components/ExampleBlock03/View';
+import Schema03 from './components/ExampleBlock03/Schema';
+import VariationView0301 from './components/ExampleBlock03/VariationView01';
+import VariationView0302 from './components/ExampleBlock03/VariationView02';
+
+// This is the icon we use for the example, use a meaningful one or provide your own image.
+import imagesSVG from '@plone/volto/icons/images.svg';
+```
+
+## See it in action
+
+Your block is ready to be used in your site.
+
+Restart your Volto site, and now you can add the new block from the block chooser found in the {guilabel}`Edit` or {guilabel}`Add` content views.
diff --git a/docs/source/blocks/examples/custom-view-variations-and-schema-enhancer.md b/docs/source/blocks/examples/custom-view-variations-and-schema-enhancer.md
new file mode 100644
index 0000000000..90f6ffebe0
--- /dev/null
+++ b/docs/source/blocks/examples/custom-view-variations-and-schema-enhancer.md
@@ -0,0 +1,278 @@
+---
+myst:
+ html_meta:
+ 'description': 'Volto block with custom schema and view components using variations and a schema enhancer in one of the variations'
+ 'property=og:description': 'Volto block with custom schema and view components using variations and a schema enhancer in one of the variations'
+ 'property=og:title': 'Volto block with custom schema, variations, and schema enhancer'
+ 'keywords': 'Volto, React, blocks, variation, custom, schema, enhancer, Plone'
+---
+
+(custom-schema-view-variations-schema-enhancer)=
+
+# Block with a custom schema, variations, and a schema enhancer in a variation
+
+This example builds upon the previous example, {doc}`custom-view-and-variations`, where you can create a block with a custom schema, variations, and a schema enhancer in one of the variations.
+A {term}`variation` is an alternative view of a block.
+The variation is shown as an additional option in the schema editor, and lets the editor change how this block is viewed.
+
+A {term}`schema enhancer` is an option of a variation.
+Using this schema enhancer, you can extend the block schema to have additional fields.
+
+To do so, define the schema, view component, variations, and schema enhancer, then configure the block settings.
+
+## Preparations
+
+In your Volto add-on, create a subfolder {file}`ExampleBlock04` inside the {file}`components` folder to save all the files required to create a block, its variations, and the schema enhancer.
+
+## Schema
+
+Create a {file}`Schema.js` file inside the {file}`ExampleBlock04` folder, with the following contents.
+
+```js
+import messages from './messages';
+
+const Schema = ({ intl }) => {
+ return {
+ title: intl.formatMessage(messages.block04),
+ block: 'block04',
+ fieldsets: [
+ {
+ id: 'default',
+ title: intl.formatMessage(messages.default),
+ fields: ['url', 'title'],
+ },
+ ],
+
+ properties: {
+ url: {
+ title: intl.formatMessage(messages.URL),
+ widget: 'url',
+ },
+ title: {
+ title: intl.formatMessage(messages.title),
+ },
+ },
+ required: [],
+ };
+};
+
+export default Schema;
+```
+
+## Messages
+
+As you may have noted, you prepared the block for internationalization.
+{term}`Internationalization` (i18n) is the process of creating user interfaces which are suitable for different languages and cultural contexts.
+
+Create a file {file}`messages.js` in the same {file}`ExampleBlock04` folder with the following contents.
+
+```js
+import { defineMessages } from 'react-intl';
+
+const messages = defineMessages({
+ block04: {
+ id: 'block04',
+ defaultMessage: 'Block 04',
+ },
+ default: {
+ id: 'default',
+ defaultMessage: 'Default',
+ },
+ URL: {
+ id: 'URL',
+ defaultMessage: 'URL',
+ },
+ title: {
+ id: 'title',
+ defaultMessage: 'Title',
+ },
+ color: {
+ id: 'color',
+ defaultMessage: 'Color',
+ },
+});
+
+export default messages;
+```
+
+## View component
+
+For variations, the view component needs to use the variation template to render the contents of the block.
+
+You can do so using the `variation` from the `props` of the block.
+
+Create a file {file}`View.jsx` in the {file}`ExampleBlock04` folder with the following contents.
+
+```jsx
+import withBlockExtensions from '@plone/volto/helpers/Extensions/withBlockExtensions';
+import cx from 'classnames';
+import React from 'react';
+
+const View = (props) => {
+ // - `data` holds the values entered in the block edit form.
+ // - `className` holds the CSS class names injected into this block
+ // by Volto's `styleClassNameExtenders`.
+ // - `style` holds the CSS properties injected into this block
+ // by Volto's `Block Style Wrapper`.
+ // - `variation` holds the variation selected in the block editor,
+ // and it is an object as defined in the block configuration.
+ const { data, className, style, variation } = props;
+
+ const BodyTemplate = variation?.template;
+
+ return (
+
+
+
+ );
+};
+
+export default withBlockExtensions(View);
+```
+
+The `withBlockExtensions` {term}`HOC` makes the variation selector available in the block edit form and provides the `variation` property in the props.
+
+## Schema enhancer
+
+Next you need to configure the schema enhancer function.
+In this example, you will add a new field named `color` when using `schemaEnhancerVariation02`.
+
+Create a file {file}`enhancers.js` in the {file}`BlockSchema04` folder with the following content:
+
+```js
+import messages from './messages';
+
+const schemaEnhancerVariation02 = ({ formData, schema, intl }) => {
+ // schema holds the original schema (see the Schema.js file)
+ // so you need to define the new property under `schema.properties`
+ // and push its name to the relevant fieldset, in this case the first one
+ // (note the `fieldsets[0]`)
+ schema.properties.color = {
+ title: intl.formatMessage(messages.color),
+ };
+ schema.fieldsets[0].fields.push('color');
+ return schema;
+};
+
+export default schemaEnhancerVariation02;
+```
+
+## Variations
+
+Next create one or more variations that will be available for this block.
+
+Create a file {file}`VariationView01.jsx` in the {file}`ExampleBlock04` folder with the following contents.
+
+```jsx
+import React from 'react';
+
+const View = (props) => {
+ const { data } = props;
+ return (
+ <>
+
Variation View 01
+
+
+
Title: {data.title}
+
URL: {data.url}
+
+
+ >
+ );
+};
+
+export default View;
+```
+
+Create a file {file}`VariationView02.jsx` in the {file}`ExampleBlock04` folder with the following contents.
+
+```jsx
+import React from 'react';
+
+const View = (props) => {
+ const { data } = props;
+ return (
+ <>
+
Variation View 02
+
+
+
Title: {data.title}
+
URL: {data.url}
+
Color: {data.color}
+
+
+ >
+ );
+};
+
+export default View;
+```
+
+As you can see, the variations are pretty much the same.
+The differences are the text that is rendered in the `
` tag, and the new field that you added with the schema enhancer.
+But it can be anything.
+
+## Block configuration
+
+With all the block components ready, you need to register the block into Volto.
+
+To do so, open your add-on's {file}`index.js` file, and insert the following contents before the last `return config;` statement.
+
+```js
+config.blocks.blocksConfig.block04 = {
+ id: 'block04', // this is the block id, it must match the id on the previous line
+ title: 'Block 04', // this is the block title
+ view: View04, // this is the block's view component
+ // We do not need a specific edit component, Volto will use the default
+ // edit: null,
+ blockSchema: Schema04, // this is the schema that will be used to render the edit form
+ icon: imagesSVG, // this is the image that will be shown in the block selector
+ sidebarTab: 1, // this is set to 1 to have the `Block` tab selected in the sidebar
+ // editor when editing this block these are the variations available for this block
+ // these are the variations available for this block
+ variations: [
+ {
+ id: 'variation01', // this is the id of the variation
+ title: 'Variation 01', // this is the title of the variation
+ isDefault: true, // this signals if this is the default variation for this block
+ template: VariationView0401, // this is the component that will render
+ // the variation
+ },
+ {
+ id: 'variation02',
+ title: 'Variation 02',
+ isDefault: false,
+ template: VariationView0402,
+ schemaEnhancer: schemaEnhancerBlock04Variation02, // this is the schema enhancer
+ // definition
+ },
+ ],
+};
+```
+
+At the top of the file, import the relevant components as follows.
+
+```js
+import View04 from './components/ExampleBlock04/View';
+import Schema04 from './components/ExampleBlock04/Schema';
+import VariationView0401 from './components/ExampleBlock04/VariationView01';
+import VariationView0402 from './components/ExampleBlock04/VariationView02';
+import schemaEnhancerBlock04Variation02 from './components/ExampleBlock04/enhancers';
+
+// This is the icon we use for the example, use a meaningful one or provide your own image.
+import imagesSVG from '@plone/volto/icons/images.svg';
+```
+
+## See it in action
+
+Your block is ready to use in your site.
+
+Restart your Volto site, and now you can add the new block from the block chooser found in the {guilabel}`Edit` or {guilabel}`Add` content views.
diff --git a/docs/source/blocks/examples/index.md b/docs/source/blocks/examples/index.md
new file mode 100644
index 0000000000..f64f6c1ea8
--- /dev/null
+++ b/docs/source/blocks/examples/index.md
@@ -0,0 +1,23 @@
+---
+myst:
+ html_meta:
+ "description": "Volto block examples"
+ "property=og:description": "Volto block examples"
+ "property=og:title": "Volto block examples"
+ "keywords": "Volto, React, blocks, example, edit, view, Plone"
+---
+
+# Volto block examples
+
+This part of the documentation shows some examples of custom blocks that you can use as a base to develop your own blocks.
+
+These blocks have been tested using Volto 18.4.0.
+
+```{toctree}
+:maxdepth: 1
+
+custom-schema-and-view
+custom-schema-view-and-edit
+custom-view-and-variations
+custom-view-variations-and-schema-enhancer
+```
diff --git a/docs/source/blocks/index.md b/docs/source/blocks/index.md
index 2a8e485349..5283c494c9 100644
--- a/docs/source/blocks/index.md
+++ b/docs/source/blocks/index.md
@@ -20,4 +20,5 @@ block-style-wrapper
extensions
ssr
core/index
+examples/index
```
diff --git a/docs/source/blocks/settings.md b/docs/source/blocks/settings.md
index 0dcb406c45..1a08cc3fd0 100644
--- a/docs/source/blocks/settings.md
+++ b/docs/source/blocks/settings.md
@@ -48,6 +48,10 @@ const customBlocks = {
// Required for alternate default block types implementations.
// See also [Settings reference](/configuration/settings-reference)
},
+ // The `blockSchema` property can either be a schema by itself
+ // (a JavaScript object describing the schema),
+ // or a function that returns a schema.
+ blockSchema: CustomSchema,
// A block can have an schema enhancer function with the signature: (schema) => schema
// It can be either be at block level (it's applied always), at a variation level
// or both. It's up to the developer to make them work nicely (not conflict) between them
diff --git a/packages/volto/news/6560.documentation b/packages/volto/news/6560.documentation
new file mode 100644
index 0000000000..6638701cfa
--- /dev/null
+++ b/packages/volto/news/6560.documentation
@@ -0,0 +1 @@
+Add Volto block examples in the documentation. @erral