-
- {!isHidden && Object.entries(menuData).map(([menuGroup, menuGroupConfiguration]) => (
- toggleMenuGroup(menuGroup)}
- {...menuGroupConfiguration}
- />
- ))}
-
-
- {BottomComponents.map((Item, key) => - )}
-
-
- );
- }
-}
diff --git a/packages/neos-ui/src/Containers/Drawer/index.ts b/packages/neos-ui/src/Containers/Drawer/index.ts
new file mode 100644
index 0000000000..122c4c1382
--- /dev/null
+++ b/packages/neos-ui/src/Containers/Drawer/index.ts
@@ -0,0 +1,10 @@
+/*
+ * This file is part of the Neos.Neos.Ui package.
+ *
+ * (c) Contributors of the Neos Project - www.neos.io
+ *
+ * This package is Open Source Software. For the full copyright and license
+ * information, please view the LICENSE file which was distributed with this
+ * source code.
+ */
+export {Drawer as default, drawer$, toggleDrawer} from './Drawer';
diff --git a/packages/neos-ui/src/Containers/FlashMessages/FlashMessage/index.js b/packages/neos-ui/src/Containers/FlashMessages/FlashMessage/index.js
deleted file mode 100644
index 278acae8f4..0000000000
--- a/packages/neos-ui/src/Containers/FlashMessages/FlashMessage/index.js
+++ /dev/null
@@ -1,64 +0,0 @@
-import React, {PureComponent} from 'react';
-import PropTypes from 'prop-types';
-import mergeClassNames from 'classnames';
-import {IconButton, Icon} from '@neos-project/react-ui-components';
-
-import style from './style.module.css';
-
-export default class FlashMessage extends PureComponent {
- static propTypes = {
- id: PropTypes.string.isRequired,
- message: PropTypes.string.isRequired,
- severity: PropTypes.string.isRequired,
- timeout: PropTypes.number,
- onClose: PropTypes.func.isRequired
- };
-
- handleClose = () => {
- const {onClose, id} = this.props;
-
- setTimeout(() => onClose(id), 100);
- }
-
- componentDidMount() {
- const {timeout} = this.props;
-
- if (timeout) {
- setTimeout(this.handleClose, timeout);
- }
- }
-
- render() {
- const {message, severity} = this.props;
- const isSuccess = severity === 'success';
- const isError = severity === 'error';
- const isInfo = severity === 'info';
-
- const flashMessageClasses = mergeClassNames({
- [style.flashMessage]: true,
- [style['flashMessage--success']]: isSuccess,
- [style['flashMessage--error']]: isError,
- [style['flashMessage--info']]: isInfo
- });
-
- const iconName = mergeClassNames({
- check: isSuccess,
- ban: isError,
- info: isInfo
- }) || 'info';
-
- return (
-
- {Object.keys(flashMessages).map(flashMessageId => {
- const flashMessage = flashMessages[flashMessageId];
- const {id, message, severity, timeout} = flashMessage;
-
- return (
-
- );
- })}
-
- );
- }
-}
diff --git a/packages/neos-ui/src/Containers/FlashMessages/style.module.css b/packages/neos-ui/src/Containers/FlashMessages/style.module.css
deleted file mode 100644
index 853c2c4c4f..0000000000
--- a/packages/neos-ui/src/Containers/FlashMessages/style.module.css
+++ /dev/null
@@ -1,15 +0,0 @@
-.flashMessageContainer {
- position: fixed;
- z-index: var(--zIndex-FlashMessageContainer);
- top: 0;
- left: 50%;
- width: 516px;
- margin-top: 8px;
- transform: translate(-50%, 0);
- max-height: calc(100% - 16px);
- overflow: auto;
-
- &:empty {
- display: none;
- }
-}
diff --git a/packages/neos-ui/src/Containers/Modals/SyncWorkspaceDialog/ConflictList.tsx b/packages/neos-ui/src/Containers/Modals/SyncWorkspaceDialog/ConflictList.tsx
index b6a20b94e8..353943ba63 100644
--- a/packages/neos-ui/src/Containers/Modals/SyncWorkspaceDialog/ConflictList.tsx
+++ b/packages/neos-ui/src/Containers/Modals/SyncWorkspaceDialog/ConflictList.tsx
@@ -9,8 +9,7 @@
*/
import React from 'react';
-import {I18nRegistry} from '@neos-project/neos-ts-interfaces';
-import I18n from '@neos-project/neos-ui-i18n';
+import I18n, {I18nRegistry} from '@neos-project/neos-ui-i18n';
import {Icon} from '@neos-project/react-ui-components';
import {Conflict, ReasonForConflict} from '@neos-project/neos-ui-redux-store/src/CR/Syncing';
import {TypeOfChange} from '@neos-project/neos-ui-redux-store/src/CR/Workspaces';
diff --git a/packages/neos-ui/src/Containers/Modals/SyncWorkspaceDialog/ResolutionStrategyConfirmationDialog.tsx b/packages/neos-ui/src/Containers/Modals/SyncWorkspaceDialog/ResolutionStrategyConfirmationDialog.tsx
index c0e67a104a..9aa24adfd7 100644
--- a/packages/neos-ui/src/Containers/Modals/SyncWorkspaceDialog/ResolutionStrategyConfirmationDialog.tsx
+++ b/packages/neos-ui/src/Containers/Modals/SyncWorkspaceDialog/ResolutionStrategyConfirmationDialog.tsx
@@ -9,8 +9,8 @@
*/
import React from 'react';
-import {I18nRegistry, WorkspaceName} from '@neos-project/neos-ts-interfaces';
-import I18n from '@neos-project/neos-ui-i18n';
+import {WorkspaceName} from '@neos-project/neos-ts-interfaces';
+import I18n, {I18nRegistry} from '@neos-project/neos-ui-i18n';
import {Button, Dialog, Icon} from '@neos-project/react-ui-components';
import {PublishingPhase} from '@neos-project/neos-ui-redux-store/src/CR/Publishing';
import {Conflict, ResolutionStrategy} from '@neos-project/neos-ui-redux-store/src/CR/Syncing';
diff --git a/packages/neos-ui/src/Containers/Modals/SyncWorkspaceDialog/ResolutionStrategySelectionDialog.tsx b/packages/neos-ui/src/Containers/Modals/SyncWorkspaceDialog/ResolutionStrategySelectionDialog.tsx
index c4feb6f686..6c46c83095 100644
--- a/packages/neos-ui/src/Containers/Modals/SyncWorkspaceDialog/ResolutionStrategySelectionDialog.tsx
+++ b/packages/neos-ui/src/Containers/Modals/SyncWorkspaceDialog/ResolutionStrategySelectionDialog.tsx
@@ -9,8 +9,8 @@
*/
import React from 'react';
-import I18n from '@neos-project/neos-ui-i18n';
-import {I18nRegistry, WorkspaceName} from '@neos-project/neos-ts-interfaces';
+import I18n, {I18nRegistry} from '@neos-project/neos-ui-i18n';
+import {WorkspaceName} from '@neos-project/neos-ts-interfaces';
import {Button, Dialog, Icon, SelectBox, SelectBox_Option_MultiLineWithThumbnail} from '@neos-project/react-ui-components';
import {Conflict, ResolutionStrategy, SyncingPhase} from '@neos-project/neos-ui-redux-store/src/CR/Syncing';
diff --git a/packages/neos-ui/src/Containers/Modals/SyncWorkspaceDialog/SyncWorkspaceDialog.tsx b/packages/neos-ui/src/Containers/Modals/SyncWorkspaceDialog/SyncWorkspaceDialog.tsx
index 2da8d0a0fd..bdb242ee24 100644
--- a/packages/neos-ui/src/Containers/Modals/SyncWorkspaceDialog/SyncWorkspaceDialog.tsx
+++ b/packages/neos-ui/src/Containers/Modals/SyncWorkspaceDialog/SyncWorkspaceDialog.tsx
@@ -14,7 +14,8 @@ import {connect} from 'react-redux';
import {neos} from '@neos-project/neos-ui-decorators';
import {selectors, actions} from '@neos-project/neos-ui-redux-store';
import {GlobalState} from '@neos-project/neos-ui-redux-store/src/System';
-import {I18nRegistry, WorkspaceName} from '@neos-project/neos-ts-interfaces';
+import type {WorkspaceName} from '@neos-project/neos-ts-interfaces';
+import type {I18nRegistry} from '@neos-project/neos-ui-i18n';
import {ResolutionStrategy, SyncingPhase, State as SyncingState} from '@neos-project/neos-ui-redux-store/src/CR/Syncing';
import {ConfirmationDialog} from './ConfirmationDialog';
diff --git a/packages/neos-ui/src/Containers/PrimaryToolbar/MenuToggler/MenuToggler.tsx b/packages/neos-ui/src/Containers/PrimaryToolbar/MenuToggler/MenuToggler.tsx
new file mode 100644
index 0000000000..96b7cce780
--- /dev/null
+++ b/packages/neos-ui/src/Containers/PrimaryToolbar/MenuToggler/MenuToggler.tsx
@@ -0,0 +1,65 @@
+/*
+ * This file is part of the Neos.Neos.Ui package.
+ *
+ * (c) Contributors of the Neos Project - www.neos.io
+ *
+ * This package is Open Source Software. For the full copyright and license
+ * information, please view the LICENSE file which was distributed with this
+ * source code.
+ */
+import React from 'react';
+import mergeClassNames from 'classnames';
+
+import Button from '@neos-project/react-ui-components/src/Button/';
+import {neos} from '@neos-project/neos-ui-decorators';
+import {I18nRegistry} from '@neos-project/neos-ts-interfaces';
+import {useLatestState} from '@neos-project/framework-observable-react';
+
+import {drawer$, toggleDrawer} from '../../Drawer';
+
+import style from './style.module.css';
+
+const withNeosGlobals = neos(globalRegistry => ({
+ i18nRegistry: globalRegistry.get('i18n')
+}));
+
+const StatelessMenuToggler: React.FC<{
+ i18nRegistry: I18nRegistry;
+
+ className?: string;
+}> = (props) => {
+ const handleToggle = React.useCallback(() => {
+ toggleDrawer();
+ }, []);
+
+ const {className, i18nRegistry} = props;
+ const {isHidden: isMenuHidden} = useLatestState(drawer$);
+ const isMenuVisible = !isMenuHidden;
+ const classNames = mergeClassNames({
+ [style.menuToggler]: true,
+ [style['menuToggler--isActive']]: isMenuVisible,
+ [className ?? '']: className && className.length
+ });
+
+ //
+ // ToDo: Replace the static 'Menu' aria-label with a label from the i18n service.
+ //
+ return (
+