diff --git a/package.json b/package.json
index 90d05f9c7be..cc55d3cedc3 100644
--- a/package.json
+++ b/package.json
@@ -75,6 +75,7 @@
"prop-types": "^15.6.0",
"react-beautiful-dnd": "^13.1.0",
"react-dropzone": "^11.5.3",
+ "react-element-to-jsx-string": "^14.3.4",
"react-focus-on": "^3.5.4",
"react-input-autosize": "^3.0.0",
"react-is": "^17.0.2",
diff --git a/scripts/babel/proptypes-from-ts-props/index.js b/scripts/babel/proptypes-from-ts-props/index.js
index 5ee71b02c59..2af5e0b24b8 100644
--- a/scripts/babel/proptypes-from-ts-props/index.js
+++ b/scripts/babel/proptypes-from-ts-props/index.js
@@ -1035,6 +1035,8 @@ function getPropTypesForNode(node, optional, state) {
return propType;
}
+const typescriptExtensions = new Set(['', '.ts', '.tsx']);
+
// typeDefinitionExtractors is a mapping of [ast_node_type: func] which is used to find type definitions
// these definitions come from four sources:
// - import statements
@@ -1054,9 +1056,11 @@ const typeDefinitionExtractors = {
const { fs, sourceFilename, parse, state } = extractionOptions;
const importPath = node.source.value;
const isPathRelative = /^\.{1,2}\//.test(importPath);
+ const pathExtension = path.extname(importPath);
+ const isImportTypecript = typescriptExtensions.has(pathExtension);
// only process relative imports for typescript definitions (avoid node_modules)
- if (isPathRelative) {
+ if (isPathRelative && isImportTypecript) {
// find the variable names being imported
const importedTypeNames = node.specifiers.map(specifier => {
switch (specifier.type) {
diff --git a/scripts/babel/proptypes-from-ts-props/index.test.ts b/scripts/babel/proptypes-from-ts-props/index.test.ts
index 9a96aca23ee..3d519e69409 100644
--- a/scripts/babel/proptypes-from-ts-props/index.test.ts
+++ b/scripts/babel/proptypes-from-ts-props/index.test.ts
@@ -2514,6 +2514,35 @@ let something: any;
expect(result.code).toBe('let something;');
});
+
+ it('skips non-typescript imports', () => {
+ const result = transform(
+ `
+import something from './somewhere.txt';
+`,
+ {
+ ...babelOptions,
+ plugins: [
+ [
+ './scripts/babel/proptypes-from-ts-props',
+ {
+ fs: {
+ existsSync: () => true,
+ statSync: () => ({ isDirectory: () => false }),
+ readFileSync: () => {
+ return Buffer.from(`
+ this is not valid javascript
+ `);
+ },
+ },
+ },
+ ],
+ ],
+ }
+ );
+
+ expect(result.code).toBe("export {};");
+ });
});
});
});
diff --git a/src-docs/src/components/guide_section/guide_section.tsx b/src-docs/src/components/guide_section/guide_section.tsx
index 755eca9a737..873ebfd8d92 100644
--- a/src-docs/src/components/guide_section/guide_section.tsx
+++ b/src-docs/src/components/guide_section/guide_section.tsx
@@ -48,6 +48,10 @@ export const GuideSectionCodeTypesMap = {
name: 'demoTSX',
displayName: 'Demo TS',
},
+ STRING_JS: {
+ name: 'demoJS',
+ displayName: 'Demo JS',
+ },
SNIPPET: {
name: 'snippet',
displayName: 'Snippet',
diff --git a/src-docs/src/components/guide_section/guide_section_parts/guide_section_code.tsx b/src-docs/src/components/guide_section/guide_section_parts/guide_section_code.tsx
index c93bfa5c512..a85e3dc0f7b 100644
--- a/src-docs/src/components/guide_section/guide_section_parts/guide_section_code.tsx
+++ b/src-docs/src/components/guide_section/guide_section_parts/guide_section_code.tsx
@@ -50,7 +50,11 @@ export const GuideSectionExampleCode: FunctionComponent
return (
<>
diff --git a/src-docs/src/components/guide_section/guide_section_types.tsx b/src-docs/src/components/guide_section/guide_section_types.tsx
index 0597b72af2a..e49f40c582e 100644
--- a/src-docs/src/components/guide_section/guide_section_types.tsx
+++ b/src-docs/src/components/guide_section/guide_section_types.tsx
@@ -3,4 +3,5 @@ export const GuideSectionTypes = {
TSX: 'TSX',
SNIPPET: 'SNIPPET',
SASS: 'SASS',
+ STRING_JS: 'STRING_JS',
};
diff --git a/src-docs/src/images/empty-prompt/404_rainy_cloud_dark.png b/src-docs/src/images/empty-prompt/404_rainy_cloud_dark.png
new file mode 100644
index 00000000000..92ca7064fbb
Binary files /dev/null and b/src-docs/src/images/empty-prompt/404_rainy_cloud_dark.png differ
diff --git a/src-docs/src/images/empty-prompt/404_rainy_cloud_light.png b/src-docs/src/images/empty-prompt/404_rainy_cloud_light.png
new file mode 100644
index 00000000000..9735dc6f757
Binary files /dev/null and b/src-docs/src/images/empty-prompt/404_rainy_cloud_light.png differ
diff --git a/src-docs/src/images/empty-prompt_illustration.svg b/src-docs/src/images/empty-prompt/illustration.svg
similarity index 100%
rename from src-docs/src/images/empty-prompt_illustration.svg
rename to src-docs/src/images/empty-prompt/illustration.svg
diff --git a/src-docs/src/images/empty-prompt/inline-link.svg b/src-docs/src/images/empty-prompt/inline-link.svg
new file mode 100644
index 00000000000..b97e81568a2
--- /dev/null
+++ b/src-docs/src/images/empty-prompt/inline-link.svg
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src-docs/src/images/empty-prompt/no-results--dark.svg b/src-docs/src/images/empty-prompt/no-results--dark.svg
new file mode 100644
index 00000000000..e76cfc10272
--- /dev/null
+++ b/src-docs/src/images/empty-prompt/no-results--dark.svg
@@ -0,0 +1,416 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src-docs/src/images/empty-prompt/no-results--light.svg b/src-docs/src/images/empty-prompt/no-results--light.svg
new file mode 100644
index 00000000000..a2546872380
--- /dev/null
+++ b/src-docs/src/images/empty-prompt/no-results--light.svg
@@ -0,0 +1,416 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src-docs/src/images/empty-prompt/thumbnail_dark_empty_content.svg b/src-docs/src/images/empty-prompt/thumbnail_dark_empty_content.svg
new file mode 100644
index 00000000000..12cd8cc3c78
--- /dev/null
+++ b/src-docs/src/images/empty-prompt/thumbnail_dark_empty_content.svg
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/src-docs/src/images/empty-prompt/thumbnail_dark_page-empty.svg b/src-docs/src/images/empty-prompt/thumbnail_dark_page-empty.svg
new file mode 100644
index 00000000000..b8d0938d3ea
--- /dev/null
+++ b/src-docs/src/images/empty-prompt/thumbnail_dark_page-empty.svg
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src-docs/src/images/empty-prompt/thumbnail_dark_page-multiple.svg b/src-docs/src/images/empty-prompt/thumbnail_dark_page-multiple.svg
new file mode 100644
index 00000000000..9b8b3daf1eb
--- /dev/null
+++ b/src-docs/src/images/empty-prompt/thumbnail_dark_page-multiple.svg
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src-docs/src/images/empty-prompt/thumbnail_dark_page-sidebar.svg b/src-docs/src/images/empty-prompt/thumbnail_dark_page-sidebar.svg
new file mode 100644
index 00000000000..e95232cbc81
--- /dev/null
+++ b/src-docs/src/images/empty-prompt/thumbnail_dark_page-sidebar.svg
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src-docs/src/images/empty-prompt/thumbnail_footer-link.svg b/src-docs/src/images/empty-prompt/thumbnail_footer-link.svg
new file mode 100644
index 00000000000..a5ab9b08b17
--- /dev/null
+++ b/src-docs/src/images/empty-prompt/thumbnail_footer-link.svg
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src-docs/src/images/empty-prompt/thumbnail_horizontal.svg b/src-docs/src/images/empty-prompt/thumbnail_horizontal.svg
new file mode 100644
index 00000000000..ffb40fe5581
--- /dev/null
+++ b/src-docs/src/images/empty-prompt/thumbnail_horizontal.svg
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src-docs/src/images/empty-prompt/thumbnail_icon-do.svg b/src-docs/src/images/empty-prompt/thumbnail_icon-do.svg
new file mode 100644
index 00000000000..3c69daa0cad
--- /dev/null
+++ b/src-docs/src/images/empty-prompt/thumbnail_icon-do.svg
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src-docs/src/images/empty-prompt/thumbnail_icon-dont.svg b/src-docs/src/images/empty-prompt/thumbnail_icon-dont.svg
new file mode 100644
index 00000000000..6301ae00261
--- /dev/null
+++ b/src-docs/src/images/empty-prompt/thumbnail_icon-dont.svg
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src-docs/src/images/empty-prompt/thumbnail_illustration.svg b/src-docs/src/images/empty-prompt/thumbnail_illustration.svg
new file mode 100644
index 00000000000..7f61ef8bea3
--- /dev/null
+++ b/src-docs/src/images/empty-prompt/thumbnail_illustration.svg
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src-docs/src/images/empty-prompt/thumbnail_inline-link.svg b/src-docs/src/images/empty-prompt/thumbnail_inline-link.svg
new file mode 100644
index 00000000000..b6f0eb72f4a
--- /dev/null
+++ b/src-docs/src/images/empty-prompt/thumbnail_inline-link.svg
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src-docs/src/images/empty-prompt/thumbnail_light_empty_content.svg b/src-docs/src/images/empty-prompt/thumbnail_light_empty_content.svg
new file mode 100644
index 00000000000..0ac477bc5c0
--- /dev/null
+++ b/src-docs/src/images/empty-prompt/thumbnail_light_empty_content.svg
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/src-docs/src/images/empty-prompt/thumbnail_light_page-empty.svg b/src-docs/src/images/empty-prompt/thumbnail_light_page-empty.svg
new file mode 100644
index 00000000000..4a5fc21496e
--- /dev/null
+++ b/src-docs/src/images/empty-prompt/thumbnail_light_page-empty.svg
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src-docs/src/images/empty-prompt/thumbnail_light_page-multiple.svg b/src-docs/src/images/empty-prompt/thumbnail_light_page-multiple.svg
new file mode 100644
index 00000000000..b88215ff5cf
--- /dev/null
+++ b/src-docs/src/images/empty-prompt/thumbnail_light_page-multiple.svg
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src-docs/src/images/empty-prompt/thumbnail_light_page-sidebar.svg b/src-docs/src/images/empty-prompt/thumbnail_light_page-sidebar.svg
new file mode 100644
index 00000000000..eecf7c40535
--- /dev/null
+++ b/src-docs/src/images/empty-prompt/thumbnail_light_page-sidebar.svg
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src-docs/src/images/empty-prompt/thumbnail_multiple-do.svg b/src-docs/src/images/empty-prompt/thumbnail_multiple-do.svg
new file mode 100644
index 00000000000..14cd1a401c2
--- /dev/null
+++ b/src-docs/src/images/empty-prompt/thumbnail_multiple-do.svg
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src-docs/src/images/empty-prompt/thumbnail_multiple-dont.svg b/src-docs/src/images/empty-prompt/thumbnail_multiple-dont.svg
new file mode 100644
index 00000000000..2e7f084d816
--- /dev/null
+++ b/src-docs/src/images/empty-prompt/thumbnail_multiple-dont.svg
@@ -0,0 +1,82 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src-docs/src/images/empty-prompt/thumbnail_vertical.svg b/src-docs/src/images/empty-prompt/thumbnail_vertical.svg
new file mode 100644
index 00000000000..48e8606bb8a
--- /dev/null
+++ b/src-docs/src/images/empty-prompt/thumbnail_vertical.svg
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src-docs/src/images/empty-prompt/vertical.svg b/src-docs/src/images/empty-prompt/vertical.svg
new file mode 100644
index 00000000000..75dbf9dbf18
--- /dev/null
+++ b/src-docs/src/images/empty-prompt/vertical.svg
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src-docs/src/images/empty-prompt_anatomy.svg b/src-docs/src/images/empty-prompt_anatomy.svg
deleted file mode 100644
index 28a0bb62eb4..00000000000
--- a/src-docs/src/images/empty-prompt_anatomy.svg
+++ /dev/null
@@ -1,37 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src-docs/src/views/_index.scss b/src-docs/src/views/_index.scss
index 2537fd6566c..57cb58195e3 100644
--- a/src-docs/src/views/_index.scss
+++ b/src-docs/src/views/_index.scss
@@ -6,6 +6,7 @@ $guideDemoHighlightColor: transparentize($euiColorPrimary, .9);
@import './datagrid/datagrid';
@import './date_picker/date_picker';
@import './elastic_charts/index';
+@import './empty_prompt/empty_prompt';
@import './flex/flex';
@import './horizontal_rule/horizontal_rule';
@import './page/page';
diff --git a/src-docs/src/views/empty_prompt/_empty_prompt.scss b/src-docs/src/views/empty_prompt/_empty_prompt.scss
new file mode 100644
index 00000000000..c89e4026a58
--- /dev/null
+++ b/src-docs/src/views/empty_prompt/_empty_prompt.scss
@@ -0,0 +1,29 @@
+.guideDemo__emptyPromptPanelPicker {
+ width: 100%;
+ gap: $euiSizeXL; // sass-lint:disable-line no-misspelled-properties
+}
+
+.guideDemo__emptyPromptPanelPickerThumbBtn {
+ width: 120px;
+ height: auto;
+
+ .euiKeyPadMenuItem__icon {
+ transform: none;
+ margin-bottom: $euiSizeS;
+ }
+}
+
+.guideDemo__emptyPromptPanelPickerThumb {
+ border: $euiBorderThin;
+ border-radius: $euiBorderRadius;
+ overflow: hidden;
+
+ &-isSelected {
+ border-color: $euiColorPrimary;
+ }
+}
+
+.guideDemo__emptyPromptDemoPreview {
+ border: 1px solid $guideDemoHighlightColor;
+ overflow: hidden;
+}
\ No newline at end of file
diff --git a/src-docs/src/views/empty_prompt/_page_template_table.tsx b/src-docs/src/views/empty_prompt/_page_template_table.tsx
index 0df2c03957f..8deb150f2ba 100644
--- a/src-docs/src/views/empty_prompt/_page_template_table.tsx
+++ b/src-docs/src/views/empty_prompt/_page_template_table.tsx
@@ -25,8 +25,7 @@ export default () => (
- Set {'color="plain"'} and
- {'hasBorder={true}'} .
+ Set {'color="subdued"'} .
diff --git a/src-docs/src/views/empty_prompt/_types_of_empty_states.tsx b/src-docs/src/views/empty_prompt/_types_of_empty_states.tsx
new file mode 100644
index 00000000000..812086cac89
--- /dev/null
+++ b/src-docs/src/views/empty_prompt/_types_of_empty_states.tsx
@@ -0,0 +1,399 @@
+import React, { useState, useEffect, useContext } from 'react';
+import reactElementToJSXString from 'react-element-to-jsx-string';
+import classNames from 'classnames';
+import {
+ EuiTitle,
+ EuiImage,
+ EuiSpacer,
+ EuiRadioGroup,
+ EuiEmptyPrompt,
+ EuiSplitPanel,
+ EuiKeyPadMenu,
+ EuiFlexItem,
+ EuiRadioGroupOption,
+ EuiPageTemplate,
+ EuiFlexGrid,
+ EuiPanel,
+ EuiKeyPadMenuItem,
+ EuiDescriptionList,
+ EuiDescriptionListTitle,
+ EuiDescriptionListDescription,
+ EuiLoadingSpinner,
+} from '../../../../src/components';
+import { ThemeContext } from '../../components/with_theme';
+import { typesOfPanelColors } from './_types_of_panel_colors';
+// @ts-ignore Importing from JS file
+import { typesOfUseCases } from './_types_of_use_cases';
+import { useIsWithinBreakpoints } from '../../../../src/services/hooks';
+import { GuideSection } from '../../components/guide_section/guide_section';
+import { GuideSectionTypes } from '../../components/guide_section/guide_section_types';
+
+// images dark
+import darkSidebar from '../../images/empty-prompt/thumbnail_dark_page-sidebar.svg';
+import darkEmpty from '../../images/empty-prompt/thumbnail_dark_page-empty.svg';
+import darkMultiple from '../../images/empty-prompt/thumbnail_dark_page-multiple.svg';
+import darkContent from '../../images/empty-prompt/thumbnail_dark_empty_content.svg';
+
+// images light
+import lightSidebar from '../../images/empty-prompt/thumbnail_light_page-sidebar.svg';
+import lightEmpty from '../../images/empty-prompt/thumbnail_light_page-empty.svg';
+import lightMultiple from '../../images/empty-prompt/thumbnail_light_page-multiple.svg';
+import lightContent from '../../images/empty-prompt/thumbnail_light_empty_content.svg';
+
+import sideNavSvg from '../../images/side_nav.svg';
+import singleSvg from '../../images/single.svg';
+
+export default () => {
+ const themeContext = useContext(ThemeContext);
+
+ /**
+ * Setup theme based on current light/dark theme
+ */
+ const isDarkTheme = themeContext.theme.includes('dark');
+
+ const useCasesOptions: EuiRadioGroupOption[] = Object.values(
+ typesOfUseCases
+ ).map((item: any) => {
+ return {
+ id: item.id,
+ label: item.label,
+ };
+ });
+
+ const errorValue = typesOfUseCases.error.id;
+ const [radioUseCaseId, setRadioUseCaseId] = useState<
+ EuiRadioGroupOption['id']
+ >(typesOfUseCases.firstUse.id);
+
+ const [panelProps, setPanelProps] = useState({ color: 'plain' });
+ const [thumbnail, setThumbnail] = useState('sidebar');
+ const [isDisabledMultipleThumb, setIsDisabledMultipleThumb] = useState(false);
+
+ const onSelectThumbnail = (thumbnailName: string) => {
+ setThumbnail(thumbnailName);
+ };
+
+ const isSidebar = thumbnail === 'sidebar';
+ const isEmpty = thumbnail === 'empty';
+ const isMultiple = thumbnail === 'multiple';
+
+ const onChangeUseCase = (id: EuiRadioGroupOption['id']) => {
+ setRadioUseCaseId(id);
+ };
+
+ const [
+ visibleRecommendedPanelColorText,
+ setVisibleRecommendedPanelColorText,
+ ] = useState(typesOfPanelColors.subdued.text);
+
+ const isMobileSize = useIsWithinBreakpoints(['xs', 's']);
+
+ const sideNav = (
+
+ );
+
+ useEffect(() => {
+ if (isSidebar && radioUseCaseId !== errorValue) {
+ setVisibleRecommendedPanelColorText(typesOfPanelColors.subdued.text);
+ setPanelProps(typesOfPanelColors.subdued.props);
+ } else if (isEmpty && radioUseCaseId !== errorValue) {
+ setVisibleRecommendedPanelColorText(typesOfPanelColors.plain.text);
+ setPanelProps(typesOfPanelColors.plain.props);
+ } else if (isMultiple && radioUseCaseId !== errorValue) {
+ setVisibleRecommendedPanelColorText(typesOfPanelColors.multiple.text);
+ setPanelProps(typesOfPanelColors.multiple.props);
+ } else {
+ setVisibleRecommendedPanelColorText(typesOfPanelColors.error.text);
+ setPanelProps(typesOfPanelColors.error.props);
+ }
+
+ if (
+ radioUseCaseId === 'noPrivileges' ||
+ radioUseCaseId === 'errorPages' ||
+ radioUseCaseId === 'forbidden' ||
+ radioUseCaseId === 'noResults'
+ ) {
+ // if the `multiple` thumb is selected when we changing the use case for `noPrivileges`, `errorPages`, `forbidden` or `noResults` we change the selection for the first thumb
+ // because these use cases don't work for a `multiple` page layout
+ if (thumbnail === 'multiple') {
+ setThumbnail('sidebar');
+ }
+
+ setIsDisabledMultipleThumb(true);
+ } else {
+ setIsDisabledMultipleThumb(false);
+ }
+ }, [radioUseCaseId, errorValue, isSidebar, isEmpty, isMultiple, thumbnail]);
+
+ const currentUseCaseInfo = typesOfUseCases[radioUseCaseId].info;
+
+ const currentUseCaseExample = typesOfUseCases[radioUseCaseId].example;
+
+ let icon;
+
+ if (currentUseCaseExample.iconLoading && radioUseCaseId === 'loading') {
+ // if is multiple just show a loading spinner
+ if (isMultiple) {
+ icon = { icon: };
+ } else {
+ icon = {
+ icon: currentUseCaseExample.iconLoading,
+ };
+ }
+ } else if (currentUseCaseExample.iconType) {
+ icon = { iconType: currentUseCaseExample.iconType };
+ } else {
+ const iconImg: string = isDarkTheme
+ ? currentUseCaseExample.iconDark!
+ : currentUseCaseExample.iconLight!;
+
+ icon = {
+ icon: ,
+ };
+ }
+
+ const layout = currentUseCaseExample.layout
+ ? { layout: currentUseCaseExample.layout }
+ : { layout: 'vertical' };
+
+ const titleSize = isMultiple ? 's' : 'm';
+ const multipleLoadingPanel = isMultiple && radioUseCaseId === 'loading';
+
+ const multipleLoadingPanelStyles = multipleLoadingPanel && {
+ style: {
+ minWidth: '100%',
+ width: '100%',
+ },
+ };
+
+ const body = currentUseCaseExample.body && {
+ body: currentUseCaseExample.body,
+ };
+
+ const actions = currentUseCaseExample.actions && {
+ actions: currentUseCaseExample.actions,
+ };
+
+ const euiEmptyPromptPreview = (
+
+ );
+
+ let demo;
+
+ if (isSidebar) {
+ demo = (
+
+ {euiEmptyPromptPreview}
+
+ );
+ } else if (isEmpty) {
+ demo = (
+
+ {euiEmptyPromptPreview}
+
+ );
+ } else if (isMultiple) {
+ demo = (
+
+
+ {euiEmptyPromptPreview}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+ }
+
+ const code = reactElementToJSXString(demo);
+
+ return (
+ <>
+
+
+
+ What is the use case?
+
+ ),
+ }}
+ />
+
+
+
+
+
+ What is the page template?
+
+
+
+
+
+
+ onSelectThumbnail('sidebar')}
+ >
+
+
+ onSelectThumbnail('empty')}
+ >
+
+
+ {!isDisabledMultipleThumb && (
+ onSelectThumbnail('multiple')}
+ >
+
+
+ )}
+
+
+
+
+
+
+
+ Description
+
+ {currentUseCaseInfo.description}
+
+
+ Goal
+
+ {currentUseCaseInfo.goal}
+
+
+ {currentUseCaseInfo.action && (
+ <>
+ Action
+
+ {currentUseCaseInfo.action}
+
+ >
+ )}
+
+
+ Recommended panel color
+
+
+ {visibleRecommendedPanelColorText}
+
+
+
+ {/* */}
+
+
+
+ {demo}}
+ source={[
+ {
+ type: GuideSectionTypes.STRING_JS,
+ code: code,
+ },
+ ]}
+ />
+ >
+ );
+};
diff --git a/src-docs/src/views/empty_prompt/_types_of_panel_colors.tsx b/src-docs/src/views/empty_prompt/_types_of_panel_colors.tsx
new file mode 100644
index 00000000000..0cba5330baf
--- /dev/null
+++ b/src-docs/src/views/empty_prompt/_types_of_panel_colors.tsx
@@ -0,0 +1,64 @@
+import React from 'react';
+import { EuiCode } from '../../../../src/components';
+
+export const typesOfPanelColors: any = {
+ subdued: {
+ id: 'subdued',
+ text: (
+ <>
+
+ Set {'color="subdued"'} to make users not getting
+ distracted and focus on the content.
+
+
+ Consider the transparent color if the empty prompt is contained in
+ another component.
+
+ >
+ ),
+ props: { color: 'subdued' },
+ },
+ plain: {
+ id: 'plain',
+ text: (
+ <>
+
+ Set {'color="plain”'} to make users getting focus
+ on the content
+
+
+ Consider the transparent color if the empty prompt is contained in
+ another component.
+
+ >
+ ),
+ props: { color: 'plain' },
+ },
+ error: {
+ id: 'error',
+ text: (
+
+ Set {'color="danger'} to emphasize that an error
+ happened.
+
+ ),
+ props: { color: 'danger' },
+ },
+ multiple: {
+ id: 'multiple',
+ text: (
+ <>
+
+ Set {'color="plain” and hasBorder={true}'} when you
+ have multiple panels on the page. The other panels should also have
+ borders to ensure consistency.
+
+
+ Consider the transparent color if the empty prompt is contained in
+ another component.
+
+ >
+ ),
+ props: { color: 'plain', hasBorder: true },
+ },
+};
diff --git a/src-docs/src/views/empty_prompt/_types_of_use_cases.tsx b/src-docs/src/views/empty_prompt/_types_of_use_cases.tsx
new file mode 100644
index 00000000000..5153bb39997
--- /dev/null
+++ b/src-docs/src/views/empty_prompt/_types_of_use_cases.tsx
@@ -0,0 +1,290 @@
+import React, { ReactNode } from 'react';
+import {
+ EuiButton,
+ EuiButtonEmpty,
+ EuiLoadingLogo,
+ EuiTitle,
+ EuiLink,
+ EuiFlexGroup,
+ EuiFlexItem,
+ EuiDescriptionList,
+ EuiDescriptionListTitle,
+ EuiDescriptionListDescription,
+ IconType,
+} from '../../../../src/components';
+
+import pageNotFoundLight from '../../images/empty-prompt/404_rainy_cloud_light.png';
+import pageNotFoundDark from '../../images/empty-prompt/404_rainy_cloud_dark.png';
+import noResultsLight from '../../images/empty-prompt/no-results--light.svg';
+import noResultsDark from '../../images/empty-prompt/no-results--dark.svg';
+
+export const typesOfUseCases: {
+ [key: string]: {
+ id: string;
+ label: string;
+ info: {
+ description: ReactNode;
+ goal: ReactNode;
+ action?: ReactNode;
+ };
+ example: {
+ iconLoading?: ReactNode;
+ iconLight?: string;
+ iconDark?: string;
+ iconType?: IconType;
+ title: ReactNode;
+ body?: ReactNode;
+ actions?: ReactNode[];
+ layout?: 'horizontal' | 'vertical';
+ footer?: ReactNode;
+ };
+ footer?: ReactNode;
+ };
+} = {
+ firstUse: {
+ id: 'firstUse',
+ label: 'First time use',
+ info: {
+ description: First time use.
,
+ goal: (
+ <>
+ Help users understand how they can start using the product.
+
+ For no data use cases, consider using a{' '}
+ EuiCard . In Kibana, you
+ just need to pass a no data configuration into your{' '}
+
+ KibanaPageTemplate
+ {' '}
+ to display a specific UI that guides users to add data.
+
+ >
+ ),
+ action: (
+
+ Actions specific to first use. For example: “Add cases”, “Create job”,
+ “Add workpad”.
+
+ ),
+ },
+ example: {
+ iconType: 'logoSecurity',
+ title: Start adding cases ,
+ body: Add a new case or change your filter settings.
,
+ actions: [
+
+ Add a case
+ ,
+ ],
+ },
+ footer: (
+
+
+
+ Want to learn more?
+
+
+
+ Read documentation
+
+
+
+
+
+ Sure you have data?
+
+
+ {}}
+ iconType="refresh"
+ iconSide="right"
+ iconSize="s"
+ flush="both"
+ size="s"
+ >
+ Check for new data
+
+
+
+
+ ),
+ },
+ noPrivileges: {
+ id: 'noPrivileges',
+ label: 'No privileges',
+ info: {
+ description: No privileges to access a feature.
,
+ goal: (
+
+ Help users understand why they don't have privileges to a feature
+ and what actions to take to get access.
+
+ ),
+ action: Request permission.
,
+ },
+
+ example: {
+ iconType: 'lock',
+ title: Contact your administrator for access ,
+ body: To view cases in this space, you need additional privileges.
,
+ },
+ },
+ noResults: {
+ id: 'noResults',
+ label: 'No results',
+ info: {
+ description: No results matched the search.
,
+ goal: (
+
+ Help users understand why the search didn't match any results and
+ what they can do to get better results.
+
+ ),
+ action: (
+
+ Refresh, try again, reformat the data, or try another action specific
+ to the error.
+
+ ),
+ },
+ example: {
+ iconLight: noResultsLight,
+ iconDark: noResultsDark,
+ title: No results match your search criteria ,
+ layout: 'horizontal',
+ body: (
+
+
+ Expand your time range
+
+
+ Try searching over a longer period of time.
+
+
+ Adjust your query
+
+ Try searching for a different combination of terms.
+
+
+ ),
+ },
+ },
+ error: {
+ id: 'error',
+ label: 'Error loading data',
+ info: {
+ description: An error happened when loading the data.
,
+ goal: (
+
+ Help users understand why they're facing an error and what they
+ can do to solve it.
+
+ ),
+ },
+ example: {
+ iconType: 'alert',
+ title: Unable to load your dashboards ,
+ body: (
+
+ There was a problem loading the Dashboard application. Contact your
+ administrator for help.
+
+ ),
+ },
+ },
+ errorPages: {
+ id: 'errorPages',
+ label: 'Error pages (4xx and 5xx)',
+ info: {
+ description: (
+
+ The error pages come from client and server errors — the 4xx and 5xx
+ status code classes.
+
+ ),
+ goal: Help users understand there is a client or server error.
,
+ action: Go home or go back.
,
+ },
+ example: {
+ iconLight: pageNotFoundLight,
+ iconDark: pageNotFoundDark,
+ title: Page not found ,
+ body: (
+
+ Sorry, we can't find the page you're looking for. It might
+ have been removed or renamed, or maybe it never existed.
+
+ ),
+ actions: [
+
+ Go home
+ ,
+
+ Go back
+ ,
+ ],
+ },
+ },
+ licenseUpgrade: {
+ id: 'licenseUpgrade',
+ label: 'License upgrade',
+ info: {
+ description: No license to use a feature.
,
+ goal: (
+
+ Help users understand that they don't have the required license
+ to access a feature and what actions they need to perform to upgrade
+ the license.
+
+ ),
+ action: Start a trial or upgrade the license.
,
+ },
+ example: {
+ iconType: 'logoKibana',
+ title: Do more with Kibana! ,
+ body: (
+
+ Start a free trial or upgrade your license to use anomaly detection.
+
+ ),
+ actions: [
+
+ Upgrade
+ ,
+ Start a free trial ,
+ ],
+ footer: (
+ <>
+
+ Want to learn more?
+
+
+ Read documentation
+
+ >
+ ),
+ },
+ },
+ loading: {
+ id: 'loading',
+ label: 'Loading',
+ info: {
+ description: The page or content is loading.
,
+ goal: Help users understand that the data is loading.
,
+ },
+ example: {
+ iconLoading: ,
+ title: Loading dashboards ,
+ },
+ },
+};
diff --git a/src-docs/src/views/empty_prompt/empty_prompt_error.tsx b/src-docs/src/views/empty_prompt/empty_prompt_error.tsx
index 324aaefa031..c4867bf4671 100644
--- a/src-docs/src/views/empty_prompt/empty_prompt_error.tsx
+++ b/src-docs/src/views/empty_prompt/empty_prompt_error.tsx
@@ -6,7 +6,7 @@ export default () => (
Error loading Dashboards}
+ title={Unable to load your dashboards }
body={
There was an error loading the Dashboard application. Contact your
diff --git a/src-docs/src/views/empty_prompt/empty_prompt_example.js b/src-docs/src/views/empty_prompt/empty_prompt_example.js
index e4745fa0277..16a42229dfd 100644
--- a/src-docs/src/views/empty_prompt/empty_prompt_example.js
+++ b/src-docs/src/views/empty_prompt/empty_prompt_example.js
@@ -163,12 +163,12 @@ export const EmptyPromptExample = {
color prop will also attempt to adjust the{' '}
iconColor and footer color.
- {/* Commenting out for now, as the Guidelines don't yet specify.
+
Read the{' '}
usage guidelines to
better understand when to use certain panel props.
-
*/}
+
diff --git a/src-docs/src/views/empty_prompt/empty_prompt_layout.tsx b/src-docs/src/views/empty_prompt/empty_prompt_layout.tsx
index 6db4c5045c0..eee99f89898 100644
--- a/src-docs/src/views/empty_prompt/empty_prompt_layout.tsx
+++ b/src-docs/src/views/empty_prompt/empty_prompt_layout.tsx
@@ -8,7 +8,7 @@ import {
EuiImage,
} from '../../../../src/components';
-import illustration from '../../images/empty-prompt_illustration.svg';
+import illustration from '../../images/empty-prompt/illustration.svg';
export default () => {
return (
diff --git a/src-docs/src/views/empty_prompt/empty_prompt_multiple_types.tsx b/src-docs/src/views/empty_prompt/empty_prompt_multiple_types.tsx
index 9d7a8c86485..5b510516cd2 100644
--- a/src-docs/src/views/empty_prompt/empty_prompt_multiple_types.tsx
+++ b/src-docs/src/views/empty_prompt/empty_prompt_multiple_types.tsx
@@ -6,10 +6,10 @@ import { GuideSection } from '../../components/guide_section/guide_section';
import { GuideSectionTypes } from '../../components/guide_section/guide_section_types';
import { PanelColor } from '../../../../src/components/panel/panel';
-import pageError from './prompt_types/page_error';
-const pageErrorSource = require('!!raw-loader!./prompt_types/page_error');
-import noPermission from './prompt_types/no_permission';
-const noPermissionSource = require('!!raw-loader!./prompt_types/no_permission');
+import errorPages from './prompt_types/page_not_found';
+const errorPagesSource = require('!!raw-loader!./prompt_types/page_not_found');
+import noPrivileges from './prompt_types/no_permission';
+const noPrivilegesSource = require('!!raw-loader!./prompt_types/no_permission');
import licenseUpgrade from './prompt_types/license_upgrade';
const licenseUpgradeSource = require('!!raw-loader!./prompt_types/license_upgrade');
import complex from './prompt_types/complex';
@@ -24,16 +24,16 @@ export default () => {
demoBackground?: PanelColor;
}> = [
{
- value: 'pageError',
+ value: 'errorPages',
text: 'Page not found',
- component: pageError,
- source: pageErrorSource,
+ component: errorPages,
+ source: errorPagesSource,
},
{
- value: 'noPermission',
+ value: 'noPrivileges',
text: 'No permission',
- component: noPermission,
- source: noPermissionSource,
+ component: noPrivileges,
+ source: noPrivilegesSource,
},
{
value: 'licenseUpgrade',
diff --git a/src-docs/src/views/empty_prompt/empty_prompt_page_template.tsx b/src-docs/src/views/empty_prompt/empty_prompt_page_template.tsx
index b96ed46af43..1f7cb750249 100644
--- a/src-docs/src/views/empty_prompt/empty_prompt_page_template.tsx
+++ b/src-docs/src/views/empty_prompt/empty_prompt_page_template.tsx
@@ -8,7 +8,7 @@ import {
EuiLink,
EuiImage,
} from '../../../../src/components';
-import illustration from '../../images/empty-prompt_illustration.svg';
+import illustration from '../../images/empty-prompt/illustration.svg';
export default () => (
{
emptyPromptProps = {
color: 'danger',
iconType: 'alert',
- title: Error loading Dashboards ,
+ title: Unable to load your dashboards ,
body: (
There was an error loading the Dashboard application. Contact your
diff --git a/src-docs/src/views/empty_prompt/guidelines.tsx b/src-docs/src/views/empty_prompt/guidelines.tsx
index 35fda9eea6e..99474ad67ac 100644
--- a/src-docs/src/views/empty_prompt/guidelines.tsx
+++ b/src-docs/src/views/empty_prompt/guidelines.tsx
@@ -1,23 +1,24 @@
import React from 'react';
-// @ts-ignore Importing from JS
-import { GuideRuleTitle } from '../../components';
+// @ts-ignore Importing from JS file
+import { GuideRule, GuideRuleExample, GuideRuleTitle } from '../../components';
import {
EuiTitle,
EuiText,
EuiSpacer,
- EuiFlexGroup,
- EuiFlexItem,
EuiImage,
- EuiTable,
- EuiTableHeader,
- EuiTableHeaderCell,
- EuiTableBody,
- EuiTableRow,
- EuiTableRowCell,
+ EuiAspectRatio,
} from '../../../../src/components';
+import TypesOfEmptyStates from './_types_of_empty_states';
-import imgAnatomy from '../../images/empty-prompt_anatomy.svg';
+import vertical from '../../images/empty-prompt/thumbnail_vertical.svg';
+import horizontal from '../../images/empty-prompt/thumbnail_horizontal.svg';
+import iconDont from '../../images/empty-prompt/thumbnail_icon-dont.svg';
+import iconDo from '../../images/empty-prompt/thumbnail_icon-do.svg';
+import multipleDo from '../../images/empty-prompt/thumbnail_multiple-do.svg';
+import multipleDont from '../../images/empty-prompt/thumbnail_multiple-dont.svg';
+import inlineLink from '../../images/empty-prompt/thumbnail_inline-link.svg';
+import footerLink from '../../images/empty-prompt/thumbnail_footer-link.svg';
export default () => (
<>
@@ -27,174 +28,211 @@ export default () => (
-
+
- A useful empty state will let the user know what’s happening, why it’s
- happening, and what to do about it. If done right, it can can contribute
- to a more compelling user experience and add more value to the business.
+ A useful empty state will let the user know what's happening, why
+ it's happening, and what to do about it. It can contribute to a
+ more compelling user experience and add more value to the business if
+ done right.
To make the empty state clear, follow this pattern:
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
- Icon/illustration (optional): A meaningful icon
- or illustration that represents the solution or context.
-
-
- Title: The title will answer the question. What’s
- happening? Is it an error? Is there data?
-
-
- Description: Why is it happening? Try to provide
- more information regarding why the space is empty and guide the
- user through next actions.
-
-
- Action(s): What will solve the issue? It’s always
- important to lead users to take action or to guide them about the
- next steps.
-
-
- Footer (optional): Use the footer to provide more
- helpful guidance. Use this section to reference documentation or
- to link to an area where users can learn more about the issue they
- are facing.
-
-
-
-
-
+
+
+
+
+ Icon or illustration (optional): A meaningful
+ representation of the the solution or context.
+
+
+ Title: Answers the question "What's
+ happening?". Is it an error? Is it loading?
+
+
+ Description: Why is it happening? Explain why the
+ space is empty and guide the users through the required actions.
+
+
+ Action(s): Your call to actions should answer the
+ question "What will solve the issue?". Lead the users to
+ take action or guide them about the next steps.
+
+
+ Footer (optional): Use this section to reference
+ documentation or link to an area where users can learn more about the
+ issue they are facing.
+
+
+
{/* End of Content section */}
- {/* Usage section */}
- Types of empty states and goals
+
+ {/* Types of empty states; goals and recommendations section */}
+
+ Empty state types, goals, and recommendations
+
-
+
- But how do you know when you should create an empty state? These are the
- scenarios we recommend the usage of an empty state:
+ The following scenarios detail the most common empty states use cases
+ and provide recommendations for use with{' '}
+ EuiPageTemplate .
-
-
- Type
- Description
- Goal
-
-
-
-
-
- First use
-
-
-
- No content on screen because it is the first time users are
- interacting with that screen.
-
-
-
- Users understand there’s no data because it is the first time they
- interact with the app. They can clearly understand how to add data.
-
-
-
-
-
- No data
-
-
-
- No data is available, or the data doesn’t match the filter.
-
-
-
- Users understand why there is no data displayed and what actions
- they can perform to make it available.
-
-
-
-
-
- No permission
-
-
-
- No permission to access the content.
-
-
-
- Users understand why they don’t have permission to access the
- content and what actions they need to perform to get access.
-
-
-
-
-
- No results
-
-
- No results matched the search.
-
-
- Users understand why the search didn’t match any results and what
- they can do to have better results.
-
-
-
-
-
- Error
-
-
- An error happened.
-
-
- Users understand why they’re facing an error and what they can do to
- solve the error.
-
-
-
-
-
- Completed tasks
-
-
-
- All actions/tasks are completed, and there is nothing to display.
-
-
-
- Users understand that there are no more actions to complete.
-
-
-
-
-
- License upgrade
-
-
- No license to use a feature.
-
-
- Users understand that they don’t have the required license to access
- a feature and what actions they need to perform to upgrade the
- license.
-
-
-
-
- {/* End of usage section */}
+
+
+ {/* End of Types of empty states; goals and recommendations section */}
+
+ {/* Design section */}
+ Design
+
+
+
+ The vertical layout is perfect when the content is small—a title and
+ two paragraphs at most. You can use this layout with an icon, an
+ illustration, or no icons at all.
+
+
+ Use the horizontal layout when you have a long description, multiple
+ calls to action, and a footer. For this type of layout, an
+ illustration is required.
+
+ >
+ }
+ >
+
+
+
+
+
+
+
+
+
+
+ Icons and illustrations must first and foremost communicate meaning.
+ They are also an opportunity to delight users and show our Elastic
+ brand.
+
+
+ When using an illustration, bear in mind that they stand out a lot.
+ Use one illustration per page. Having multiple illustrations might
+ make the page too crowded.
+
+ >
+ }
+ >
+
+
+
+
+
+
+
+
+
+
+ "Learn more" links are optional. You can use them in your
+ empty prompt to link to documentation where users can get more
+ detailed help.
+
+
+ Include the link after the description when the empty prompt
+ doesn't contain a call to action. If there is a call to action,
+ include the link in the footer.
+
+ >
+ }
+ >
+
+
+
+
+
+
+
+
+
+
+ When a page has multiple empty states, avoid using multiple primary
+ actions and multiple icons or illustrations.
+
+
+ Use secondary actions and no icons or illustrations. This way, the
+ visual noise will be reduced. Consider using an illustration or a
+ primary action if you want to make one of the empty states stand
+ out.
+
+ >
+ }
+ >
+
+
+
+
+
+
+
+
+ {/* End of Design section */}
>
);
diff --git a/src-docs/src/views/empty_prompt/prompt_types/complex.tsx b/src-docs/src/views/empty_prompt/prompt_types/complex.tsx
index e346dd50345..89c16138483 100644
--- a/src-docs/src/views/empty_prompt/prompt_types/complex.tsx
+++ b/src-docs/src/views/empty_prompt/prompt_types/complex.tsx
@@ -10,7 +10,7 @@ import {
EuiTitle,
} from '../../../../../src/components';
-import illustration from '../../../images/empty-prompt_illustration.svg';
+import illustration from '../../../images/empty-prompt/illustration.svg';
export default () => (
(
Do more with Kibana!}
+ iconType={example.iconType}
+ title={example.title}
layout="vertical"
hasBorder
- body={
-
- Start a free trial or upgrade your license to use anomaly detection.
-
- }
- actions={[
-
- Upgrade
- ,
- Start a free trial ,
- ]}
- footer={
- <>
-
- Want to learn more?
-
-
- Read documentation
-
- >
- }
+ body={example.body}
+ actions={example.actions}
+ footer={example.footer}
/>
);
diff --git a/src-docs/src/views/empty_prompt/prompt_types/no_permission.tsx b/src-docs/src/views/empty_prompt/prompt_types/no_permission.tsx
index f5add5f1c04..cc61b582521 100644
--- a/src-docs/src/views/empty_prompt/prompt_types/no_permission.tsx
+++ b/src-docs/src/views/empty_prompt/prompt_types/no_permission.tsx
@@ -1,12 +1,16 @@
import React from 'react';
import { EuiEmptyPrompt } from '../../../../../src/components';
+// @ts-ignore Importing from JS file
+import { typesOfUseCases } from '../_types_of_use_cases';
+
+const example: any = typesOfUseCases.noPrivileges.example;
export default () => (
Contact your administrator for access}
- body={To view cases in this space, you need additional privileges.
}
+ title={example.title}
+ body={example.body}
/>
);
diff --git a/src-docs/src/views/empty_prompt/prompt_types/page_error.tsx b/src-docs/src/views/empty_prompt/prompt_types/page_error.tsx
deleted file mode 100644
index ee34c9e691a..00000000000
--- a/src-docs/src/views/empty_prompt/prompt_types/page_error.tsx
+++ /dev/null
@@ -1,32 +0,0 @@
-import React from 'react';
-
-import {
- EuiEmptyPrompt,
- EuiButton,
- EuiButtonEmpty,
- EuiImage,
-} from '../../../../../src/components';
-
-import illustration from '../../../images/empty-prompt_illustration.svg';
-
-export default () => (
- }
- title={Page not found }
- layout="vertical"
- body={
-
- The page you are looking for might have been removed or temporarily
- unavailable.
-
- }
- actions={[
-
- Go home
- ,
-
- Go back
- ,
- ]}
- />
-);
diff --git a/src-docs/src/views/empty_prompt/prompt_types/page_not_found.tsx b/src-docs/src/views/empty_prompt/prompt_types/page_not_found.tsx
new file mode 100644
index 00000000000..9b6b6c5dd26
--- /dev/null
+++ b/src-docs/src/views/empty_prompt/prompt_types/page_not_found.tsx
@@ -0,0 +1,24 @@
+import React, { useContext } from 'react';
+import { EuiEmptyPrompt, EuiImage } from '../../../../../src/components';
+// @ts-ignore Importing from JS file
+import { typesOfUseCases } from '../_types_of_use_cases';
+import { ThemeContext } from '../../../components/with_theme';
+
+export default () => {
+ const themeContext = useContext(ThemeContext);
+ const isDarkTheme = themeContext.theme.includes('dark');
+
+ const example: any = typesOfUseCases.errorPages.example;
+
+ const iconImg: string = isDarkTheme ? example.iconDark : example.iconLight;
+
+ return (
+ }
+ title={example.title}
+ layout="vertical"
+ body={example.body}
+ actions={example.actions}
+ />
+ );
+};
diff --git a/src-docs/webpack.config.js b/src-docs/webpack.config.js
index 824ce572fd6..8d72556e173 100644
--- a/src-docs/webpack.config.js
+++ b/src-docs/webpack.config.js
@@ -2,6 +2,7 @@ const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CircularDependencyPlugin = require('circular-dependency-plugin');
const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');
+const TerserPlugin = require('terser-webpack-plugin');
const babelConfig = require('./.babelrc.js');
const getPort = require('get-port');
@@ -149,6 +150,20 @@ const webpackConfig = {
node: {
fs: 'empty',
},
+
+ optimization: {
+ minimize: isProduction,
+ minimizer: [
+ new TerserPlugin({
+ parallel: true,
+ terserOptions: {
+ // prevent Eui* function (component) names from being mangled,
+ // as mangling prevents copy-pasteable component code from being generated
+ keep_fnames: /^Eui[A-Z]/,
+ },
+ }),
+ ],
+ },
};
// Inspired by `get-port-sync`, but propogates options
diff --git a/yarn.lock b/yarn.lock
index f8cadf66820..9a01c0a8f16 100755
--- a/yarn.lock
+++ b/yarn.lock
@@ -2320,6 +2320,11 @@
"@babel/helper-validator-identifier" "^7.16.7"
to-fast-properties "^2.0.0"
+"@base2/pretty-print-object@1.0.1":
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/@base2/pretty-print-object/-/pretty-print-object-1.0.1.tgz#371ba8be66d556812dc7fb169ebc3c08378f69d4"
+ integrity sha512-4iri8i1AqYHJE2DstZYkyEprg6Pq6sKx3xn5FpySk9sNhH7qN2LLlHJCfDTZRILNwQNPD7mATWM0TBui7uC1pA==
+
"@cnakazawa/watch@^1.0.3":
version "1.0.4"
resolved "https://registry.yarnpkg.com/@cnakazawa/watch/-/watch-1.0.4.tgz#f864ae85004d0fcab6f50be9141c4da368d1656a"
@@ -11482,6 +11487,11 @@ is-plain-obj@^2.0.0:
resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287"
integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==
+is-plain-object@5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344"
+ integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==
+
is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4:
version "2.0.4"
resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677"
@@ -16203,6 +16213,15 @@ react-dropzone@^11.5.3:
file-selector "^0.2.2"
prop-types "^15.7.2"
+react-element-to-jsx-string@^14.3.4:
+ version "14.3.4"
+ resolved "https://registry.yarnpkg.com/react-element-to-jsx-string/-/react-element-to-jsx-string-14.3.4.tgz#709125bc72f06800b68f9f4db485f2c7d31218a8"
+ integrity sha512-t4ZwvV6vwNxzujDQ+37bspnLwA4JlgUPWhLjBJWsNIDceAf6ZKUTCjdm08cN6WeZ5pTMKiCJkmAYnpmR4Bm+dg==
+ dependencies:
+ "@base2/pretty-print-object" "1.0.1"
+ is-plain-object "5.0.0"
+ react-is "17.0.2"
+
react-fast-compare@^3.1.1:
version "3.2.0"
resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.0.tgz#641a9da81b6a6320f270e89724fb45a0b39e43bb"
@@ -16250,16 +16269,16 @@ react-input-autosize@^3.0.0:
dependencies:
prop-types "^15.5.8"
+react-is@17.0.2, "react-is@^16.12.0 || ^17.0.0", react-is@^17.0.0, react-is@^17.0.2:
+ version "17.0.2"
+ resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0"
+ integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==
+
react-is@^16.12.0, react-is@^16.13.1, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.4, react-is@^16.9.0:
version "16.13.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
-"react-is@^16.12.0 || ^17.0.0", react-is@^17.0.0, react-is@^17.0.2:
- version "17.0.2"
- resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0"
- integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==
-
react-redux@^7.1.0:
version "7.2.2"
resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.2.2.tgz#03862e803a30b6b9ef8582dadcc810947f74b736"