Skip to content

Commit 3faf8f7

Browse files
[Lens] Use flyout toolbar for visualization configuration: appearance, titles and text, axis, and legend settings (#240804)
## Summary Enables flyout toolbar in **dashboard visualization in-line editing** and **Lens workspace**, for appearance, titles and text, axis and legend settings configuration. Closes #238794 > [!IMPORTANT] > In #240088, we will delete all the deprecated components related to the previously used toolbar popover. ### Dashboard visualization in-line editing https://github.com/user-attachments/assets/a2e54633-bb1a-4796-8682-70b2c9beb1be ### Lens workspace https://github.com/user-attachments/assets/7eb2d165-180e-491c-a1d3-ea461d7c6a7e ## Checklist - [ ] [Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [ ] [Flaky Test Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was used on any tests changed - [x] The PR description includes the appropriate Release Notes section, and the correct `release_note:*` label is applied per the [guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process) - [x] Review the [backport guidelines](https://docs.google.com/document/d/1VyN5k91e5OVumlc0Gb9RPa3h1ewuPE705nRtioPiTvY/edit?usp=sharing) and apply applicable `backport:*` labels. ### Release Notes In **dashboard visualization in-line editing** and **Lens workspace**, the 'Appearance', 'Titles and text', 'Axis', and 'Legend' settings have been moved from a popover into a dedicated flyout panel. --------- Co-authored-by: kibanamachine <[email protected]>
1 parent f85ab43 commit 3faf8f7

File tree

48 files changed

+560
-697
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+560
-697
lines changed

src/platform/packages/shared/kbn-lens-common/visualizations/types.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -375,8 +375,8 @@ export interface Visualization<T = unknown, P = T, ExtraAppendLayerArg = unknown
375375
* in a flyout panel. Provides configuration options for style, legend and filters.
376376
*/
377377
FlyoutToolbarComponent?: (
378-
props: VisualizationToolbarProps<T>
379-
) => null | ReactElement<VisualizationToolbarProps<T>>;
378+
props: VisualizationToolbarProps<T> & { isInlineEditing: boolean }
379+
) => null | ReactElement<VisualizationToolbarProps<T> & { isInlineEditing: boolean }>;
380380

381381
/**
382382
* The frame is telling the visualization to update or set a dimension based on user interaction

x-pack/platform/plugins/shared/lens/public/app_plugin/shared/edit_on_the_fly/lens_configuration_flyout.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,9 @@ export function LensEditConfigurationFlyout({
294294
isSaveable={isSaveable}
295295
isReadOnly={isReadOnly}
296296
applyButtonLabel={applyButtonLabel}
297-
toolbar={<VisualizationToolbarWrapper framePublicAPI={framePublicAPI} />}
297+
toolbar={
298+
<VisualizationToolbarWrapper framePublicAPI={framePublicAPI} isInlineEditing={true} />
299+
}
298300
>
299301
<LayerConfiguration
300302
// TODO: remove this once we support switching to any chart in Discover
@@ -334,7 +336,9 @@ export function LensEditConfigurationFlyout({
334336
isNewPanel={isNewPanel}
335337
isReadOnly={isReadOnly}
336338
applyButtonLabel={applyButtonLabel}
337-
toolbar={<VisualizationToolbarWrapper framePublicAPI={framePublicAPI} />}
339+
toolbar={
340+
<VisualizationToolbarWrapper framePublicAPI={framePublicAPI} isInlineEditing={true} />
341+
}
338342
>
339343
<EuiFlexGroup
340344
css={css`

x-pack/platform/plugins/shared/lens/public/editor_frame_service/editor_frame/editor_frame.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,5 +218,7 @@ export function EditorFrame(props: EditorFrameProps) {
218218

219219
const componentStyles = {
220220
visualizationToolbar: ({ euiTheme }: UseEuiTheme) =>
221-
css({ margin: `${euiTheme.size.base} ${euiTheme.size.base} 0 ${euiTheme.size.base}` }),
221+
css({
222+
margin: `${euiTheme.size.base} ${euiTheme.size.base} ${euiTheme.size.s} ${euiTheme.size.base}`,
223+
}),
222224
};

x-pack/platform/plugins/shared/lens/public/editor_frame_service/editor_frame/visualization_toolbar.tsx

Lines changed: 24 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
* 2.0.
66
*/
77

