From 50f59ad8cbc60640c86f1c7e085e62da4e0ab0ab Mon Sep 17 00:00:00 2001 From: Stephanie Roy Date: Mon, 16 Oct 2023 13:14:43 -0400 Subject: [PATCH 1/2] Add a tooltip to plots with long titles that are cut by Vega --- webview/src/plots/components/App.test.tsx | 72 +++++++++++++++++++ webview/src/plots/components/ZoomablePlot.tsx | 69 +++++++++--------- .../plots/components/ZoomablePlotWrapper.tsx | 21 ++++++ 3 files changed, 129 insertions(+), 33 deletions(-) create mode 100644 webview/src/plots/components/ZoomablePlotWrapper.tsx diff --git a/webview/src/plots/components/App.test.tsx b/webview/src/plots/components/App.test.tsx index 39795f19e7..bafd7ee1a4 100644 --- a/webview/src/plots/components/App.test.tsx +++ b/webview/src/plots/components/App.test.tsx @@ -2637,6 +2637,78 @@ describe('App', () => { expect(clickEvent.stopPropagation).toHaveBeenCalledTimes(1) }) + it('should have a tooltip on the plot if the title is cut', () => { + const title = 'Plot with a long title' + renderAppWithOptionalData({ + template: { + ...templatePlotsFixture, + plots: [ + { + entries: [ + { + ...templatePlotsFixture.plots[0].entries[0], + content: { + ...templatePlotsFixture.plots[0].entries[0].content, + title: '… with a long title' + } as unknown as VisualizationSpec, + id: title + } + ], + group: TemplatePlotGroup.SINGLE_VIEW + } + ] + } + }) + + expect(screen.queryByText(title)).not.toBeInTheDocument() + + const plot = within(screen.getByTestId(`plot_${title}`)).getAllByRole( + 'button' + )[0] + fireEvent.mouseEnter(plot, { + bubbles: true, + cancelable: true + }) + + expect(screen.getByText(title)).toBeInTheDocument() + }) + + it('should not have a tooltip on the plot if the title is not cut', () => { + const title = 'Short title' + renderAppWithOptionalData({ + template: { + ...templatePlotsFixture, + plots: [ + { + entries: [ + { + ...templatePlotsFixture.plots[0].entries[0], + content: { + ...templatePlotsFixture.plots[0].entries[0].content, + title + } as unknown as VisualizationSpec, + id: title + } + ], + group: TemplatePlotGroup.SINGLE_VIEW + } + ] + } + }) + + expect(screen.queryByText(title)).not.toBeInTheDocument() + + const plot = within(screen.getByTestId(`plot_${title}`)).getAllByRole( + 'button' + )[0] + fireEvent.mouseEnter(plot, { + bubbles: true, + cancelable: true + }) + + expect(screen.queryByText(title)).not.toBeInTheDocument() + }) + describe('Smooth Plots', () => { const waitSetValuePostMessage = (value: number) => waitFor( diff --git a/webview/src/plots/components/ZoomablePlot.tsx b/webview/src/plots/components/ZoomablePlot.tsx index d426009284..806e27bbc0 100644 --- a/webview/src/plots/components/ZoomablePlot.tsx +++ b/webview/src/plots/components/ZoomablePlot.tsx @@ -4,6 +4,7 @@ import React, { useEffect, useRef } from 'react' import { useDispatch } from 'react-redux' import { VisualizationSpec } from 'react-vega' import VegaLite, { VegaLiteProps } from 'react-vega/lib/VegaLite' +import { ZoomablePlotWrapper } from './ZoomablePlotWrapper' import { TemplateVegaLite } from './templatePlots/TemplateVegaLite' import { setZoomedInPlot } from './webviewSlice' import styles from './styles.module.scss' @@ -77,39 +78,41 @@ export const ZoomablePlot: React.FC = ({ } return ( - + + { + event.stopPropagation() + handleOnClick(true) + }} + onKeyDown={event => { + if (event.key === 'Enter') { + handleOnClick(true) + } + }} + role="button" + tabIndex={0} + aria-label="See Plot Export Options" + > + + + {currentPlotProps.current && + (isTemplatePlot ? ( + + ) : ( + + ))} + + ) } diff --git a/webview/src/plots/components/ZoomablePlotWrapper.tsx b/webview/src/plots/components/ZoomablePlotWrapper.tsx new file mode 100644 index 0000000000..bc4eda3c7c --- /dev/null +++ b/webview/src/plots/components/ZoomablePlotWrapper.tsx @@ -0,0 +1,21 @@ +import React, { ReactElement, PropsWithChildren } from 'react' +import Tooltip from '../../shared/components/tooltip/Tooltip' + +interface ZoomablePlotWrapperProps { + title?: string + id: string +} + +export const ZoomablePlotWrapper: React.FC< + PropsWithChildren +> = ({ title, id, children }) => { + const isTitleCut = title?.indexOf('…') === 0 + + return isTitleCut ? ( + + {children as ReactElement} + + ) : ( + children + ) +} From 33a94c7530a684eb4e078ba11652ac748315c6b6 Mon Sep 17 00:00:00 2001 From: Stephanie Roy Date: Tue, 17 Oct 2023 10:16:15 -0400 Subject: [PATCH 2/2] Add tooltip inside zoomed in plot and correctly make it interactive --- .../plots/components/ZoomablePlotWrapper.tsx | 2 +- webview/src/plots/components/ZoomedInPlot.tsx | 33 ++++++++++--------- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/webview/src/plots/components/ZoomablePlotWrapper.tsx b/webview/src/plots/components/ZoomablePlotWrapper.tsx index bc4eda3c7c..5a7540b319 100644 --- a/webview/src/plots/components/ZoomablePlotWrapper.tsx +++ b/webview/src/plots/components/ZoomablePlotWrapper.tsx @@ -12,7 +12,7 @@ export const ZoomablePlotWrapper: React.FC< const isTitleCut = title?.indexOf('…') === 0 return isTitleCut ? ( - + {children as ReactElement} ) : ( diff --git a/webview/src/plots/components/ZoomedInPlot.tsx b/webview/src/plots/components/ZoomedInPlot.tsx index ebbf80024f..3cf2bfebfe 100644 --- a/webview/src/plots/components/ZoomedInPlot.tsx +++ b/webview/src/plots/components/ZoomedInPlot.tsx @@ -9,6 +9,7 @@ import { } from 'dvc/src/plots/vega/util' import { TemplateVegaLite } from './templatePlots/TemplateVegaLite' import styles from './styles.module.scss' +import { ZoomablePlotWrapper } from './ZoomablePlotWrapper' import { getThemeValue, ThemeProperty } from '../../util/styles' import { exportPlotDataAsCsv, @@ -101,20 +102,22 @@ export const ZoomedInPlot: React.FC = ({ } return ( -
- {isTemplatePlot ? ( - - ) : ( - - )} -
+ +
+ {isTemplatePlot ? ( + + ) : ( + + )} +
+
) }