diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/constants.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/constants.ts
index 57af8cada9890..99f3d340f8430 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/constants.ts
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/constants.ts
@@ -5,6 +5,7 @@
* 2.0.
*/
+import { EuiButtonIconColor } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
export const CURATIONS_TITLE = i18n.translate(
@@ -49,26 +50,26 @@ export const PROMOTE_DOCUMENT_ACTION = {
defaultMessage: 'Promote this result',
}),
iconType: 'starPlusEmpty',
- iconColor: 'primary',
+ iconColor: 'primary' as EuiButtonIconColor,
};
export const DEMOTE_DOCUMENT_ACTION = {
title: i18n.translate('xpack.enterpriseSearch.appSearch.engine.curations.demoteButtonLabel', {
defaultMessage: 'Demote this result',
}),
iconType: 'starMinusFilled',
- iconColor: 'primary',
+ iconColor: 'primary' as EuiButtonIconColor,
};
export const HIDE_DOCUMENT_ACTION = {
title: i18n.translate('xpack.enterpriseSearch.appSearch.engine.curations.hideButtonLabel', {
defaultMessage: 'Hide this result',
}),
iconType: 'eyeClosed',
- iconColor: 'danger',
+ iconColor: 'danger' as EuiButtonIconColor,
};
export const SHOW_DOCUMENT_ACTION = {
title: i18n.translate('xpack.enterpriseSearch.appSearch.engine.curations.showButtonLabel', {
defaultMessage: 'Show this result',
}),
iconType: 'eye',
- iconColor: 'primary',
+ iconColor: 'primary' as EuiButtonIconColor,
};
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/library/library.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/library/library.tsx
index ad693628d911e..9ad32c6e48632 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/library/library.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/library/library.tsx
@@ -16,6 +16,7 @@ import {
EuiDragDropContext,
EuiDroppable,
EuiDraggable,
+ EuiButtonIconColor,
} from '@elastic/eui';
import { SetAppSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome';
@@ -78,7 +79,7 @@ export const Library: React.FC = () => {
title: 'Fill this action button',
onClick: () => setIsActionButtonFilled(!isActionButtonFilled),
iconType: isActionButtonFilled ? 'starFilled' : 'starEmpty',
- iconColor: 'primary',
+ iconColor: 'primary' as EuiButtonIconColor,
},
];
@@ -221,7 +222,7 @@ export const Library: React.FC = () => {
With custom actions and a link
-
+
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/index.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/index.ts
index 89909c1e51d3f..a7eed3b95e6fa 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/index.ts
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/index.ts
@@ -6,4 +6,5 @@
*/
export { ResultFieldValue } from './result_field_value';
+export { ResultToken } from './result_token';
export { Result } from './result';
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result.scss b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result.scss
index 5f1b165f2c362..3132894ddc7a1 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result.scss
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result.scss
@@ -6,6 +6,7 @@
'drag content actions'
'drag toggle actions';
overflow: hidden; // Prevents child background-colors from clipping outside of panel border-radius
+ border: $euiBorderThin; // TODO: Remove after EUI version is bumped beyond 31.8.0
&__content {
grid-area: content;
@@ -44,9 +45,13 @@
display: flex;
justify-content: center;
align-items: center;
- width: $euiSizeL * 2;
+ width: $euiSize * 2;
border-left: $euiBorderThin;
+ &:first-child {
+ border-left: none;
+ }
+
&:hover,
&:focus {
background-color: $euiPageBackgroundColor;
@@ -62,22 +67,3 @@
border-right: $euiBorderThin;
}
}
-
-/**
- * CSS for hover specific logic
- * It's mildly horrific, so I pulled it out to its own section here
- */
-
-.appSearchResult--link {
- &:hover,
- &:focus {
- @include euiSlightShadowHover;
- }
-}
-.appSearchResult__content--link:hover {
- cursor: pointer;
-
- & ~ .appSearchResult__actionButtons .appSearchResult__actionButton--link {
- background-color: $euiPageBackgroundColor;
- }
-}
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result.test.tsx
index 15c9ee2967d3e..3e83717bf9355 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result.test.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result.test.tsx
@@ -10,9 +10,8 @@ import { DraggableProvidedDragHandleProps } from 'react-beautiful-dnd';
import { shallow, ShallowWrapper } from 'enzyme';
-import { EuiPanel } from '@elastic/eui';
+import { EuiButtonIcon, EuiPanel, EuiButtonIconColor } from '@elastic/eui';
-import { ReactRouterHelper } from '../../../shared/react_router_helpers/eui_components';
import { SchemaTypes } from '../../../shared/types';
import { Result } from './result';
@@ -64,37 +63,18 @@ describe('Result', () => {
]);
});
- it('passes showScore, resultMeta, and isMetaEngine to ResultHeader', () => {
+ it('renders a header', () => {
const wrapper = shallow();
- expect(wrapper.find(ResultHeader).props()).toEqual({
- isMetaEngine: true,
- showScore: true,
- resultMeta: {
- id: '1',
- score: 100,
- engine: 'my-engine',
- },
- });
- });
-
- describe('document detail link', () => {
- it('will render a link if shouldLinkToDetailPage is true', () => {
- const wrapper = shallow();
- wrapper.find(ReactRouterHelper).forEach((link) => {
- expect(link.prop('to')).toEqual('/engines/my-engine/documents/1');
- });
- expect(wrapper.hasClass('appSearchResult--link')).toBe(true);
- expect(wrapper.find('.appSearchResult__content--link').exists()).toBe(true);
- expect(wrapper.find('.appSearchResult__actionButton--link').exists()).toBe(true);
- });
-
- it('will not render a link if shouldLinkToDetailPage is not set', () => {
- const wrapper = shallow();
- expect(wrapper.find(ReactRouterHelper).exists()).toBe(false);
- expect(wrapper.hasClass('appSearchResult--link')).toBe(false);
- expect(wrapper.find('.appSearchResult__content--link').exists()).toBe(false);
- expect(wrapper.find('.appSearchResult__actionButton--link').exists()).toBe(false);
- });
+ const header = wrapper.find(ResultHeader);
+ expect(header.exists()).toBe(true);
+ expect(header.prop('isMetaEngine')).toBe(true); // passed through from props
+ expect(header.prop('showScore')).toBe(true); // passed through from props
+ expect(header.prop('shouldLinkToDetailPage')).toBe(false); // passed through from props
+ expect(header.prop('resultMeta')).toEqual({
+ id: '1',
+ score: 100,
+ engine: 'my-engine',
+ }); // passed through from meta in result prop
});
describe('actions', () => {
@@ -103,30 +83,53 @@ describe('Result', () => {
title: 'Hide',
onClick: jest.fn(),
iconType: 'eyeClosed',
- iconColor: 'danger',
+ iconColor: 'danger' as EuiButtonIconColor,
},
{
title: 'Bookmark',
onClick: jest.fn(),
iconType: 'starFilled',
- iconColor: 'primary',
+ iconColor: undefined,
},
];
- it('will render an action button for each action passed', () => {
+ it('will render an action button in the header for each action passed', () => {
const wrapper = shallow();
- expect(wrapper.find('.appSearchResult__actionButton')).toHaveLength(2);
-
- wrapper.find('.appSearchResult__actionButton').first().simulate('click');
+ const header = wrapper.find(ResultHeader);
+ const renderedActions = shallow(header.prop('actions') as any);
+ const buttons = renderedActions.find(EuiButtonIcon);
+ expect(buttons).toHaveLength(2);
+
+ expect(buttons.first().prop('iconType')).toEqual('eyeClosed');
+ expect(buttons.first().prop('color')).toEqual('danger');
+ buttons.first().simulate('click');
expect(actions[0].onClick).toHaveBeenCalled();
- wrapper.find('.appSearchResult__actionButton').last().simulate('click');
+ expect(buttons.last().prop('iconType')).toEqual('starFilled');
+ // Note that no iconColor was passed so it was defaulted to primary
+ expect(buttons.last().prop('color')).toEqual('primary');
+ buttons.last().simulate('click');
expect(actions[1].onClick).toHaveBeenCalled();
});
- it('will render custom actions seamlessly next to the document detail link', () => {
+ it('will render a document detail link as the first action if shouldLinkToDetailPage is passed', () => {
const wrapper = shallow();
- expect(wrapper.find('.appSearchResult__actionButton')).toHaveLength(3);
+ const header = wrapper.find(ResultHeader);
+ const renderedActions = shallow(header.prop('actions') as any);
+ const buttons = renderedActions.find(EuiButtonIcon);
+
+ // In addition to the 2 actions passed, we also have a link action
+ expect(buttons).toHaveLength(3);
+
+ expect(buttons.first().prop('data-test-subj')).toEqual('DocumentDetailLink');
+ });
+
+ it('will not render anything if no actions are passed and shouldLinkToDetailPage is false', () => {
+ const wrapper = shallow();
+ const header = wrapper.find(ResultHeader);
+ const renderedActions = shallow(header.prop('actions') as any);
+ const buttons = renderedActions.find(EuiButtonIcon);
+ expect(buttons).toHaveLength(0);
});
});
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result.tsx
index 89208a041af35..71d9f39d802d5 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result.tsx
@@ -8,16 +8,16 @@
import React, { useState, useMemo } from 'react';
import { DraggableProvidedDragHandleProps } from 'react-beautiful-dnd';
-import classNames from 'classnames';
-
import './result.scss';
-import { EuiPanel, EuiIcon } from '@elastic/eui';
+import { EuiButtonIcon, EuiPanel, EuiFlexGroup, EuiFlexItem, EuiIcon } from '@elastic/eui';
+
import { i18n } from '@kbn/i18n';
import { ReactRouterHelper } from '../../../shared/react_router_helpers/eui_components';
import { Schema } from '../../../shared/types';
+
import { ENGINE_DOCUMENT_DETAIL_PATH } from '../../routes';
import { generateEncodedPath } from '../../utils/encode_path_params';
@@ -56,34 +56,54 @@ export const Result: React.FC = ({
[result]
);
const numResults = resultFields.length;
- const typeForField = (fieldName: string) => {
- if (schemaForTypeHighlights) return schemaForTypeHighlights[fieldName];
- };
-
const documentLink = generateEncodedPath(ENGINE_DOCUMENT_DETAIL_PATH, {
engineName: resultMeta.engine,
documentId: resultMeta.id,
});
- const conditionallyLinkedArticle = (children: React.ReactNode) => {
- return shouldLinkToDetailPage ? (
-
-
- {children}
-
-
- ) : (
- {children}
- );
+
+ const typeForField = (fieldName: string) => {
+ if (schemaForTypeHighlights) return schemaForTypeHighlights[fieldName];
};
- const classes = classNames('appSearchResult', {
- 'appSearchResult--link': shouldLinkToDetailPage,
- });
+ const ResultActions = () => {
+ if (!shouldLinkToDetailPage && !actions.length) return null;
+ return (
+
+
+ {shouldLinkToDetailPage && (
+
+
+
+
+
+ )}
+ {actions.map(({ onClick, title, iconType, iconColor }) => (
+
+
+
+ ))}
+
+
+ );
+ };
return (
= ({
)}
- {conditionallyLinkedArticle(
- <>
-
- {resultFields
- .slice(0, isOpen ? resultFields.length : RESULT_CUTOFF)
- .map(([field, value]: [string, FieldValue]) => (
-
- ))}
- >
- )}
+
+ }
+ />
+ {resultFields
+ .slice(0, isOpen ? resultFields.length : RESULT_CUTOFF)
+ .map(([field, value]: [string, FieldValue]) => (
+
+ ))}
+
{numResults > RESULT_CUTOFF && (
)}
-
- {shouldLinkToDetailPage && (
-
-
-
-
-
- )}
- {actions.map(({ onClick, title, iconType, iconColor }) => (
-
- ))}
-
);
};
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_field.scss b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_field.scss
index 80d60e2de67e2..443c130548f6b 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_field.scss
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_field.scss
@@ -14,6 +14,16 @@
}
}
+ &__key {
+ display: flex;
+ align-items: center;
+ @include euiCodeFont;
+
+ .euiToken {
+ margin-right: $euiSizeS;
+ }
+ }
+
&__value {
padding-left: $euiSize;
overflow: hidden;
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_field.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_field.tsx
index 003810ec40a8d..9b78d769d2f30 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_field.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_field.tsx
@@ -9,7 +9,7 @@ import React from 'react';
import { FieldType, Raw, Snippet } from './types';
-import { ResultFieldValue } from '.';
+import { ResultFieldValue, ResultToken } from '.';
import './result_field.scss';
@@ -23,7 +23,10 @@ interface Props {
export const ResultField: React.FC = ({ field, raw, snippet, type }) => {
return (
-
{field}
+
+ {type && }
+ {field}
+
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header.scss b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header.scss
index 73372d7c4aca0..cd1042998dd34 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header.scss
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header.scss
@@ -1,7 +1,5 @@
.appSearchResultHeader {
display: flex;
- justify-content: space-between;
- align-items: flex-start;
margin-bottom: $euiSizeS;
@include euiBreakpoint('xs') {
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header.test.tsx
index dcefd0f6bc0b0..80cff9b96a3ca 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header.test.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header.test.tsx
@@ -30,6 +30,22 @@ describe('ResultHeader', () => {
);
expect(wrapper.find('[data-test-subj="ResultId"]').prop('value')).toEqual('1');
+ expect(wrapper.find('[data-test-subj="ResultId"]').prop('href')).toBeUndefined();
+ });
+
+ it('renders id as a link if shouldLinkToDetailPage is true', () => {
+ const wrapper = shallow(
+
+ );
+ expect(wrapper.find('[data-test-subj="ResultId"]').prop('value')).toEqual('1');
+ expect(wrapper.find('[data-test-subj="ResultId"]').prop('href')).toEqual(
+ '/engines/my-engine/documents/1'
+ );
});
describe('score', () => {
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header.tsx
index 550093a8cd904..93a684b1968a2 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header.tsx
@@ -7,6 +7,11 @@
import React from 'react';
+import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
+
+import { ENGINE_DOCUMENT_DETAIL_PATH } from '../../routes';
+import { generateEncodedPath } from '../../utils/encode_path_params';
+
import { ResultHeaderItem } from './result_header_item';
import { ResultMeta } from './types';
@@ -16,33 +21,56 @@ interface Props {
showScore: boolean;
isMetaEngine: boolean;
resultMeta: ResultMeta;
+ actions?: React.ReactNode;
+ shouldLinkToDetailPage?: boolean;
}
-export const ResultHeader: React.FC
= ({ showScore, resultMeta, isMetaEngine }) => {
+export const ResultHeader: React.FC = ({
+ showScore,
+ resultMeta,
+ isMetaEngine,
+ actions,
+ shouldLinkToDetailPage = false,
+}) => {
+ const documentLink = generateEncodedPath(ENGINE_DOCUMENT_DETAIL_PATH, {
+ engineName: resultMeta.engine,
+ documentId: resultMeta.id,
+ });
+
return (
-
);
};
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header_item.scss b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header_item.scss
index f1e9343530af3..df3e2ec241106 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header_item.scss
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header_item.scss
@@ -1,16 +1,12 @@
-.appSearchResultHeaderItem {
- display: flex;
+.euiFlexItem:not(:first-child):not(:last-child) .appSearchResultHeaderItem {
+ padding-right: .75rem;
+ box-shadow: inset -1px 0 0 0 $euiBorderColor;
+}
- &__key,
- &__value {
- line-height: $euiLineHeight;
- font-size: $euiFontSizeXS;
- }
+.appSearchResultHeaderItem {
+ @include euiCodeFont;
- &__key {
- text-transform: uppercase;
- font-weight: $euiFontWeightLight;
- color: $euiColorDarkShade;
- margin-right: $euiSizeXS;
+ &__score {
+ color: $euiColorSuccessText;
}
}
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header_item.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header_item.test.tsx
index 52fa81943bb2e..e0407b4db7f25 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header_item.test.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header_item.test.tsx
@@ -7,15 +7,14 @@
import React from 'react';
-import { mount } from 'enzyme';
+import { shallow, mount } from 'enzyme';
import { ResultHeaderItem } from './result_header_item';
describe('ResultHeaderItem', () => {
it('renders', () => {
const wrapper = mount();
- expect(wrapper.find('.appSearchResultHeaderItem__key').text()).toEqual('id');
- expect(wrapper.find('.appSearchResultHeaderItem__value').text()).toEqual('001');
+ expect(wrapper.find('.appSearchResultHeaderItem').text()).toContain('001');
});
it('will truncate long field names', () => {
@@ -26,7 +25,7 @@ describe('ResultHeaderItem', () => {
type="string"
/>
);
- expect(wrapper.find('.appSearchResultHeaderItem__key').text()).toEqual(
+ expect(wrapper.find('.appSearchResultHeaderItem').text()).toContain(
'a-really-really-really-really-…'
);
});
@@ -35,7 +34,7 @@ describe('ResultHeaderItem', () => {
const wrapper = mount(
);
- expect(wrapper.find('.appSearchResultHeaderItem__value').text()).toEqual(
+ expect(wrapper.find('.appSearchResultHeaderItem').text()).toContain(
'a-really-really-really-really-…'
);
});
@@ -44,18 +43,33 @@ describe('ResultHeaderItem', () => {
const wrapper = mount(
);
- expect(wrapper.find('.appSearchResultHeaderItem__value').text()).toEqual(
+ expect(wrapper.find('.appSearchResultHeaderItem').text()).toContain(
'…lly-really-really-really-value'
);
});
it('will round any numeric values that are passed in to 2 decimals, regardless of the explicit "type" passed', () => {
const wrapper = mount();
- expect(wrapper.find('.appSearchResultHeaderItem__value').text()).toEqual('5.19');
+ expect(wrapper.find('.appSearchResultHeaderItem').text()).toContain('5.19');
});
it('if the value passed in is undefined, it will render "-"', () => {
const wrapper = mount();
- expect(wrapper.find('.appSearchResultHeaderItem__value').text()).toEqual('-');
+ expect(wrapper.find('.appSearchResultHeaderItem').text()).toContain('-');
+ });
+
+ it('it will add a "score" class if the "type" passed is "score"', () => {
+ const wrapper = shallow();
+ expect(
+ wrapper.find('.appSearchResultHeaderItem').hasClass('appSearchResultHeaderItem__score')
+ ).toBe(true);
+ });
+
+ it('it will render as a link if an href is passed', () => {
+ const wrapper = shallow(
+
+ );
+ expect(wrapper.find('ReactRouterHelper').exists()).toBe(true);
+ expect(wrapper.find('ReactRouterHelper').prop('to')).toBe('http://www.example.com');
});
});
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header_item.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header_item.tsx
index cda56fbc4797c..545b85c17a529 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header_item.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header_item.tsx
@@ -9,17 +9,20 @@ import React from 'react';
import './result_header_item.scss';
+import { ReactRouterHelper } from '../../../shared/react_router_helpers/eui_components';
+
import { TruncatedContent } from '../../../shared/truncate';
interface Props {
field: string;
value?: string | number;
type: 'id' | 'score' | 'string';
+ href?: string;
}
const MAX_CHARACTER_LENGTH = 30;
-export const ResultHeaderItem: React.FC = ({ field, type, value }) => {
+export const ResultHeaderItem: React.FC = ({ field, type, value, href }) => {
let formattedValue = '-';
if (typeof value === 'string') {
formattedValue = value;
@@ -27,19 +30,32 @@ export const ResultHeaderItem: React.FC = ({ field, type, value }) => {
formattedValue = parseFloat((value as number).toFixed(2)).toString();
}
+ const HeaderItemContent = () => (
+
+ );
+
return (
-
+
+
+
+ {href ? (
+
+
+
+
+
+ ) : (
+
+ )}
+
);
};
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_token.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_token.test.tsx
new file mode 100644
index 0000000000000..d50b35198acb9
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_token.test.tsx
@@ -0,0 +1,28 @@
+/*
+ * 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 from 'react';
+
+import { shallow } from 'enzyme';
+
+import { EuiToken } from '@elastic/eui';
+
+import { ResultToken } from './result_token';
+
+describe('ResultToken', () => {
+ beforeEach(() => {
+ jest.clearAllMocks();
+ });
+
+ it('render a token icon based on the provided field type', () => {
+ expect(
+ shallow()
+ .find(EuiToken)
+ .prop('iconType')
+ ).toBe('tokenString');
+ });
+});
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_token.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_token.tsx
new file mode 100644
index 0000000000000..773fcd19ce9ea
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_token.tsx
@@ -0,0 +1,30 @@
+/*
+ * 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 from 'react';
+
+import { EuiToken } from '@elastic/eui';
+
+import { FieldType } from './types';
+
+interface Props {
+ fieldType: FieldType;
+}
+
+const fieldTypeToTokenMap = {
+ text: 'tokenString',
+ string: 'tokenString',
+ number: 'tokenNumber',
+ float: 'tokenNumber',
+ location: 'tokenGeo',
+ geolocation: 'tokenGeo',
+ date: 'tokenDate',
+};
+
+export const ResultToken: React.FC = ({ fieldType }) => {
+ return ;
+};
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/types.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/types.ts
index 96a135b0db36e..638a76511deee 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/types.ts
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/types.ts
@@ -5,6 +5,8 @@
* 2.0.
*/
+import { EuiButtonIconColor } from '@elastic/eui';
+
import { InternalSchemaTypes, SchemaTypes } from '../../../shared/types';
export type FieldType = InternalSchemaTypes | SchemaTypes;
@@ -38,5 +40,5 @@ export interface ResultAction {
onClick(): void;
title: string;
iconType: string;
- iconColor?: string;
+ iconColor?: EuiButtonIconColor;
}