diff --git a/src/plugins/dashboard/public/application/top_nav/editor_menu.tsx b/src/plugins/dashboard/public/application/top_nav/editor_menu.tsx
index 8a46a16c1bf0c..effbf8ce980d7 100644
--- a/src/plugins/dashboard/public/application/top_nav/editor_menu.tsx
+++ b/src/plugins/dashboard/public/application/top_nav/editor_menu.tsx
@@ -231,7 +231,7 @@ export const EditorMenu = ({ dashboardContainer, createNewVisType }: Props) => {
     <SolutionToolbarPopover
       ownFocus
       label={i18n.translate('dashboard.solutionToolbar.editorMenuButtonLabel', {
-        defaultMessage: 'All types',
+        defaultMessage: 'Select type',
       })}
       iconType="arrowDown"
       iconSide="right"
diff --git a/src/plugins/presentation_util/public/components/solution_toolbar/items/quick_group.scss b/src/plugins/presentation_util/public/components/solution_toolbar/items/quick_group.scss
index 535570a51d777..c70e317546d40 100644
--- a/src/plugins/presentation_util/public/components/solution_toolbar/items/quick_group.scss
+++ b/src/plugins/presentation_util/public/components/solution_toolbar/items/quick_group.scss
@@ -1,11 +1,31 @@
 .quickButtonGroup {
-  .quickButtonGroup__button {
-    background-color: $euiColorEmptyShade;
-    @include kbnThemeStyle('v8') {
-      // sass-lint:disable-block no-important
-      border-width: $euiBorderWidthThin !important;
-      border-style: solid !important;
-      border-color: $euiBorderColor !important;
+  .euiButtonGroup__buttons {
+    border-radius: $euiBorderRadius;
+
+    .quickButtonGroup__button {
+      background-color: $euiColorEmptyShade;
+      @include kbnThemeStyle('v8') {
+        // sass-lint:disable-block no-important
+        border-width: $euiBorderWidthThin !important;
+        border-style: solid !important;
+        border-color: $euiBorderColor !important;
+      }
+    }
+
+    .quickButtonGroup__button:first-of-type {
+      @include kbnThemeStyle('v8') {
+        // sass-lint:disable-block no-important
+        border-top-left-radius: $euiBorderRadius !important;
+        border-bottom-left-radius: $euiBorderRadius !important;
+      }
+    }
+
+    .quickButtonGroup__button:last-of-type {
+      @include kbnThemeStyle('v8') {
+        // sass-lint:disable-block no-important
+        border-top-right-radius: $euiBorderRadius !important;
+        border-bottom-right-radius: $euiBorderRadius !important;
+      }
     }
   }
 }
diff --git a/x-pack/plugins/canvas/kibana.json b/x-pack/plugins/canvas/kibana.json
index 9c4d1b2179d82..2fd312502a3c7 100644
--- a/x-pack/plugins/canvas/kibana.json
+++ b/x-pack/plugins/canvas/kibana.json
@@ -25,6 +25,7 @@
     "features",
     "inspector",
     "presentationUtil",
+    "visualizations",
     "uiActions",
     "share"
   ],
diff --git a/x-pack/plugins/canvas/public/components/workpad_app/workpad_app.scss b/x-pack/plugins/canvas/public/components/workpad_app/workpad_app.scss
index 4acdca10d61cc..0ddd44ed8f9a8 100644
--- a/x-pack/plugins/canvas/public/components/workpad_app/workpad_app.scss
+++ b/x-pack/plugins/canvas/public/components/workpad_app/workpad_app.scss
@@ -31,7 +31,7 @@ $canvasLayoutFontSize: $euiFontSizeS;
 .canvasLayout__stageHeader {
   flex-grow: 0;
   flex-basis: auto;
-  padding: $euiSizeS;
+  padding: $euiSizeS $euiSize;
   font-size: $canvasLayoutFontSize;
   border-bottom: $euiBorderThin;
   background: $euiColorLightestShade;
diff --git a/x-pack/plugins/canvas/public/components/workpad_header/editor_menu/__stories__/__snapshots__/editor_menu.stories.storyshot b/x-pack/plugins/canvas/public/components/workpad_header/editor_menu/__stories__/__snapshots__/editor_menu.stories.storyshot
new file mode 100644
index 0000000000000..f4aab0e59e7ee
--- /dev/null
+++ b/x-pack/plugins/canvas/public/components/workpad_header/editor_menu/__stories__/__snapshots__/editor_menu.stories.storyshot
@@ -0,0 +1,81 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Storyshots components/WorkpadHeader/EditorMenu dark mode 1`] = `
+<div
+  className="euiPopover euiPopover--anchorDownLeft"
+  data-test-subj="canvasEditorMenuButton"
+>
+  <div
+    className="euiPopover__anchor"
+  >
+    <button
+      className="euiButton euiButton--text solutionToolbarButton undefined"
+      data-test-subj="canvasEditorMenuButton"
+      disabled={false}
+      onClick={[Function]}
+      style={
+        Object {
+          "minWidth": undefined,
+        }
+      }
+      type="button"
+    >
+      <span
+        className="euiButtonContent euiButtonContent--iconRight euiButton__content"
+      >
+        <span
+          className="euiButtonContent__icon"
+          color="inherit"
+          data-euiicon-type="arrowDown"
+          size="m"
+        />
+        <span
+          className="euiButton__text"
+        >
+          Select type
+        </span>
+      </span>
+    </button>
+  </div>
+</div>
+`;
+
+exports[`Storyshots components/WorkpadHeader/EditorMenu default 1`] = `
+<div
+  className="euiPopover euiPopover--anchorDownLeft"
+  data-test-subj="canvasEditorMenuButton"
+>
+  <div
+    className="euiPopover__anchor"
+  >
+    <button
+      className="euiButton euiButton--text solutionToolbarButton undefined"
+      data-test-subj="canvasEditorMenuButton"
+      disabled={false}
+      onClick={[Function]}
+      style={
+        Object {
+          "minWidth": undefined,
+        }
+      }
+      type="button"
+    >
+      <span
+        className="euiButtonContent euiButtonContent--iconRight euiButton__content"
+      >
+        <span
+          className="euiButtonContent__icon"
+          color="inherit"
+          data-euiicon-type="arrowDown"
+          size="m"
+        />
+        <span
+          className="euiButton__text"
+        >
+          Select type
+        </span>
+      </span>
+    </button>
+  </div>
+</div>
+`;
diff --git a/x-pack/plugins/canvas/public/components/workpad_header/editor_menu/__stories__/editor_menu.stories.tsx b/x-pack/plugins/canvas/public/components/workpad_header/editor_menu/__stories__/editor_menu.stories.tsx
new file mode 100644
index 0000000000000..01048bc0af301
--- /dev/null
+++ b/x-pack/plugins/canvas/public/components/workpad_header/editor_menu/__stories__/editor_menu.stories.tsx
@@ -0,0 +1,107 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { storiesOf } from '@storybook/react';
+import { action } from '@storybook/addon-actions';
+import React from 'react';
+import { EmbeddableFactoryDefinition, IEmbeddable } from 'src/plugins/embeddable/public';
+import { BaseVisType, VisTypeAlias } from 'src/plugins/visualizations/public';
+import { EditorMenu } from '../editor_menu.component';
+
+const testFactories: EmbeddableFactoryDefinition[] = [
+  {
+    type: 'ml_anomaly_swimlane',
+    getDisplayName: () => 'Anomaly swimlane',
+    getIconType: () => '',
+    getDescription: () => 'Description for anomaly swimlane',
+    isEditable: () => Promise.resolve(true),
+    create: () => Promise.resolve({ id: 'swimlane_embeddable' } as IEmbeddable),
+    grouping: [
+      {
+        id: 'ml',
+        getDisplayName: () => 'machine learning',
+        getIconType: () => 'machineLearningApp',
+      },
+    ],
+  },
+  {
+    type: 'ml_anomaly_chart',
+    getDisplayName: () => 'Anomaly chart',
+    getIconType: () => '',
+    getDescription: () => 'Description for anomaly chart',
+    isEditable: () => Promise.resolve(true),
+    create: () => Promise.resolve({ id: 'anomaly_chart_embeddable' } as IEmbeddable),
+    grouping: [
+      {
+        id: 'ml',
+        getDisplayName: () => 'machine learning',
+        getIconType: () => 'machineLearningApp',
+      },
+    ],
+  },
+  {
+    type: 'log_stream',
+    getDisplayName: () => 'Log stream',
+    getIconType: () => '',
+    getDescription: () => 'Description for log stream',
+    isEditable: () => Promise.resolve(true),
+    create: () => Promise.resolve({ id: 'anomaly_chart_embeddable' } as IEmbeddable),
+  },
+];
+
+const testVisTypes: BaseVisType[] = [
+  { title: 'TSVB', icon: '', description: 'Description of TSVB', name: 'tsvb' } as BaseVisType,
+  {
+    titleInWizard: 'Custom visualization',
+    title: 'Vega',
+    icon: '',
+    description: 'Description of Vega',
+    name: 'vega',
+  } as BaseVisType,
+];
+
+const testVisTypeAliases: VisTypeAlias[] = [
+  {
+    title: 'Lens',
+    aliasApp: 'lens',
+    aliasPath: 'path/to/lens',
+    icon: 'lensApp',
+    name: 'lens',
+    description: 'Description of Lens app',
+    stage: 'production',
+  },
+  {
+    title: 'Maps',
+    aliasApp: 'maps',
+    aliasPath: 'path/to/maps',
+    icon: 'gisApp',
+    name: 'maps',
+    description: 'Description of Maps app',
+    stage: 'production',
+  },
+];
+
+storiesOf('components/WorkpadHeader/EditorMenu', module)
+  .add('default', () => (
+    <EditorMenu
+      factories={testFactories}
+      promotedVisTypes={testVisTypes}
+      visTypeAliases={testVisTypeAliases}
+      createNewVisType={() => action('createNewVisType')}
+      createNewEmbeddable={() => action('createNewEmbeddable')}
+    />
+  ))
+  .add('dark mode', () => (
+    <EditorMenu
+      factories={testFactories}
+      isDarkThemeEnabled
+      promotedVisTypes={testVisTypes}
+      visTypeAliases={testVisTypeAliases}
+      createNewVisType={() => action('createNewVisType')}
+      createNewEmbeddable={() => action('createNewEmbeddable')}
+    />
+  ));
diff --git a/x-pack/plugins/canvas/public/components/workpad_header/editor_menu/editor_menu.component.tsx b/x-pack/plugins/canvas/public/components/workpad_header/editor_menu/editor_menu.component.tsx
new file mode 100644
index 0000000000000..e8f762f9731a1
--- /dev/null
+++ b/x-pack/plugins/canvas/public/components/workpad_header/editor_menu/editor_menu.component.tsx
@@ -0,0 +1,170 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React, { FC } from 'react';
+import {
+  EuiContextMenu,
+  EuiContextMenuPanelItemDescriptor,
+  EuiContextMenuItemIcon,
+} from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
+import { EmbeddableFactoryDefinition } from '../../../../../../../src/plugins/embeddable/public';
+import { BaseVisType, VisTypeAlias } from '../../../../../../../src/plugins/visualizations/public';
+import { SolutionToolbarPopover } from '../../../../../../../src/plugins/presentation_util/public';
+
+const strings = {
+  getEditorMenuButtonLabel: () =>
+    i18n.translate('xpack.canvas.solutionToolbar.editorMenuButtonLabel', {
+      defaultMessage: 'Select type',
+    }),
+};
+
+interface FactoryGroup {
+  id: string;
+  appName: string;
+  icon: EuiContextMenuItemIcon;
+  panelId: number;
+  factories: EmbeddableFactoryDefinition[];
+}
+
+interface Props {
+  factories: EmbeddableFactoryDefinition[];
+  isDarkThemeEnabled?: boolean;
+  promotedVisTypes: BaseVisType[];
+  visTypeAliases: VisTypeAlias[];
+  createNewVisType: (visType?: BaseVisType | VisTypeAlias) => () => void;
+  createNewEmbeddable: (factory: EmbeddableFactoryDefinition) => () => void;
+}
+
+export const EditorMenu: FC<Props> = ({
+  factories,
+  isDarkThemeEnabled,
+  promotedVisTypes,
+  visTypeAliases,
+  createNewVisType,
+  createNewEmbeddable,
+}: Props) => {
+  const factoryGroupMap: Record<string, FactoryGroup> = {};
+  const ungroupedFactories: EmbeddableFactoryDefinition[] = [];
+
+  let panelCount = 1;
+
+  // Maps factories with a group to create nested context menus for each group type
+  // and pushes ungrouped factories into a separate array
+  factories.forEach((factory: EmbeddableFactoryDefinition, index) => {
+    const { grouping } = factory;
+
+    if (grouping) {
+      grouping.forEach((group) => {
+        if (factoryGroupMap[group.id]) {
+          factoryGroupMap[group.id].factories.push(factory);
+        } else {
+          factoryGroupMap[group.id] = {
+            id: group.id,
+            appName: group.getDisplayName ? group.getDisplayName({}) : group.id,
+            icon: (group.getIconType ? group.getIconType({}) : 'empty') as EuiContextMenuItemIcon,
+            factories: [factory],
+            panelId: panelCount,
+          };
+
+          panelCount++;
+        }
+      });
+    } else {
+      ungroupedFactories.push(factory);
+    }
+  });
+
+  const getVisTypeMenuItem = (visType: BaseVisType): EuiContextMenuPanelItemDescriptor => {
+    const { name, title, titleInWizard, description, icon = 'empty' } = visType;
+    return {
+      name: titleInWizard || title,
+      icon: icon as string,
+      onClick: createNewVisType(visType),
+      'data-test-subj': `visType-${name}`,
+      toolTipContent: description,
+    };
+  };
+
+  const getVisTypeAliasMenuItem = (
+    visTypeAlias: VisTypeAlias
+  ): EuiContextMenuPanelItemDescriptor => {
+    const { name, title, description, icon = 'empty' } = visTypeAlias;
+
+    return {
+      name: title,
+      icon,
+      onClick: createNewVisType(visTypeAlias),
+      'data-test-subj': `visType-${name}`,
+      toolTipContent: description,
+    };
+  };
+
+  const getEmbeddableFactoryMenuItem = (
+    factory: EmbeddableFactoryDefinition
+  ): EuiContextMenuPanelItemDescriptor => {
+    const icon = factory?.getIconType ? factory.getIconType() : 'empty';
+
+    const toolTipContent = factory?.getDescription ? factory.getDescription() : undefined;
+
+    return {
+      name: factory.getDisplayName(),
+      icon,
+      toolTipContent,
+      onClick: createNewEmbeddable(factory),
+      'data-test-subj': `createNew-${factory.type}`,
+    };
+  };
+
+  const editorMenuPanels = [
+    {
+      id: 0,
+      items: [
+        ...visTypeAliases.map(getVisTypeAliasMenuItem),
+        ...Object.values(factoryGroupMap).map(({ id, appName, icon, panelId }) => ({
+          name: appName,
+          icon,
+          panel: panelId,
+          'data-test-subj': `canvasEditorMenu-${id}Group`,
+        })),
+        ...ungroupedFactories.map(getEmbeddableFactoryMenuItem),
+        ...promotedVisTypes.map(getVisTypeMenuItem),
+      ],
+    },
+    ...Object.values(factoryGroupMap).map(
+      ({ appName, panelId, factories: groupFactories }: FactoryGroup) => ({
+        id: panelId,
+        title: appName,
+        items: groupFactories.map(getEmbeddableFactoryMenuItem),
+      })
+    ),
+  ];
+
+  return (
+    <SolutionToolbarPopover
+      ownFocus
+      label={strings.getEditorMenuButtonLabel()}
+      iconType="arrowDown"
+      iconSide="right"
+      panelPaddingSize="none"
+      data-test-subj="canvasEditorMenuButton"
+    >
+      {() => (
+        <EuiContextMenu
+          initialPanelId={0}
+          panels={editorMenuPanels}
+          className={`canvasSolutionToolbar__editorContextMenu ${
+            isDarkThemeEnabled
+              ? 'canvasSolutionToolbar__editorContextMenu--dark'
+              : 'canvasSolutionToolbar__editorContextMenu--light'
+          }`}
+          data-test-subj="canvasEditorContextMenu"
+        />
+      )}
+    </SolutionToolbarPopover>
+  );
+};
diff --git a/x-pack/plugins/canvas/public/components/workpad_header/editor_menu/editor_menu.tsx b/x-pack/plugins/canvas/public/components/workpad_header/editor_menu/editor_menu.tsx
new file mode 100644
index 0000000000000..dad34e6983c5d
--- /dev/null
+++ b/x-pack/plugins/canvas/public/components/workpad_header/editor_menu/editor_menu.tsx
@@ -0,0 +1,147 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React, { FC, useCallback } from 'react';
+import { useLocation } from 'react-router-dom';
+import { trackCanvasUiMetric, METRIC_TYPE } from '../../../../public/lib/ui_metric';
+import {
+  useEmbeddablesService,
+  usePlatformService,
+  useVisualizationsService,
+} from '../../../services';
+import {
+  BaseVisType,
+  VisGroups,
+  VisTypeAlias,
+} from '../../../../../../../src/plugins/visualizations/public';
+import {
+  EmbeddableFactoryDefinition,
+  EmbeddableInput,
+} from '../../../../../../../src/plugins/embeddable/public';
+import { CANVAS_APP } from '../../../../common/lib';
+import { encode } from '../../../../common/lib/embeddable_dataurl';
+import { ElementSpec } from '../../../../types';
+import { EditorMenu as Component } from './editor_menu.component';
+
+interface Props {
+  /**
+   * Handler for adding a selected element to the workpad
+   */
+  addElement: (element: Partial<ElementSpec>) => void;
+}
+
+export const EditorMenu: FC<Props> = ({ addElement }) => {
+  const embeddablesService = useEmbeddablesService();
+  const { pathname, search } = useLocation();
+  const platformService = usePlatformService();
+  const stateTransferService = embeddablesService.getStateTransfer();
+  const visualizationsService = useVisualizationsService();
+  const IS_DARK_THEME = platformService.getUISetting('theme:darkMode');
+
+  const createNewVisType = useCallback(
+    (visType?: BaseVisType | VisTypeAlias) => () => {
+      let path = '';
+      let appId = '';
+
+      if (visType) {
+        if (trackCanvasUiMetric) {
+          trackCanvasUiMetric(METRIC_TYPE.CLICK, `${visType.name}:create`);
+        }
+
+        if ('aliasPath' in visType) {
+          appId = visType.aliasApp;
+          path = visType.aliasPath;
+        } else {
+          appId = 'visualize';
+          path = `#/create?type=${encodeURIComponent(visType.name)}`;
+        }
+      } else {
+        appId = 'visualize';
+        path = '#/create?';
+      }
+
+      stateTransferService.navigateToEditor(appId, {
+        path,
+        state: {
+          originatingApp: CANVAS_APP,
+          originatingPath: `#/${pathname}${search}`,
+        },
+      });
+    },
+    [stateTransferService, pathname, search]
+  );
+
+  const createNewEmbeddable = useCallback(
+    (factory: EmbeddableFactoryDefinition) => async () => {
+      if (trackCanvasUiMetric) {
+        trackCanvasUiMetric(METRIC_TYPE.CLICK, factory.type);
+      }
+      let embeddableInput;
+      if (factory.getExplicitInput) {
+        embeddableInput = await factory.getExplicitInput();
+      } else {
+        const newEmbeddable = await factory.create({} as EmbeddableInput);
+        embeddableInput = newEmbeddable?.getInput();
+      }
+
+      if (embeddableInput) {
+        const config = encode(embeddableInput);
+        const expression = `embeddable config="${config}"
+  type="${factory.type}" 
+| render`;
+
+        addElement({ expression });
+      }
+    },
+    [addElement]
+  );
+
+  const getVisTypesByGroup = (group: VisGroups): BaseVisType[] =>
+    visualizationsService
+      .getByGroup(group)
+      .sort(({ name: a }: BaseVisType | VisTypeAlias, { name: b }: BaseVisType | VisTypeAlias) => {
+        if (a < b) {
+          return -1;
+        }
+        if (a > b) {
+          return 1;
+        }
+        return 0;
+      })
+      .filter(({ hidden }: BaseVisType) => !hidden);
+
+  const visTypeAliases = visualizationsService
+    .getAliases()
+    .sort(({ promotion: a = false }: VisTypeAlias, { promotion: b = false }: VisTypeAlias) =>
+      a === b ? 0 : a ? -1 : 1
+    );
+
+  const factories = embeddablesService
+    ? Array.from(embeddablesService.getEmbeddableFactories()).filter(
+        ({ type, isEditable, canCreateNew, isContainerType }) =>
+          isEditable() &&
+          !isContainerType &&
+          canCreateNew() &&
+          !['visualization', 'ml'].some((factoryType) => {
+            return type.includes(factoryType);
+          })
+      )
+    : [];
+
+  const promotedVisTypes = getVisTypesByGroup(VisGroups.PROMOTED);
+
+  return (
+    <Component
+      createNewVisType={createNewVisType}
+      createNewEmbeddable={createNewEmbeddable}
+      promotedVisTypes={promotedVisTypes}
+      isDarkThemeEnabled={IS_DARK_THEME}
+      factories={factories}
+      visTypeAliases={visTypeAliases}
+    />
+  );
+};
diff --git a/x-pack/plugins/canvas/public/components/workpad_header/editor_menu/index.ts b/x-pack/plugins/canvas/public/components/workpad_header/editor_menu/index.ts
new file mode 100644
index 0000000000000..0f903b1bbbe2e
--- /dev/null
+++ b/x-pack/plugins/canvas/public/components/workpad_header/editor_menu/index.ts
@@ -0,0 +1,9 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+export { EditorMenu } from './editor_menu';
+export { EditorMenu as EditorMenuComponent } from './editor_menu.component';
diff --git a/x-pack/plugins/canvas/public/components/workpad_header/element_menu/__stories__/element_menu.stories.tsx b/x-pack/plugins/canvas/public/components/workpad_header/element_menu/__stories__/element_menu.stories.tsx
index a48a6e35a4a37..9d37873bcae0a 100644
--- a/x-pack/plugins/canvas/public/components/workpad_header/element_menu/__stories__/element_menu.stories.tsx
+++ b/x-pack/plugins/canvas/public/components/workpad_header/element_menu/__stories__/element_menu.stories.tsx
@@ -130,9 +130,5 @@ You can use standard Markdown in here, but you can also access your piped-in dat
 };
 
 storiesOf('components/WorkpadHeader/ElementMenu', module).add('default', () => (
-  <ElementMenu
-    elements={testElements}
-    addElement={action('addElement')}
-    createNewEmbeddable={action('createNewEmbeddable')}
-  />
+  <ElementMenu elements={testElements} addElement={action('addElement')} />
 ));
