diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/chart_switch.tsx b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/chart_switch.tsx
index 4868c21bc5c5a..95eacf3483d62 100644
--- a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/chart_switch.tsx
+++ b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/chart_switch.tsx
@@ -200,7 +200,7 @@ export function ChartSwitch(props: Props) {
>
(
{i18n.translate('xpack.lens.configPanel.changeVisualization', {
- defaultMessage: 'Change',
+ defaultMessage: 'change',
})}
)
diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/editor_frame.test.tsx b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/editor_frame.test.tsx
index 7d9ff8918ab29..716ea75e39824 100644
--- a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/editor_frame.test.tsx
+++ b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/editor_frame.test.tsx
@@ -17,6 +17,7 @@ import {
DatasourceMock,
} from '../mocks';
import { ExpressionRenderer } from 'src/legacy/core_plugins/data/public';
+import { EuiPanel, EuiToolTip } from '@elastic/eui';
// calling this function will wait for all pending Promises from mock
// datasources to be processed by its callers.
@@ -1119,13 +1120,12 @@ describe('editor_frame', () => {
// TODO why is this necessary?
instance.update();
- const suggestions = instance.find('[data-test-subj="suggestion-title"]');
- expect(suggestions.map(el => el.text())).toEqual([
- 'Suggestion1',
- 'Suggestion2',
- 'Suggestion3',
- 'Suggestion4',
- ]);
+ expect(
+ instance
+ .find('[data-test-subj="lnsSuggestion"]')
+ .find(EuiPanel)
+ .map(el => el.parents(EuiToolTip).prop('content'))
+ ).toEqual(['Suggestion1', 'Suggestion2', 'Suggestion3', 'Suggestion4']);
});
it('should switch to suggested visualization', async () => {
@@ -1167,7 +1167,10 @@ describe('editor_frame', () => {
instance.update();
act(() => {
- instance.find('[data-test-subj="suggestion-title"]').simulate('click');
+ instance
+ .find('[data-test-subj="lnsSuggestion"]')
+ .first()
+ .simulate('click');
});
expect(mockVisualization.renderConfigPanel).toHaveBeenCalledTimes(1);
diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/frame_layout.tsx b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/frame_layout.tsx
index c630bc96704f3..8a33178de70cf 100644
--- a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/frame_layout.tsx
+++ b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/frame_layout.tsx
@@ -23,10 +23,10 @@ export function FrameLayout(props: FrameLayoutProps) {
{props.dataPanel}
{props.workspacePanel}
+ {props.suggestionsPanel}
{props.configPanel}
- {props.suggestionsPanel}
diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/index.scss b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/index.scss
index ba6ae3bf71bd7..72b5f1eb79638 100644
--- a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/index.scss
+++ b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/index.scss
@@ -1,3 +1,4 @@
+$lnsPanelMinWidth: $euiSize * 18;
.lnsPage {
padding: 0;
@@ -24,7 +25,7 @@
.lnsSidebar {
margin: 0;
flex: 1 0 18%;
- min-width: ($euiSize * 22);
+ min-width: $lnsPanelMinWidth + $euiSize;
display: flex;
flex-direction: column;
position: relative;
@@ -45,10 +46,13 @@
}
.lnsSidebar--right {
- min-width: ($euiSize * 22);
@include euiScrollBar;
- overflow: hidden auto;
- padding: $euiSize;
+ min-width: $lnsPanelMinWidth + $euiSize;
+ overflow-x: hidden;
+ overflow-y: auto;
+ padding-top: $euiSize;
+ padding-right: $euiSize;
+ max-height: 100%;
}
.lnsSidebarContainer {
@@ -64,31 +68,37 @@
.lnsPageBody {
@include euiScrollBar;
- padding-top: $euiSize;
- padding-bottom: $euiSize;
- overflow: hidden auto;
+ min-width: $lnsPanelMinWidth + $euiSizeXL;
+ overflow: hidden;
+ // Leave out bottom padding so the suggestions scrollbar stays flush to window edge
+ // This also means needing to add same amount of margin to page content and suggestion items
+ padding: $euiSize $euiSize 0;
&:first-child {
padding-left: $euiSize;
}
.lnsPageContent {
+ @include euiScrollBar;
+ overflow: hidden;
padding: 0;
+ margin-bottom: $euiSize;
display: flex;
flex-direction: column;
.lnsPageContentHeader {
- padding: $euiSize;
+ padding: $euiSizeS;
border-bottom: $euiBorderThin;
margin-bottom: 0;
}
.lnsPageContentBody {
+ @include euiScrollBar;
flex-grow: 1;
- padding: $euiSizeXL;
display: flex;
align-items: stretch;
justify-content: stretch;
+ overflow: auto;
> * {
flex: 1 1 100%;
@@ -108,6 +118,7 @@
align-items: center;
justify-content: center;
overflow-x: hidden;
+ padding: $euiSize;
}
.lnsTitleInput {
diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/suggestion_panel.scss b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/suggestion_panel.scss
index 2139b314ae314..add9df3f10dbd 100644
--- a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/suggestion_panel.scss
+++ b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/suggestion_panel.scss
@@ -1,21 +1,59 @@
-.lnsSidebar__suggestions {
- > * {
- margin-top: $euiSizeS;
+ // SASSTODO: Create this in EUI
+ @mixin lnsOverflowShadowHorizontal {
+ $hideHeight: $euiScrollBarCorner * 1.25;
+ mask-image: linear-gradient(to right,
+ transparentize(red, .9) 0%,
+ transparentize(red, 0) $hideHeight,
+ transparentize(red, 0) calc(100% - #{$hideHeight}),
+ transparentize(red, .9) 100%
+ );
+}
+
+.lnsSuggestionsPanel__title {
+ margin: $euiSizeS 0 $euiSizeXS;
+}
+
+.lnsSuggestionsPanel__suggestions {
+ @include euiScrollBar;
+ @include lnsOverflowShadowHorizontal;
+ padding-top: $euiSizeXS;
+ overflow-x: auto;
+ overflow-y: hidden;
+ display: flex;
+
+ // Padding / negative margins to make room for overflow shadow
+ padding-left: $euiSizeXS;
+ margin-left: -$euiSizeXS;
+
+ // Add margin to the next of the same type
+ > * + * {
+ margin-left: $euiSizeS;
}
}
-$suggestionHeight: 120px;
+// These sizes also match canvas' page thumbnails for consistency
+$lnsSuggestionHeight: 100px;
+$lnsSuggestionWidth: 150px;
+
+.lnsSuggestionPanel__button {
+ flex: 0 0 auto;
+ width: $lnsSuggestionWidth !important;
+ height: $lnsSuggestionHeight;
+ // Allows the scrollbar to stay flush to window
+ margin-bottom: $euiSize;
+}
.lnsSidebar__suggestionIcon {
+ color: $euiColorDarkShade;
width: 100%;
- height: $suggestionHeight;
+ height: 100%;
display: flex;
align-items: center;
justify-content: center;
- padding: $euiSize;
+ padding: $euiSizeS;
}
- .lnsSuggestionChartWrapper {
- height: $suggestionHeight;
- pointer-events: none;
- }
\ No newline at end of file
+.lnsSuggestionChartWrapper {
+ height: $lnsSuggestionHeight - $euiSize;
+ pointer-events: none;
+}
diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/suggestion_panel.test.tsx b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/suggestion_panel.test.tsx
index effadb27ddb43..d2f3b8e895aa6 100644
--- a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/suggestion_panel.test.tsx
+++ b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/suggestion_panel.test.tsx
@@ -17,7 +17,7 @@ import { ExpressionRenderer } from 'src/legacy/core_plugins/data/public';
import { SuggestionPanel, SuggestionPanelProps } from './suggestion_panel';
import { getSuggestions, Suggestion } from './suggestion_helpers';
import { fromExpression } from '@kbn/interpreter/target/common';
-import { EuiIcon } from '@elastic/eui';
+import { EuiIcon, EuiPanel, EuiToolTip } from '@elastic/eui';
jest.mock('./suggestion_helpers');
@@ -82,17 +82,19 @@ describe('suggestion_panel', () => {
it('should list passed in suggestions', () => {
const wrapper = mount();
- expect(wrapper.find('[data-test-subj="suggestion-title"]').map(el => el.text())).toEqual([
- 'Suggestion1',
- 'Suggestion2',
- ]);
+ expect(
+ wrapper
+ .find('[data-test-subj="lnsSuggestion"]')
+ .find(EuiPanel)
+ .map(el => el.parents(EuiToolTip).prop('content'))
+ ).toEqual(['Suggestion1', 'Suggestion2']);
});
it('should dispatch visualization switch action if suggestion is clicked', () => {
const wrapper = mount();
wrapper
- .find('[data-test-subj="suggestion-title"]')
+ .find('[data-test-subj="lnsSuggestion"]')
.first()
.simulate('click');
diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/suggestion_panel.tsx b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/suggestion_panel.tsx
index 1ee732df85908..aad24b4c3b9cd 100644
--- a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/suggestion_panel.tsx
+++ b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/suggestion_panel.tsx
@@ -6,7 +6,7 @@
import React, { useState, useEffect } from 'react';
import { FormattedMessage } from '@kbn/i18n/react';
-import { EuiIcon, EuiTitle, EuiPanel, EuiIconTip } from '@elastic/eui';
+import { EuiIcon, EuiTitle, EuiPanel, EuiIconTip, EuiToolTip } from '@elastic/eui';
import { toExpression } from '@kbn/interpreter/common';
import { i18n } from '@kbn/i18n';
import { Action } from './state_management';
@@ -51,46 +51,46 @@ const SuggestionPreview = ({
}, [previewExpression]);
return (
- {
- dispatch(toSwitchAction(suggestion));
- }}
- >
-
- {suggestion.title}
-
- {expressionError ? (
-
-
+ {
+ dispatch(toSwitchAction(suggestion));
+ }}
+ >
+ {expressionError ? (
+
+
+
+ ) : previewExpression ? (
+ {
+ // eslint-disable-next-line no-console
+ console.error(`Failed to render preview: `, e);
+ setExpressionError(true);
+ }}
/>
-
- ) : previewExpression ? (
- {
- // eslint-disable-next-line no-console
- console.error(`Failed to render preview: `, e);
- setExpressionError(true);
- }}
- />
- ) : (
-
-
-
- )}
-
+ ) : (
+
+
+
+ )}
+
+
);
};
@@ -125,8 +125,8 @@ function InnerSuggestionPanel({
}
return (
-
-
+
+
- {suggestions.map(suggestion => {
- const previewExpression = suggestion.previewExpression
- ? prependDatasourceExpression(
- suggestion.previewExpression,
- datasourceMap,
- datasourceStates
- )
- : null;
- return (
-
- );
- })}
+
+ {suggestions.map(suggestion => {
+ const previewExpression = suggestion.previewExpression
+ ? prependDatasourceExpression(
+ suggestion.previewExpression,
+ datasourceMap,
+ datasourceStates
+ )
+ : null;
+ return (
+
+ );
+ })}
+
);
}
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/datapanel.tsx b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/datapanel.tsx
index 07b48c0479b46..8451704f455f5 100644
--- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/datapanel.tsx
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/datapanel.tsx
@@ -124,7 +124,12 @@ export const InnerIndexPatternDataPanel = function InnerIndexPatternDataPanel({
if (Object.keys(indexPatterns).length === 0) {
return (
-
+
-
+
{!showIndexPatternSwitcher ? (
@@ -232,7 +242,11 @@ export const InnerIndexPatternDataPanel = function InnerIndexPatternDataPanel({
-
+