diff --git a/x-pack/plugins/drilldowns/public/components/list_manage_drilldowns/i18n.ts b/x-pack/plugins/drilldowns/public/components/list_manage_drilldowns/i18n.ts
new file mode 100644
index 0000000000000..fbc7c9dcfb4a1
--- /dev/null
+++ b/x-pack/plugins/drilldowns/public/components/list_manage_drilldowns/i18n.ts
@@ -0,0 +1,36 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { i18n } from '@kbn/i18n';
+
+export const txtCreateDrilldown = i18n.translate(
+ 'xpack.drilldowns.components.ListManageDrilldowns.createDrilldownButtonLabel',
+ {
+ defaultMessage: 'Create new',
+ }
+);
+
+export const txtEditDrilldown = i18n.translate(
+ 'xpack.drilldowns.components.ListManageDrilldowns.editDrilldownButtonLabel',
+ {
+ defaultMessage: 'Edit',
+ }
+);
+
+export const txtDeleteDrilldowns = (count: number) =>
+ i18n.translate('xpack.drilldowns.components.ListManageDrilldowns.deleteDrilldownsButtonLabel', {
+ defaultMessage: 'Delete ({count})',
+ values: {
+ count,
+ },
+ });
+
+export const txtSelectDrilldown = i18n.translate(
+ 'xpack.drilldowns.components.ListManageDrilldowns.selectThisDrilldownCheckboxLabel',
+ {
+ defaultMessage: 'Select this drilldown',
+ }
+);
diff --git a/x-pack/plugins/drilldowns/public/components/list_manage_drilldowns/index.tsx b/x-pack/plugins/drilldowns/public/components/list_manage_drilldowns/index.tsx
new file mode 100644
index 0000000000000..82b6ce27af6d4
--- /dev/null
+++ b/x-pack/plugins/drilldowns/public/components/list_manage_drilldowns/index.tsx
@@ -0,0 +1,7 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export * from './list_manage_drilldowns';
diff --git a/x-pack/plugins/drilldowns/public/components/list_manage_drilldowns/list_manage_drilldowns.story.tsx b/x-pack/plugins/drilldowns/public/components/list_manage_drilldowns/list_manage_drilldowns.story.tsx
new file mode 100644
index 0000000000000..ae1b063449928
--- /dev/null
+++ b/x-pack/plugins/drilldowns/public/components/list_manage_drilldowns/list_manage_drilldowns.story.tsx
@@ -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;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import * as React from 'react';
+import { storiesOf } from '@storybook/react';
+import { ListManageDrilldowns } from './list_manage_drilldowns';
+import { drilldowns } from './test_data';
+
+storiesOf('components/ListManageDrilldowns', module).add('default', () => (
+
+));
diff --git a/x-pack/plugins/drilldowns/public/components/list_manage_drilldowns/list_manage_drilldowns.test.tsx b/x-pack/plugins/drilldowns/public/components/list_manage_drilldowns/list_manage_drilldowns.test.tsx
new file mode 100644
index 0000000000000..2ad83f684b339
--- /dev/null
+++ b/x-pack/plugins/drilldowns/public/components/list_manage_drilldowns/list_manage_drilldowns.test.tsx
@@ -0,0 +1,61 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React from 'react';
+import { cleanup, fireEvent, render } from '@testing-library/react';
+import '@testing-library/jest-dom/extend-expect'; // TODO: this should be global
+import { drilldowns } from './test_data';
+import { ListManageDrilldowns, TEST_SUBJ_DRILLDOWN_ITEM } from './list_manage_drilldowns';
+
+// TODO: for some reason global cleanup from RTL doesn't work
+// afterEach is not available for it globally during setup
+afterEach(cleanup);
+
+test('Render list of drilldowns', () => {
+ const screen = render();
+ expect(screen.getAllByTestId(TEST_SUBJ_DRILLDOWN_ITEM)).toHaveLength(drilldowns.length);
+});
+
+test('Emit onEdit() when clicking on edit drilldown', () => {
+ const fn = jest.fn();
+ const screen = render();
+
+ const editButtons = screen.getAllByText('Edit');
+ expect(editButtons).toHaveLength(drilldowns.length);
+ fireEvent.click(editButtons[1]);
+ expect(fn).toBeCalledWith(drilldowns[1].id);
+});
+
+test('Emit onCreate() when clicking on create drilldown', () => {
+ const fn = jest.fn();
+ const screen = render();
+ fireEvent.click(screen.getByText('Create new'));
+ expect(fn).toBeCalled();
+});
+
+test('Delete button is not visible when non is selected', () => {
+ const fn = jest.fn();
+ const screen = render();
+ expect(screen.queryByText(/Delete/i)).not.toBeInTheDocument();
+ expect(screen.queryByText(/Create/i)).toBeInTheDocument();
+});
+
+test('Can delete drilldowns', () => {
+ const fn = jest.fn();
+ const screen = render();
+
+ const checkboxes = screen.getAllByLabelText(/Select this drilldown/i);
+ expect(checkboxes).toHaveLength(3);
+
+ fireEvent.click(checkboxes[1]);
+ fireEvent.click(checkboxes[2]);
+
+ expect(screen.queryByText(/Create/i)).not.toBeInTheDocument();
+
+ fireEvent.click(screen.getByText(/Delete \(2\)/i));
+
+ expect(fn).toBeCalledWith([drilldowns[1].id, drilldowns[2].id]);
+});
diff --git a/x-pack/plugins/drilldowns/public/components/list_manage_drilldowns/list_manage_drilldowns.tsx b/x-pack/plugins/drilldowns/public/components/list_manage_drilldowns/list_manage_drilldowns.tsx
new file mode 100644
index 0000000000000..71e566d1020f5
--- /dev/null
+++ b/x-pack/plugins/drilldowns/public/components/list_manage_drilldowns/list_manage_drilldowns.tsx
@@ -0,0 +1,97 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import {
+ EuiBasicTable,
+ EuiBasicTableColumn,
+ EuiButton,
+ EuiButtonEmpty,
+ EuiSpacer,
+} from '@elastic/eui';
+import React, { useState } from 'react';
+import {
+ txtEditDrilldown,
+ txtCreateDrilldown,
+ txtDeleteDrilldowns,
+ txtSelectDrilldown,
+} from './i18n';
+
+// TODO: interface is temporary
+export interface DrilldownListItem {
+ id: string;
+ actionTypeDisplayName: string;
+ name: string;
+}
+
+export interface ListManageDrilldownsProps {
+ drilldowns: DrilldownListItem[];
+
+ onEdit?: (id: string) => void;
+ onCreate?: () => void;
+ onDelete?: (ids: string[]) => void;
+}
+
+const noop = () => {};
+
+export const TEST_SUBJ_DRILLDOWN_ITEM = 'list-manage-drilldowns-item';
+
+export function ListManageDrilldowns({
+ drilldowns,
+ onEdit = noop,
+ onCreate = noop,
+ onDelete = noop,
+}: ListManageDrilldownsProps) {
+ const [selectedDrilldowns, setSelectedDrilldowns] = useState([]);
+
+ const columns: Array> = [
+ {
+ field: 'name',
+ name: 'Name',
+ truncateText: true,
+ },
+ {
+ field: 'actionTypeDisplayName',
+ name: 'Action',
+ truncateText: true,
+ },
+ {
+ render: (drilldown: DrilldownListItem) => (
+ onEdit(drilldown.id)}>
+ {txtEditDrilldown}
+
+ ),
+ },
+ ];
+
+ return (
+ <>
+ {
+ setSelectedDrilldowns(selection.map(drilldown => drilldown.id));
+ },
+ selectableMessage: () => txtSelectDrilldown,
+ }}
+ rowProps={{ 'data-test-subj': TEST_SUBJ_DRILLDOWN_ITEM }}
+ hasActions={true}
+ />
+
+ {selectedDrilldowns.length === 0 ? (
+ onCreate()}>
+ {txtCreateDrilldown}
+
+ ) : (
+ onDelete(selectedDrilldowns)}>
+ {txtDeleteDrilldowns(selectedDrilldowns.length)}
+
+ )}
+ >
+ );
+}
diff --git a/x-pack/plugins/drilldowns/public/components/list_manage_drilldowns/test_data.ts b/x-pack/plugins/drilldowns/public/components/list_manage_drilldowns/test_data.ts
new file mode 100644
index 0000000000000..862c3efafa189
--- /dev/null
+++ b/x-pack/plugins/drilldowns/public/components/list_manage_drilldowns/test_data.ts
@@ -0,0 +1,11 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export const drilldowns = [
+ { id: '1', actionTypeDisplayName: 'Dashboard', name: 'Drilldown 1' },
+ { id: '2', actionTypeDisplayName: 'Dashboard', name: 'Drilldown 2' },
+ { id: '3', actionTypeDisplayName: 'Dashboard', name: 'Drilldown 3' },
+];