diff --git a/src/components/DashboardEditor/DashboardEditor.jsx b/src/components/DashboardEditor/DashboardEditor.jsx
new file mode 100644
index 0000000000..86f6da5e15
--- /dev/null
+++ b/src/components/DashboardEditor/DashboardEditor.jsx
@@ -0,0 +1,87 @@
+import React, { useState } from 'react';
+import PropTypes from 'prop-types';
+import uuid from 'uuid';
+
+import { settings } from '../../constants/Settings';
+import { CARD_SIZES } from '../../constants/LayoutConstants';
+import { Button, CodeSnippet, CardEditor } from '../../index';
+
+const { iotPrefix } = settings;
+
+const defaultProps = {
+ initialValue: [],
+ renderHeader: null,
+};
+
+const propTypes = {
+ /** initial dashboard data to edit */
+ initialValue: PropTypes.array, // eslint-disable-line react/forbid-prop-types
+ /** if provided, renders header content above preview */
+ renderHeader: PropTypes.func,
+};
+
+const DashboardEditor = ({ initialValue, renderHeader }) => {
+ const baseClassName = `${iotPrefix}--dashboard-editor`;
+
+ // show the gallery if no card is being edited
+ const [dashboardCards, setDashboardCards] = useState(initialValue);
+ const [selectedCardId, setSelectedCardId] = useState();
+
+ const addCard = data => setDashboardCards([...dashboardCards, data]);
+ const removeCard = id => setDashboardCards(dashboardCards.filter(i => i.id !== id));
+
+ return (
+
+
+ {renderHeader && renderHeader()}
+
+
Dashboard Template preview
+
+ As you add and edit cards, the content underneath here will be updated in real-time. We
+ will replace this with the actual Dashboard component.
+
+
+ {dashboardCards.map(i => (
+
+
+ {JSON.stringify(i, null, 4)}
+
+
+
+
+
+ ))}
+
+
+
i.id === selectedCardId)}
+ onShowGallery={() => setSelectedCardId(null)}
+ // NOTE: won't support changes to card ID
+ onChange={cardData =>
+ setDashboardCards(dashboardCards.map(i => (i.id === cardData.id ? cardData : i)))
+ }
+ onAddCard={type =>
+ addCard({
+ id: uuid.v4(),
+ title: 'New card',
+ size: CARD_SIZES.SMALL,
+ type,
+ })
+ }
+ />
+
+ );
+};
+
+DashboardEditor.propTypes = propTypes;
+DashboardEditor.defaultProps = defaultProps;
+
+export default DashboardEditor;
diff --git a/src/components/DashboardEditor/DashboardEditor.story.jsx b/src/components/DashboardEditor/DashboardEditor.story.jsx
new file mode 100644
index 0000000000..39531936da
--- /dev/null
+++ b/src/components/DashboardEditor/DashboardEditor.story.jsx
@@ -0,0 +1,23 @@
+import React from 'react';
+import { storiesOf } from '@storybook/react';
+import { action } from '@storybook/addon-actions';
+import { withKnobs, object } from '@storybook/addon-knobs';
+
+import { PageTitleBar, Button } from '../../index';
+
+import DashboardEditor from './DashboardEditor';
+
+storiesOf('Watson IoT Experimental/DashboardEditor', module)
+ .addDecorator(withKnobs)
+ .add('default', () => (
+
+
(
+ Do something}
+ />
+ )}
+ />
+
+ ));
diff --git a/src/components/DashboardEditor/_dashboard-editor.scss b/src/components/DashboardEditor/_dashboard-editor.scss
new file mode 100644
index 0000000000..b49ae5d2af
--- /dev/null
+++ b/src/components/DashboardEditor/_dashboard-editor.scss
@@ -0,0 +1,11 @@
+.#{$iot-prefix}--dashboard-editor {
+ display: flex;
+ height: 100%;
+ &--content {
+ flex: 1;
+ flex-direction: column;
+ }
+ &--preview {
+ flex: 1;
+ }
+}
diff --git a/src/index.js b/src/index.js
index 04aeaf66ea..e482af7c47 100755
--- a/src/index.js
+++ b/src/index.js
@@ -60,6 +60,7 @@ export useSuiteHeaderData from './components/SuiteHeader/hooks/useSuiteHeaderDat
export Dashboard from './components/Dashboard/Dashboard';
export DashboardHeader from './components/Dashboard/DashboardHeader';
export DashboardGrid from './components/Dashboard/DashboardGrid';
+export DashboardEditor from './components/DashboardEditor/DashboardEditor';
export CardEditor from './components/CardEditor/CardEditor';
export Card from './components/Card/Card';
export ValueCard from './components/ValueCard/ValueCard';
diff --git a/src/styles.scss b/src/styles.scss
index 41f7eb1636..a383d739ce 100644
--- a/src/styles.scss
+++ b/src/styles.scss
@@ -182,6 +182,7 @@ $deprecations--message: 'Deprecated code was found, this code will be removed be
@import 'components/CardEditor/CardEditForm/card-edit-form';
@import 'components/ComposedModal/composed-modal';
@import 'components/Dashboard/dashboard';
+@import 'components/DashboardEditor/dashboard-editor';
@import 'components/DateTimePicker/date-time-picker';
@import 'components/GaugeCard/gauge-card';
@import 'components/Header/header';