diff --git a/x-pack/plugins/canvas/public/components/workpad_header/element_menu/element_menu.component.tsx b/x-pack/plugins/canvas/public/components/workpad_header/element_menu/element_menu.component.tsx
index 024c71c7a8dfc..1cfab236d9a9c 100644
--- a/x-pack/plugins/canvas/public/components/workpad_header/element_menu/element_menu.component.tsx
+++ b/x-pack/plugins/canvas/public/components/workpad_header/element_menu/element_menu.component.tsx
@@ -12,13 +12,12 @@ import { EuiContextMenu, EuiIcon, EuiContextMenuPanelItemDescriptor } from '@ela
 import { i18n } from '@kbn/i18n';
 import { PrimaryActionPopover } from '../../../../../../../src/plugins/presentation_util/public';
 import { getId } from '../../../lib/get_id';
-import { ClosePopoverFn } from '../../popover';
 import { CONTEXT_MENU_TOP_BORDER_CLASSNAME } from '../../../../common/lib';
 import { ElementSpec } from '../../../../types';
 import { flattenPanelTree } from '../../../lib/flatten_panel_tree';
 import { AssetManager } from '../../asset_manager';
+import { ClosePopoverFn } from '../../popover';
 import { SavedElementsModal } from '../../saved_elements_modal';
