diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.scss b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.scss
index f84191e1bfb1a..e0031d051df81 100644
--- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.scss
+++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.scss
@@ -16,3 +16,7 @@ img.lnsChartSwitch__chartIcon { // sass-lint:disable-line no-qualifying-elements
// The large icons aren't square so max out the width to fill the height
width: 100%;
}
+
+.lnsChartSwitch__search {
+ width: 4 * $euiSizeXXL;
+}
\ No newline at end of file
diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.tsx
index f4526cac39c8a..73ffbf56ff45a 100644
--- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.tsx
+++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.tsx
@@ -12,9 +12,14 @@ import {
EuiPopoverTitle,
EuiKeyPadMenu,
EuiKeyPadMenuItem,
+ EuiFieldSearch,
+ EuiFlexGroup,
+ EuiFlexItem,
+ EuiSelectableMessage,
} from '@elastic/eui';
import { flatten } from 'lodash';
import { i18n } from '@kbn/i18n';
+import { FormattedMessage } from '@kbn/i18n/react';
import { Visualization, FramePublicAPI, Datasource } from '../../../types';
import { Action } from '../state_management';
import { getSuggestions, switchToSuggestion, Suggestion } from '../suggestion_helpers';
@@ -173,6 +178,8 @@ export function ChartSwitch(props: Props) {
};
}
+ const [searchTerm, setSearchTerm] = useState('');
+
const visualizationTypes = useMemo(
() =>
flyoutOpen &&
@@ -184,10 +191,17 @@ export function ChartSwitch(props: Props) {
icon: t.icon,
}))
)
- ).map((visualizationType) => ({
- ...visualizationType,
- selection: getSelection(visualizationType.visualizationId, visualizationType.id),
- })),
+ )
+ .filter(
+ (visualizationType) =>
+ visualizationType.label.toLowerCase().includes(searchTerm.toLowerCase()) ||
+ (visualizationType.fullLabel &&
+ visualizationType.fullLabel.toLowerCase().includes(searchTerm.toLowerCase()))
+ )
+ .map((visualizationType) => ({
+ ...visualizationType,
+ selection: getSelection(visualizationType.visualizationId, visualizationType.id),
+ })),
// eslint-disable-next-line react-hooks/exhaustive-deps
[
flyoutOpen,
@@ -195,6 +209,7 @@ export function ChartSwitch(props: Props) {
props.framePublicAPI,
props.visualizationId,
props.visualizationState,
+ searchTerm,
]
);
@@ -219,15 +234,30 @@ export function ChartSwitch(props: Props) {
anchorPosition="downLeft"
>
- {i18n.translate('xpack.lens.configPanel.selectVisualization', {
- defaultMessage: 'Select a visualization',
- })}
+
+
+ {i18n.translate('xpack.lens.configPanel.chartType', {
+ defaultMessage: 'Chart type',
+ })}
+
+
+ setSearchTerm(e.target.value)}
+ />
+
+
{(visualizationTypes || []).map((v) => (
{v.label}}
+ title={v.fullLabel}
role="menuitem"
data-test-subj={`lnsChartSwitchPopover_${v.id}`}
onClick={() => commitSelection(v.selection)}
@@ -251,6 +281,17 @@ export function ChartSwitch(props: Props) {
))}
+ {searchTerm && (visualizationTypes || []).length === 0 && (
+
+ {searchTerm},
+ }}
+ />
+
+ )}
);
diff --git a/x-pack/plugins/lens/public/types.ts b/x-pack/plugins/lens/public/types.ts
index 6061f928bce41..2b9ca5a2425f8 100644
--- a/x-pack/plugins/lens/public/types.ts
+++ b/x-pack/plugins/lens/public/types.ts
@@ -430,10 +430,26 @@ export interface FramePublicAPI {
removeLayers: (layerIds: string[]) => void;
}
+/**
+ * A visualization type advertised to the user in the chart switcher
+ */
export interface VisualizationType {
+ /**
+ * Unique id of the visualization type within the visualization defining it
+ */
id: string;
+ /**
+ * Icon used in the chart switcher
+ */
icon: IconType;
+ /**
+ * Visible label used in the chart switcher and above the workspace panel in collapsed state
+ */
label: string;
+ /**
+ * Optional label used in chart type search if chart switcher is expanded and for tooltips
+ */
+ fullLabel?: string;
}
export interface Visualization {
diff --git a/x-pack/plugins/lens/public/xy_visualization/types.ts b/x-pack/plugins/lens/public/xy_visualization/types.ts
index cac982f852c7a..abee787888787 100644
--- a/x-pack/plugins/lens/public/xy_visualization/types.ts
+++ b/x-pack/plugins/lens/public/xy_visualization/types.ts
@@ -426,6 +426,9 @@ export const visualizationTypes: VisualizationType[] = [
id: 'bar_horizontal',
icon: LensIconChartBarHorizontal,
label: i18n.translate('xpack.lens.xyVisualization.barHorizontalLabel', {
+ defaultMessage: 'H. Bar',
+ }),
+ fullLabel: i18n.translate('xpack.lens.xyVisualization.barHorizontalFullLabel', {
defaultMessage: 'Horizontal bar',
}),
},
@@ -440,22 +443,31 @@ export const visualizationTypes: VisualizationType[] = [
id: 'bar_percentage_stacked',
icon: LensIconChartBarPercentage,
label: i18n.translate('xpack.lens.xyVisualization.stackedPercentageBarLabel', {
- defaultMessage: 'Bar percentage',
+ defaultMessage: 'Percentage bar',
}),
},
{
id: 'bar_horizontal_stacked',
icon: LensIconChartBarHorizontalStacked,
label: i18n.translate('xpack.lens.xyVisualization.stackedBarHorizontalLabel', {
- defaultMessage: 'Stacked horizontal bar',
+ defaultMessage: 'H. Stacked bar',
+ }),
+ fullLabel: i18n.translate('xpack.lens.xyVisualization.stackedBarHorizontalFullLabel', {
+ defaultMessage: 'Horizontal stacked bar',
}),
},
{
id: 'bar_horizontal_percentage_stacked',
icon: LensIconChartBarHorizontalPercentage,
label: i18n.translate('xpack.lens.xyVisualization.stackedPercentageBarHorizontalLabel', {
- defaultMessage: 'Horizontal bar percentage',
+ defaultMessage: 'H. Percentage bar',
}),
+ fullLabel: i18n.translate(
+ 'xpack.lens.xyVisualization.stackedPercentageBarHorizontalFullLabel',
+ {
+ defaultMessage: 'Horizontal percentage bar',
+ }
+ ),
},
{
id: 'area',
@@ -475,7 +487,7 @@ export const visualizationTypes: VisualizationType[] = [
id: 'area_percentage_stacked',
icon: LensIconChartAreaPercentage,
label: i18n.translate('xpack.lens.xyVisualization.stackedPercentageAreaLabel', {
- defaultMessage: 'Area percentage',
+ defaultMessage: 'Percentage area',
}),
},
{
diff --git a/x-pack/plugins/lens/public/xy_visualization/visualization.test.ts b/x-pack/plugins/lens/public/xy_visualization/visualization.test.ts
index 621fd082faf2d..d51b8c195c92c 100644
--- a/x-pack/plugins/lens/public/xy_visualization/visualization.test.ts
+++ b/x-pack/plugins/lens/public/xy_visualization/visualization.test.ts
@@ -44,14 +44,14 @@ describe('xy_visualization', () => {
it('should show mixed xy chart when multilple series types', () => {
const desc = xyVisualization.getDescription(mixedState('bar', 'line'));
- expect(desc.label).toEqual('Mixed XY chart');
+ expect(desc.label).toEqual('Mixed XY');
});
it('should show the preferredSeriesType if there are no layers', () => {
const desc = xyVisualization.getDescription(mixedState());
expect(desc.icon).toEqual(LensIconChartBar);
- expect(desc.label).toEqual('Bar chart');
+ expect(desc.label).toEqual('Bar');
});
it('should show mixed horizontal bar chart when multiple horizontal bar types', () => {
@@ -59,23 +59,23 @@ describe('xy_visualization', () => {
mixedState('bar_horizontal', 'bar_horizontal_stacked')
);
- expect(desc.label).toEqual('Mixed horizontal bar chart');
+ expect(desc.label).toEqual('Mixed H. bar');
});
it('should show bar chart when bar only', () => {
const desc = xyVisualization.getDescription(mixedState('bar_horizontal', 'bar_horizontal'));
- expect(desc.label).toEqual('Horizontal bar chart');
+ expect(desc.label).toEqual('H. Bar');
});
it('should show the chart description if not mixed', () => {
- expect(xyVisualization.getDescription(mixedState('area')).label).toEqual('Area chart');
- expect(xyVisualization.getDescription(mixedState('line')).label).toEqual('Line chart');
+ expect(xyVisualization.getDescription(mixedState('area')).label).toEqual('Area');
+ expect(xyVisualization.getDescription(mixedState('line')).label).toEqual('Line');
expect(xyVisualization.getDescription(mixedState('area_stacked')).label).toEqual(
- 'Stacked area chart'
+ 'Stacked area'
);
expect(xyVisualization.getDescription(mixedState('bar_horizontal_stacked')).label).toEqual(
- 'Stacked horizontal bar chart'
+ 'H. Stacked bar'
);
});
});
diff --git a/x-pack/plugins/lens/public/xy_visualization/visualization.tsx b/x-pack/plugins/lens/public/xy_visualization/visualization.tsx
index 0b8f7e2ed0f11..76c5a51cb7168 100644
--- a/x-pack/plugins/lens/public/xy_visualization/visualization.tsx
+++ b/x-pack/plugins/lens/public/xy_visualization/visualization.tsx
@@ -53,7 +53,7 @@ function getDescription(state?: State) {
return {
icon: LensIconChartBarHorizontal,
label: i18n.translate('xpack.lens.xyVisualization.mixedBarHorizontalLabel', {
- defaultMessage: 'Mixed horizontal bar',
+ defaultMessage: 'Mixed H. bar',
}),
};
}
@@ -118,14 +118,10 @@ export const xyVisualization: Visualization = {
getDescription(state) {
const { icon, label } = getDescription(state);
- const chartLabel = i18n.translate('xpack.lens.xyVisualization.chartLabel', {
- defaultMessage: '{label} chart',
- values: { label },
- });
return {
icon: icon || defaultIcon,
- label: chartLabel,
+ label,
};
},
diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json
index 01a39320a8e36..07ee08837182b 100644
--- a/x-pack/plugins/translations/translations/ja-JP.json
+++ b/x-pack/plugins/translations/translations/ja-JP.json
@@ -9659,15 +9659,12 @@
"xpack.lens.xySuggestions.unstackedChartTitle": "スタックが解除されました",
"xpack.lens.xySuggestions.yAxixConjunctionSign": " と ",
"xpack.lens.xyVisualization.areaLabel": "エリア",
- "xpack.lens.xyVisualization.barHorizontalLabel": "横棒",
"xpack.lens.xyVisualization.barLabel": "バー",
- "xpack.lens.xyVisualization.chartLabel": "{label} チャート",
"xpack.lens.xyVisualization.lineLabel": "折れ線",
"xpack.lens.xyVisualization.mixedBarHorizontalLabel": "ミックスされた横棒",
"xpack.lens.xyVisualization.mixedLabel": "ミックスされた XY",
"xpack.lens.xyVisualization.noDataLabel": "結果が見つかりませんでした",
"xpack.lens.xyVisualization.stackedAreaLabel": "スタックされたエリア",
- "xpack.lens.xyVisualization.stackedBarHorizontalLabel": "スタックされた横棒",
"xpack.lens.xyVisualization.stackedBarLabel": "スタックされたバー",
"xpack.lens.xyVisualization.xyLabel": "XY",
"xpack.licenseMgmt.app.checkingPermissionsErrorMessage": "パーミッションの確認中にエラーが発生",
diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json
index 2144dbecb0d03..71c1043b979c1 100644
--- a/x-pack/plugins/translations/translations/zh-CN.json
+++ b/x-pack/plugins/translations/translations/zh-CN.json
@@ -9665,15 +9665,12 @@
"xpack.lens.xySuggestions.unstackedChartTitle": "非堆叠",
"xpack.lens.xySuggestions.yAxixConjunctionSign": " & ",
"xpack.lens.xyVisualization.areaLabel": "面积图",
- "xpack.lens.xyVisualization.barHorizontalLabel": "水平条形图",
"xpack.lens.xyVisualization.barLabel": "条形图",
- "xpack.lens.xyVisualization.chartLabel": "{label} 图表",
"xpack.lens.xyVisualization.lineLabel": "折线图",
"xpack.lens.xyVisualization.mixedBarHorizontalLabel": "混合水平条形图",
"xpack.lens.xyVisualization.mixedLabel": "混合 XY",
"xpack.lens.xyVisualization.noDataLabel": "找不到结果",
"xpack.lens.xyVisualization.stackedAreaLabel": "堆叠面积图",
- "xpack.lens.xyVisualization.stackedBarHorizontalLabel": "堆叠水平条形图",
"xpack.lens.xyVisualization.stackedBarLabel": "堆叠条形图",
"xpack.lens.xyVisualization.xyLabel": "XY",
"xpack.licenseMgmt.app.checkingPermissionsErrorMessage": "检查权限时出错",