diff --git a/CHANGELOG.md b/CHANGELOG.md
index d2592db64ac..6c2126533ec 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -806,8 +806,6 @@ See https://6.dev-docs.plone.org/volto/upgrade-guide/index.html for more informa
## 16.0.0-alpha.34 (2022-09-17)
-### Breaking
-
### Feature
- Added new components `Aliases` for aliases control in Volto. Alias management in both controlpanel and object view. @andreiggr @avoinea
@@ -818,8 +816,6 @@ See https://6.dev-docs.plone.org/volto/upgrade-guide/index.html for more informa
- Add `matchAllRoutes` to AsyncConnect so that it matches all configured `asyncPropsExtenders` @tiberiuichim
- Fix acceptence test groups controlpanel @ksuess
-### Internal
-
### Documentation
- Bring back "Guidelines for Contributing"
diff --git a/news/3161.feature b/news/3161.feature
new file mode 100644
index 00000000000..826796a3fea
--- /dev/null
+++ b/news/3161.feature
@@ -0,0 +1 @@
+Add Quanta toolbar as experimental feature @sneridagh
diff --git a/packages/volto-slate/src/blocks/Text/DefaultTextBlockEditor.jsx b/packages/volto-slate/src/blocks/Text/DefaultTextBlockEditor.jsx
index bdd3f429269..d0fa0cedcb7 100644
--- a/packages/volto-slate/src/blocks/Text/DefaultTextBlockEditor.jsx
+++ b/packages/volto-slate/src/blocks/Text/DefaultTextBlockEditor.jsx
@@ -247,7 +247,10 @@ export const DefaultTextBlockEditor = (props) => {
}}
- {!config.experimental.addBlockButton.enabled &&
+ {!(
+ config.experimental.addBlockButton.enabled ||
+ config.experimental.quantaToolbar.enabled
+ ) &&
selected &&
!data.plaintext?.trim() &&
!disableNewBlocks && (
diff --git a/src/components/index.js b/src/components/index.js
index eec24b73a08..3d4f823b4f5 100644
--- a/src/components/index.js
+++ b/src/components/index.js
@@ -111,6 +111,7 @@ export Workflow from '@plone/volto/components/manage/Workflow/Workflow';
export Messages from '@plone/volto/components/manage/Messages/Messages';
export BlockChooser from '@plone/volto/components/manage/BlockChooser/BlockChooser';
export BlockChooserButton from '@plone/volto/components/manage/BlockChooser/BlockChooserButton';
+export BlockToolbarItem from '@plone/volto/components/manage/Blocks/Block/BlockToolbarItem';
export Toolbar from '@plone/volto/components/manage/Toolbar/Toolbar';
export Sidebar from '@plone/volto/components/manage/Sidebar/Sidebar';
export SidebarPopup from '@plone/volto/components/manage/Sidebar/SidebarPopup';
diff --git a/src/components/manage/Blocks/Block/BlockToolbarItem.jsx b/src/components/manage/Blocks/Block/BlockToolbarItem.jsx
new file mode 100644
index 00000000000..f35dc8ac6ea
--- /dev/null
+++ b/src/components/manage/Blocks/Block/BlockToolbarItem.jsx
@@ -0,0 +1,25 @@
+/**
+ * A Quanta toolbar entry button that can render itself either as
+ * a Dropdown.Item (in the more menu) or a simple Button.
+ *
+ */
+
+import React from 'react';
+import { Dropdown, Button } from 'semantic-ui-react';
+import { Icon } from '@plone/volto/components';
+
+const BlockToolbarItem = (props) => {
+ const { isMenuShape = false, icon, label, onClick } = props;
+ return isMenuShape ? (
+
+
+ {label}
+
+ ) : (
+
+ );
+};
+
+export default BlockToolbarItem;
diff --git a/src/components/manage/Blocks/Block/BlockToolbarItem.stories.js b/src/components/manage/Blocks/Block/BlockToolbarItem.stories.js
new file mode 100644
index 00000000000..a452fa7ee04
--- /dev/null
+++ b/src/components/manage/Blocks/Block/BlockToolbarItem.stories.js
@@ -0,0 +1,58 @@
+import React from 'react';
+import Wrapper from '@plone/volto/storybook';
+import BlockToolbarItem from './BlockToolbarItem';
+import { PluggablesProvider } from '@plone/volto/components/manage/Pluggable';
+import trashSVG from '@plone/volto/icons/delete.svg';
+import hideSVG from '@plone/volto/icons/hide.svg';
+import showSVG from '@plone/volto/icons/show.svg';
+
+const icons = {
+ showSVG,
+ hideSVG,
+ trashSVG,
+};
+
+const BlockToolbarItemStory = (args) => {
+ return (
+
+
+
+
+
+ );
+};
+
+export const Default = BlockToolbarItemStory.bind({});
+
+Default.args = {
+ id: 'field-default',
+ label: 'Sample entry',
+ icon: 'trashSVG',
+ isMenuShape: false,
+};
+
+export default {
+ title: 'Quanta/BlockToolbaritem',
+ component: BlockToolbarItem,
+ decorators: [
+ (Story) => (
+
+
+
+ ),
+ ],
+ argTypes: {
+ // controlled value prop
+ icon: {
+ // control: {
+ // disable: true,
+ // },
+ control: {
+ type: 'select',
+ options: ['showSVG', 'hideSVG', 'trashSVG'],
+ },
+ },
+ },
+ // excludeStories: ['searchResults'],
+ // subcomponents: { ArgsTable },
+};
diff --git a/src/components/manage/Blocks/Block/BlocksForm.jsx b/src/components/manage/Blocks/Block/BlocksForm.jsx
index c78681bc414..c810c91e9f2 100644
--- a/src/components/manage/Blocks/Block/BlocksForm.jsx
+++ b/src/components/manage/Blocks/Block/BlocksForm.jsx
@@ -1,6 +1,6 @@
import React from 'react';
+import WrapperlessBlockEdit from './Edit';
import { useIntl } from 'react-intl';
-import EditBlock from './Edit';
import { DragDropList } from '@plone/volto/components';
import {
getBlocks,
@@ -10,6 +10,7 @@ import {
import {
addBlock,
insertBlock,
+ insertBlockAfter,
changeBlock,
deleteBlock,
moveBlock,
@@ -21,8 +22,25 @@ import EditBlockWrapper from './EditBlockWrapper';
import { setSidebarTab } from '@plone/volto/actions';
import { useDispatch } from 'react-redux';
import { useDetectClickOutside, useEvent } from '@plone/volto/helpers';
+import QuantaEditBlockWrapper from './QuantaEditBlockWrapper';
import config from '@plone/volto/registry';
+const topLevelBlockWrapper = ({ draginfo }, editBlock, blockProps) => {
+ return (
+
+ {editBlock}
+
+ );
+};
+
+const defaultBlockWrapper = ({ draginfo }, editBlock, blockProps) => {
+ return (
+
+ {editBlock}
+
+ );
+};
+
const BlocksForm = (props) => {
const {
pathname,
@@ -42,6 +60,7 @@ const BlocksForm = (props) => {
isMainForm = true,
blocksConfig = config.blocks.blocksConfig,
editable = true,
+ direction,
} = props;
const blockList = getBlocks(properties);
@@ -137,6 +156,17 @@ const BlocksForm = (props) => {
return newId;
};
+ const onInsertBlockAfter = (id, value, current) => {
+ const [newId, newFormData] = insertBlockAfter(
+ properties,
+ id,
+ value,
+ current,
+ );
+ onChangeFormData(newFormData);
+ return newId;
+ };
+
const onAddBlock = (type, index) => {
if (editable) {
const [id, newFormData] = addBlock(properties, type, index);
@@ -172,14 +202,6 @@ const BlocksForm = (props) => {
onChangeFormData(newFormData);
};
- const defaultBlockWrapper = ({ draginfo }, editBlock, blockProps) => (
-
- {editBlock}
-
- );
-
- const editBlockWrapper = children || defaultBlockWrapper;
-
// Remove invalid blocks on saving
// Note they are alreaady filtered by DragDropList, but we also want them
// to be removed when the user saves the page next. Otherwise the invalid
@@ -203,6 +225,7 @@ const BlocksForm = (props) => {