-import { useLabsService } from '../../../services';
 
 interface CategorizedElementLists {
   [key: string]: ElementSpec[];
@@ -122,19 +121,9 @@ export interface Props {
    * Handler for adding a selected element to the workpad
    */
   addElement: (element: Partial<ElementSpec>) => void;
-  /**
-   * Crete new embeddable
-   */
-  createNewEmbeddable: () => void;
 }
 
-export const ElementMenu: FunctionComponent<Props> = ({
-  elements,
-  addElement,
-  createNewEmbeddable,
-}) => {
-  const labsService = useLabsService();
-  const isByValueEnabled = labsService.isProjectEnabled('labs:canvas:byValueEmbeddable');
+export const ElementMenu: FunctionComponent<Props> = ({ elements, addElement }) => {
   const [isAssetModalVisible, setAssetModalVisible] = useState(false);
   const [isSavedElementsModalVisible, setSavedElementsModalVisible] = useState(false);
 
@@ -210,18 +199,6 @@ export const ElementMenu: FunctionComponent<Props> = ({
             closePopover();
           },
         },
-        // TODO: Remove this menu option. This is a temporary menu options just for testing,
-        // will be removed once toolbar is implemented
-        isByValueEnabled
-          ? {
-              name: 'Lens',
-              icon: <EuiIcon type="lensApp" size="m" />,
-              onClick: () => {
-                createNewEmbeddable();
-                closePopover();
-              },
-            }
-          : {},
       ],
     };
   };