8-
import React, { memo, useCallback } from 'react';
9-
import type { FramePublicAPI, Visualization } from '@kbn/lens-common';
8+
import { memo, useCallback } from 'react';
9+
import type { FramePublicAPI } from '@kbn/lens-common';
1010
import {
1111
useLensDispatch,
1212
updateVisualizationState,
@@ -16,17 +16,25 @@ import {
1616
} from '../../state_management';
1717
import { useEditorFrameService } from '../editor_frame_service_context';
1818

19-
const VisualizationToolbar = memo(function VisualizationToolbar({
20-
activeVisualization,
19+
export const VisualizationToolbarWrapper = memo(function VisualizationToolbar({
2120
framePublicAPI,
22-
enableFlyoutToolbar = false,
21+
isInlineEditing = false,
22+
enableFlyoutToolbar = true,
2323
}: {
24-
activeVisualization: Visualization | null;
2524
framePublicAPI: FramePublicAPI;
25+
isInlineEditing?: boolean;
2626
enableFlyoutToolbar?: boolean;
2727
}) {
2828
const dispatchLens = useLensDispatch();
29-
const visualization = useLensSelector(selectVisualizationState);
29+
const lensVisualization = useLensSelector(selectVisualization);
30+
const visualizationState = useLensSelector(selectVisualizationState);
31+
32+
const { visualizationMap } = useEditorFrameService();
33+
34+
const activeVisualization = lensVisualization.activeId
35+
? visualizationMap[lensVisualization.activeId]
36+
: null;
37+
3038
const setVisualizationState = useCallback(
3139
(newState: unknown) => {
3240
if (!activeVisualization) {
@@ -42,43 +50,25 @@ const VisualizationToolbar = memo(function VisualizationToolbar({
4250
[dispatchLens, activeVisualization]
4351
);
4452

53+
if (!activeVisualization || !visualizationState) {
54+
return null;
55+
}
56+
4557
const { FlyoutToolbarComponent, ToolbarComponent: RegularToolbarComponent } =
4658
activeVisualization ?? {};
4759

48-
let ToolbarComponent;
49-
if (enableFlyoutToolbar) {
50-
ToolbarComponent = FlyoutToolbarComponent ?? RegularToolbarComponent;
51-
} else {
52-
ToolbarComponent = RegularToolbarComponent;
53-
}
60+
const ToolbarComponent = enableFlyoutToolbar
61+
? FlyoutToolbarComponent ?? RegularToolbarComponent
62+
: RegularToolbarComponent;
5463

5564
if (!ToolbarComponent) {
5665
return null;
5766
}
5867

5968
return ToolbarComponent({
6069
frame: framePublicAPI,
61-
state: visualization.state,
70+
state: visualizationState.state,
6271
setState: setVisualizationState,
72+
isInlineEditing,
6373
});
6474
});
65-
66-
export function VisualizationToolbarWrapper({
67-
framePublicAPI,
68-
}: {
69-
framePublicAPI: FramePublicAPI;
70-
}) {
71-
const { visualizationMap } = useEditorFrameService();
72-
const visualization = useLensSelector(selectVisualization);
73-
74-
const activeVisualization = visualization.activeId
75-
? visualizationMap[visualization.activeId]
76-
: null;
77-
78-
return activeVisualization && visualization.state ? (
79-
<VisualizationToolbar
80-
framePublicAPI={framePublicAPI}
81-
activeVisualization={activeVisualization}
82-
/>
83-
) : null;
84-
}

x-pack/platform/plugins/shared/lens/public/shared_components/flyout_container.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@ export function FlyoutContainer({
8888
return null;
8989
}
9090

91+
const hideShadow = isInlineEditing || isFullscreen;
92+
9193
return (
9294
<div ref={panelRef}>
9395
<EuiFocusTrap
@@ -107,7 +109,7 @@ export function FlyoutContainer({
107109
aria-labelledby="lnsDimensionContainerTitle"
108110
css={[
109111
css`
110-
box-shadow: ${isInlineEditing || isFullscreen ? 'none !important' : 'inherit'};
112+
box-shadow: ${hideShadow ? 'none !important' : 'inherit'};
111113
`,
112114
flyoutContainerStyles(euiThemeContext),
113115
dimensionContainerStyles.self(euiThemeContext),

x-pack/platform/plugins/shared/lens/public/shared_components/flyout_toolbar.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,11 @@ export interface ToolbarContentMap<S> {
6161

6262
export function FlyoutToolbar<S>({
6363
contentMap,
64+
isInlineEditing = false,
6465
...flyoutContentProps
6566
}: VisualizationToolbarProps<S> & {
6667
contentMap: ToolbarContentMap<S>;
68+
isInlineEditing: boolean;
6769
}) {
6870
const [isFlyoutVisible, setFlyoutVisible] = useState(false);
6971
const [idSelected, setIdSelected] = useState<Options | ''>('');
@@ -109,7 +111,7 @@ export function FlyoutToolbar<S>({
109111
<FlyoutContainer
110112
isFullscreen={false}
111113
label={flyoutTitle}
112-
isInlineEditing={true}
114+
isInlineEditing={isInlineEditing}
113115
isOpen={isFlyoutVisible}
114116
handleClose={() => {
115117
setIdSelected('');

x-pack/platform/plugins/shared/lens/public/visualizations/datatable/components/toolbar.test.tsx renamed to x-pack/platform/plugins/shared/lens/public/visualizations/datatable/components/appearance_settings.test.tsx

Lines changed: 14 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,15 @@
77

88
import React from 'react';
99
import { getSelectedButtonInGroup } from '@kbn/test-eui-helpers';
10-
import { DataTableToolbar } from './toolbar';
1110
import type {
1211
DatatableVisualizationState,
1312
PagingState,
1413
FramePublicAPI,
1514
VisualizationToolbarProps,
1615
} from '@kbn/lens-common';
1716
import { fireEvent, render, screen, within } from '@testing-library/react';
18-
import userEvent from '@testing-library/user-event';
1917
import { DataGridDensity } from '@kbn/unified-data-table';
18+
import { DatatableAppearanceSettings } from './appearance_settings';
2019

2120
// mocking random id generator function
2221
jest.mock('@elastic/eui', () => {
@@ -30,7 +29,7 @@ jest.mock('@elastic/eui', () => {
3029
};
3130
});
3231

33-
describe('datatable toolbar', () => {
32+
describe('datatable appearance settings', () => {
3433
const defaultPagingState: PagingState = {
3534
size: 10,
3635
enabled: true,
@@ -46,17 +45,12 @@ describe('datatable toolbar', () => {
4645
};
4746
});
4847

49-
const renderAndOpenToolbar = async (overrides = {}) => {
48+
const renderComponent = async (overrides = {}) => {
5049
const ROW_HEIGHT_SETTINGS_TEST_ID = 'lnsRowHeightSettings';
5150
const HEADER_HEIGHT_SETTINGS_TEST_ID = 'lnsHeaderHeightSettings';
5251
const DENSITY_SETTINGS_TEST_ID = 'lnsDensitySettings';
5352

54-
const rtlRender = render(<DataTableToolbar {...defaultProps} {...overrides} />);
55-
56-
const togglePopover = async () => {
57-
await userEvent.click(screen.getByRole('button', { name: /visual options/i }));
58-
};
59-
await togglePopover();
53+
const rtlRender = render(<DatatableAppearanceSettings {...defaultProps} {...overrides} />);
6054

6155
const selectOptionFromButtonGroup = (testId: string) => (optionName: string | RegExp) => {
6256
const buttonGroup = screen.getByTestId(testId);
@@ -74,7 +68,6 @@ describe('datatable toolbar', () => {
7468

7569
return {
7670
...rtlRender,
77-
togglePopover,
7871
getRowHeightValue: getSelectedButtonInGroup(ROW_HEIGHT_SETTINGS_TEST_ID),
7972
getRowHeightCustomValue: () => getNumberInput(ROW_HEIGHT_SETTINGS_TEST_ID),
8073
selectRowHeightOption: selectOptionFromButtonGroup(ROW_HEIGHT_SETTINGS_TEST_ID),
@@ -96,7 +89,7 @@ describe('datatable toolbar', () => {
9689
getHeaderHeightValue,
9790
getPaginationSwitch,
9891
getDensityValue,
99-
} = await renderAndOpenToolbar();
92+
} = await renderComponent();
10093

10194
expect(getRowHeightValue()).toHaveTextContent(/custom/i);
10295
expect(getHeaderHeightValue()).toHaveTextContent(/custom/i);
@@ -113,7 +106,7 @@ describe('datatable toolbar', () => {
113106
getHeaderHeightCustomValue,
114107
getRowHeightCustomValue,
115108
getDensityValue,
116-
} = await renderAndOpenToolbar({
109+
} = await renderComponent({
117110
state: {
118111
...defaultProps.state,
119112
rowHeight: 'custom',
@@ -134,7 +127,7 @@ describe('datatable toolbar', () => {
134127
});
135128

136129
it('should change row height to "Auto" mode when selected', async () => {
137-
const { selectRowHeightOption } = await renderAndOpenToolbar();
130+
const { selectRowHeightOption } = await renderComponent();
138131

139132
selectRowHeightOption(/auto/i);
140133
expect(defaultProps.setState).toHaveBeenCalledTimes(1);
@@ -144,7 +137,7 @@ describe('datatable toolbar', () => {
144137
});
145138

146139
it('should toggle pagination on click', async () => {
147-
const { clickPaginationSwitch } = await renderAndOpenToolbar();
140+
const { clickPaginationSwitch } = await renderComponent();
148141

149142
clickPaginationSwitch();
150143
expect(defaultProps.setState).toHaveBeenCalledTimes(1);
@@ -154,7 +147,7 @@ describe('datatable toolbar', () => {
154147
});
155148

156149
it('should change row height to "Custom" mode when selected', async () => {
157-
const { selectRowHeightOption } = await renderAndOpenToolbar();
150+
const { selectRowHeightOption } = await renderComponent();
158151

159152
selectRowHeightOption(/custom/i);
160153
expect(defaultProps.setState).toHaveBeenCalledTimes(1);
@@ -165,7 +158,7 @@ describe('datatable toolbar', () => {
165158
});
166159

167160
it('should change header height to "Custom" mode', async () => {
168-
const { selectHeaderHeightOption } = await renderAndOpenToolbar({
161+
const { selectHeaderHeightOption } = await renderComponent({
169162
headerRowHeight: 'auto',
170163
});
171164

@@ -178,7 +171,7 @@ describe('datatable toolbar', () => {
178171
});
179172

180173
it('should toggle on table pagination', async () => {
181-
const { clickPaginationSwitch } = await renderAndOpenToolbar();
174+
const { clickPaginationSwitch } = await renderComponent();
182175

183176
clickPaginationSwitch();
184177
expect(defaultProps.setState).toHaveBeenCalledTimes(1);
@@ -189,7 +182,7 @@ describe('datatable toolbar', () => {
189182
);
190183
});
191184
it('should toggle off table pagination', async () => {
192-
const { clickPaginationSwitch } = await renderAndOpenToolbar({
185+
const { clickPaginationSwitch } = await renderComponent({
193186
state: {
194187
...defaultProps.state,
195188
paging: defaultPagingState,
@@ -205,7 +198,7 @@ describe('datatable toolbar', () => {
205198
});
206199

207200
it('should change density to "Compact" when selected', async () => {
208-
const { selectDensityOption } = await renderAndOpenToolbar();
201+
const { selectDensityOption } = await renderComponent();
209202
selectDensityOption(/compact/i);
210203
expect(defaultProps.setState).toHaveBeenCalledTimes(1);
211204
expect(defaultProps.setState).toHaveBeenCalledWith({
@@ -214,7 +207,7 @@ describe('datatable toolbar', () => {
214207
});
215208

216209
it('should change density to "Expanded" when selected', async () => {
217-
const { selectDensityOption } = await renderAndOpenToolbar();
210+
const { selectDensityOption } = await renderComponent();
218211
selectDensityOption(/expanded/i);
219212
expect(defaultProps.setState).toHaveBeenCalledTimes(1);
220213
expect(defaultProps.setState).toHaveBeenCalledWith({

0 commit comments

Comments
 (0)