diff --git a/x-pack/plugins/canvas/public/components/workpad_header/element_menu/element_menu.tsx b/x-pack/plugins/canvas/public/components/workpad_header/element_menu/element_menu.tsx
index b4f28df9e9a11..d43d13a65a5d7 100644
--- a/x-pack/plugins/canvas/public/components/workpad_header/element_menu/element_menu.tsx
+++ b/x-pack/plugins/canvas/public/components/workpad_header/element_menu/element_menu.tsx
@@ -5,34 +5,4 @@
  * 2.0.
  */
 
-import React, { FC, useCallback } from 'react';
-import { useLocation } from 'react-router-dom';
-import { trackCanvasUiMetric, METRIC_TYPE } from '../../../../public/lib/ui_metric';
-import { CANVAS_APP } from '../../../../common/lib';
-import { ElementMenu as Component, Props } from './element_menu.component';
-import { useEmbeddablesService } from '../../../services';
-
-export const ElementMenu: FC<Omit<Props, 'createNewEmbeddable'>> = (props) => {
-  const embeddablesService = useEmbeddablesService();
-  const stateTransferService = embeddablesService.getStateTransfer();
-  const { pathname, search } = useLocation();
-
-  const createNewEmbeddable = useCallback(() => {
-    const path = '#/';
-    const appId = 'lens';
-
-    if (trackCanvasUiMetric) {
-      trackCanvasUiMetric(METRIC_TYPE.CLICK, `${appId}:create`);
-    }
-
-    stateTransferService.navigateToEditor(appId, {
-      path,
-      state: {
-        originatingApp: CANVAS_APP,
-        originatingPath: `#/${pathname}${search}`,
-      },
-    });
-  }, [pathname, search, stateTransferService]);
-
-  return <Component {...props} createNewEmbeddable={createNewEmbeddable} />;
-};
+export * from './element_menu.component';
diff --git a/x-pack/plugins/canvas/public/components/workpad_header/element_menu/index.ts b/x-pack/plugins/canvas/public/components/workpad_header/element_menu/index.ts
index 52c8daece7690..037bb84b0cdba 100644
--- a/x-pack/plugins/canvas/public/components/workpad_header/element_menu/index.ts
+++ b/x-pack/plugins/canvas/public/components/workpad_header/element_menu/index.ts
@@ -5,5 +5,4 @@
  * 2.0.
  */
 
-export { ElementMenu } from './element_menu';
-export { ElementMenu as ElementMenuComponent } from './element_menu.component';
+export { ElementMenu } from './element_menu.component';
diff --git a/x-pack/plugins/canvas/public/components/workpad_header/workpad_header.component.tsx b/x-pack/plugins/canvas/public/components/workpad_header/workpad_header.component.tsx
index f031d7c263199..b84e4faf2925e 100644
--- a/x-pack/plugins/canvas/public/components/workpad_header/workpad_header.component.tsx
+++ b/x-pack/plugins/canvas/public/components/workpad_header/workpad_header.component.tsx
@@ -27,6 +27,7 @@ import { ElementMenu } from './element_menu';
 import { ShareMenu } from './share_menu';
 import { ViewMenu } from './view_menu';
 import { LabsControl } from './labs_control';
+import { EditorMenu } from './editor_menu';
 
 const strings = {
   getFullScreenButtonAriaLabel: () =>
@@ -160,24 +161,22 @@ export const WorkpadHeader: FC<Props> = ({
       <EuiFlexGroup
         gutterSize="none"
         alignItems="center"
-        justifyContent="spaceBetween"
         className="canvasLayout__stageHeaderInner"
       >
+        {isWriteable && (
+          <EuiFlexItem grow={false}>
+            <SolutionToolbar>
+              {{
+                primaryActionButton: <ElementMenu addElement={addElement} elements={elements} />,
+                quickButtonGroup: <QuickButtonGroup buttons={quickButtons} />,
+                addFromLibraryButton: <AddFromLibraryButton onClick={showEmbedPanel} />,
+                extraButtons: [<EditorMenu addElement={addElement} />],
+              }}
+            </SolutionToolbar>
+          </EuiFlexItem>
+        )}
         <EuiFlexItem grow={false}>
           <EuiFlexGroup alignItems="center" gutterSize="none">
-            {isWriteable && (
-              <EuiFlexItem>
-                <SolutionToolbar>
-                  {{
-                    primaryActionButton: (
-                      <ElementMenu addElement={addElement} elements={elements} />
-                    ),
-                    quickButtonGroup: <QuickButtonGroup buttons={quickButtons} />,
-                    addFromLibraryButton: <AddFromLibraryButton onClick={showEmbedPanel} />,
-                  }}
-                </SolutionToolbar>
-              </EuiFlexItem>
-            )}
             <EuiFlexItem grow={false}>
               <ViewMenu />
             </EuiFlexItem>
@@ -192,6 +191,7 @@ export const WorkpadHeader: FC<Props> = ({
             </EuiFlexItem>
           </EuiFlexGroup>
         </EuiFlexItem>
+        <EuiFlexItem />
         <EuiFlexItem grow={false}>
           <EuiFlexGroup alignItems="center" gutterSize="s">
             <EuiFlexItem grow={false}>
diff --git a/x-pack/plugins/canvas/public/plugin.tsx b/x-pack/plugins/canvas/public/plugin.tsx
index afaa750c124bf..912055dd47a62 100644
--- a/x-pack/plugins/canvas/public/plugin.tsx
+++ b/x-pack/plugins/canvas/public/plugin.tsx
@@ -8,6 +8,7 @@
 import { BehaviorSubject } from 'rxjs';
 import type { SharePluginSetup } from 'src/plugins/share/public';
 import { ChartsPluginSetup, ChartsPluginStart } from 'src/plugins/charts/public';
+import { VisualizationsStart } from 'src/plugins/visualizations/public';
 import { ReportingStart } from '../../reporting/public';
 import {
   CoreSetup,
@@ -63,6 +64,7 @@ export interface CanvasStartDeps {
   charts: ChartsPluginStart;
   data: DataPublicPluginStart;
   presentationUtil: PresentationUtilPluginStart;
+  visualizations: VisualizationsStart;
   spaces?: SpacesPluginStart;
 }
 
diff --git a/x-pack/plugins/canvas/public/services/index.ts b/x-pack/plugins/canvas/public/services/index.ts
index f4292810b8089..ed55f919e4c76 100644
--- a/x-pack/plugins/canvas/public/services/index.ts
+++ b/x-pack/plugins/canvas/public/services/index.ts
@@ -17,6 +17,7 @@ import { CanvasNavLinkService } from './nav_link';
 import { CanvasNotifyService } from './notify';
 import { CanvasPlatformService } from './platform';
 import { CanvasReportingService } from './reporting';
+import { CanvasVisualizationsService } from './visualizations';
 import { CanvasWorkpadService } from './workpad';
 
 export interface CanvasPluginServices {
@@ -28,6 +29,7 @@ export interface CanvasPluginServices {
   notify: CanvasNotifyService;
   platform: CanvasPlatformService;
   reporting: CanvasReportingService;
+  visualizations: CanvasVisualizationsService;
   workpad: CanvasWorkpadService;
 }
 
@@ -44,4 +46,6 @@ export const useNavLinkService = () => (() => pluginServices.getHooks().navLink.
 export const useNotifyService = () => (() => pluginServices.getHooks().notify.useService())();
 export const usePlatformService = () => (() => pluginServices.getHooks().platform.useService())();
 export const useReportingService = () => (() => pluginServices.getHooks().reporting.useService())();
+export const useVisualizationsService = () =>
+  (() => pluginServices.getHooks().visualizations.useService())();
 export const useWorkpadService = () => (() => pluginServices.getHooks().workpad.useService())();
diff --git a/x-pack/plugins/canvas/public/services/kibana/index.ts b/x-pack/plugins/canvas/public/services/kibana/index.ts
index 1eb010e8d6f9d..91767947bc0a6 100644
--- a/x-pack/plugins/canvas/public/services/kibana/index.ts
+++ b/x-pack/plugins/canvas/public/services/kibana/index.ts
@@ -22,6 +22,7 @@ import { navLinkServiceFactory } from './nav_link';
 import { notifyServiceFactory } from './notify';
 import { platformServiceFactory } from './platform';
 import { reportingServiceFactory } from './reporting';
+import { visualizationsServiceFactory } from './visualizations';
 import { workpadServiceFactory } from './workpad';
 
 export { customElementServiceFactory } from './custom_element';
@@ -31,6 +32,7 @@ export { labsServiceFactory } from './labs';
 export { notifyServiceFactory } from './notify';
 export { platformServiceFactory } from './platform';
 export { reportingServiceFactory } from './reporting';
+export { visualizationsServiceFactory } from './visualizations';
 export { workpadServiceFactory } from './workpad';
 
 export const pluginServiceProviders: PluginServiceProviders<
@@ -45,6 +47,7 @@ export const pluginServiceProviders: PluginServiceProviders<
   notify: new PluginServiceProvider(notifyServiceFactory),
   platform: new PluginServiceProvider(platformServiceFactory),
   reporting: new PluginServiceProvider(reportingServiceFactory),
+  visualizations: new PluginServiceProvider(visualizationsServiceFactory),
   workpad: new PluginServiceProvider(workpadServiceFactory),
 };
 
diff --git a/x-pack/plugins/canvas/public/services/kibana/visualizations.ts b/x-pack/plugins/canvas/public/services/kibana/visualizations.ts
new file mode 100644
index 0000000000000..e319ec1c1f427
--- /dev/null
+++ b/x-pack/plugins/canvas/public/services/kibana/visualizations.ts
@@ -0,0 +1,21 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { KibanaPluginServiceFactory } from '../../../../../../src/plugins/presentation_util/public';
+import { CanvasStartDeps } from '../../plugin';
+import { CanvasVisualizationsService } from '../visualizations';
+
+export type VisualizationsServiceFactory = KibanaPluginServiceFactory<
+  CanvasVisualizationsService,
+  CanvasStartDeps
+>;
+
+export const visualizationsServiceFactory: VisualizationsServiceFactory = ({ startPlugins }) => ({
+  showNewVisModal: startPlugins.visualizations.showNewVisModal,
+  getByGroup: startPlugins.visualizations.getByGroup,
+  getAliases: startPlugins.visualizations.getAliases,
+});
diff --git a/x-pack/plugins/canvas/public/services/stubs/index.ts b/x-pack/plugins/canvas/public/services/stubs/index.ts
index 06a5ff49e9c04..2216013a29c12 100644
--- a/x-pack/plugins/canvas/public/services/stubs/index.ts
+++ b/x-pack/plugins/canvas/public/services/stubs/index.ts
@@ -22,6 +22,7 @@ import { navLinkServiceFactory } from './nav_link';
 import { notifyServiceFactory } from './notify';
 import { platformServiceFactory } from './platform';
 import { reportingServiceFactory } from './reporting';
+import { visualizationsServiceFactory } from './visualizations';
 import { workpadServiceFactory } from './workpad';
 
 export { customElementServiceFactory } from './custom_element';
@@ -31,6 +32,7 @@ export { navLinkServiceFactory } from './nav_link';
 export { notifyServiceFactory } from './notify';
 export { platformServiceFactory } from './platform';
 export { reportingServiceFactory } from './reporting';
+export { visualizationsServiceFactory } from './visualizations';
 export { workpadServiceFactory } from './workpad';
 
 export const pluginServiceProviders: PluginServiceProviders<CanvasPluginServices> = {
@@ -42,6 +44,7 @@ export const pluginServiceProviders: PluginServiceProviders<CanvasPluginServices
   notify: new PluginServiceProvider(notifyServiceFactory),
   platform: new PluginServiceProvider(platformServiceFactory),
   reporting: new PluginServiceProvider(reportingServiceFactory),
+  visualizations: new PluginServiceProvider(visualizationsServiceFactory),
   workpad: new PluginServiceProvider(workpadServiceFactory),
 };
 
diff --git a/x-pack/plugins/canvas/public/services/stubs/visualizations.ts b/x-pack/plugins/canvas/public/services/stubs/visualizations.ts
new file mode 100644
index 0000000000000..4c5525aea143a
--- /dev/null
+++ b/x-pack/plugins/canvas/public/services/stubs/visualizations.ts
@@ -0,0 +1,19 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { PluginServiceFactory } from '../../../../../../src/plugins/presentation_util/public';
+import { CanvasVisualizationsService } from '../visualizations';
+
+type VisualizationsServiceFactory = PluginServiceFactory<CanvasVisualizationsService>;
+
+const noop = (..._args: any[]): any => {};
+
+export const visualizationsServiceFactory: VisualizationsServiceFactory = () => ({
+  showNewVisModal: noop,
+  getByGroup: noop,
+  getAliases: noop,
+});
diff --git a/x-pack/plugins/canvas/public/services/visualizations.ts b/x-pack/plugins/canvas/public/services/visualizations.ts
new file mode 100644
index 0000000000000..c602b1dd39f3d
--- /dev/null
+++ b/x-pack/plugins/canvas/public/services/visualizations.ts
@@ -0,0 +1,14 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { VisualizationsStart } from '../../../../../src/plugins/visualizations/public';
+
+export interface CanvasVisualizationsService {
+  showNewVisModal: VisualizationsStart['showNewVisModal'];
+  getByGroup: VisualizationsStart['getByGroup'];
+  getAliases: VisualizationsStart['getAliases'];
+}