Skip to content

Commit e52033f

Browse files
authored
Create (shared) section container component (#3440)
* create shared section container component * pull out toggle section from shared component
1 parent 78fe80b commit e52033f

File tree

5 files changed

+253
-211
lines changed

5 files changed

+253
-211
lines changed

webview/src/plots/components/App.test.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ import { EXPERIMENT_WORKSPACE_ID } from 'dvc/src/cli/dvc/contract'
4040
import { VisualizationSpec } from 'react-vega'
4141
import { App } from './App'
4242
import { NewSectionBlock } from './templatePlots/TemplatePlots'
43-
import { SectionDescription } from './PlotsContainer'
4443
import {
4544
CheckpointPlotsById,
4645
plotDataStore,
@@ -55,6 +54,7 @@ import {
5554
dragEnter,
5655
dragLeave
5756
} from '../../test/dragDrop'
57+
import { SectionDescription } from '../../shared/components/sectionContainer/SectionContainer'
5858
import { DragEnterDirection } from '../../shared/components/dragDrop/util'
5959
import { clearSelection, createWindowTextSelection } from '../../test/selection'
6060
import * as EventCurrentTargetDistances from '../../shared/components/dragDrop/currentTarget'
@@ -163,7 +163,7 @@ describe('App', () => {
163163

164164
const getCheckpointMenuItem = (position: number) =>
165165
within(
166-
screen.getAllByTestId('plots-container')[
166+
screen.getAllByTestId('section-container')[
167167
sectionPosition[Section.CHECKPOINT_PLOTS]
168168
]
169169
).getAllByTestId('icon-menu-item')[position]
@@ -899,7 +899,7 @@ describe('App', () => {
899899
})
900900

901901
const [pickerButton] = within(
902-
screen.getAllByTestId('plots-container')[
902+
screen.getAllByTestId('section-container')[
903903
sectionPosition[Section.CHECKPOINT_PLOTS]
904904
]
905905
).queryAllByTestId('icon-menu-item')
Lines changed: 47 additions & 144 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import cx from 'classnames'
22
import React, {
3-
MouseEvent,
43
useEffect,
54
DetailedHTMLProps,
65
HTMLAttributes,
@@ -12,23 +11,12 @@ import { Section } from 'dvc/src/plots/webview/contract'
1211
import { MessageFromWebviewType } from 'dvc/src/webview/contract'
1312
import { PlotsPicker, PlotsPickerProps } from './PlotsPicker'
1413
import styles from './styles.module.scss'
15-
import { Icon } from '../../shared/components/Icon'
16-
import { IconMenu } from '../../shared/components/iconMenu/IconMenu'
1714
import { IconMenuItemProps } from '../../shared/components/iconMenu/IconMenuItem'
1815
import { sendMessage } from '../../shared/vscode'
19-
import Tooltip from '../../shared/components/tooltip/Tooltip'
20-
import {
21-
ChevronDown,
22-
ChevronRight,
23-
Info,
24-
Lines,
25-
Add,
26-
Trash
27-
} from '../../shared/components/icons'
28-
import { isSelecting } from '../../util/strings'
29-
import { isTooltip } from '../../util/helpers'
16+
import { Lines, Add, Trash } from '../../shared/components/icons'
3017
import { MinMaxSlider } from '../../shared/components/slider/MinMaxSlider'
3118
import { PlotsState } from '../store'
19+
import { SectionContainer } from '../../shared/components/sectionContainer/SectionContainer'
3220

3321
export interface PlotsContainerProps {
3422
sectionCollapsed: boolean
@@ -43,58 +31,6 @@ export interface PlotsContainerProps {
4331
hasItems?: boolean
4432
}
4533

46-
export const SectionDescription = {
47-
// "Trends"
48-
[Section.CHECKPOINT_PLOTS]: (
49-
<span data-testid="tooltip-checkpoint-plots">
50-
Automatically generated and updated linear plots that show metric value
51-
per epoch if{' '}
52-
<a href="https://dvc.org/doc/user-guide/experiment-management/checkpoints">
53-
checkpoints
54-
</a>{' '}
55-
are enabled.
56-
</span>
57-
),
58-
// "Custom"
59-
[Section.CUSTOM_PLOTS]: (
60-
<span data-testid="tooltip-custom-plots">
61-
Generated custom linear plots comparing chosen metrics and params in all
62-
experiments in the table.
63-
</span>
64-
),
65-
// "Images"
66-
[Section.COMPARISON_TABLE]: (
67-
<span data-testid="tooltip-comparison-plots">
68-
Images (e.g. any <code>.jpg</code>, <code>.svg</code>, or
69-
<code>.png</code> file) rendered side by side across experiments. They
70-
should be registered as{' '}
71-
<a href="https://dvc.org/doc/user-guide/experiment-management/visualizing-plots">
72-
plots
73-
</a>
74-
.
75-
</span>
76-
),
77-
// "Data Series"
78-
[Section.TEMPLATE_PLOTS]: (
79-
<span data-testid="tooltip-template-plots">
80-
Any <code>JSON</code>, <code>YAML</code>, <code>CSV</code>, or{' '}
81-
<code>TSV</code> file(s) with data points, visualized using{' '}
82-
<a href="https://dvc.org/doc/user-guide/experiment-management/visualizing-plots#plot-templates-data-series-only">
83-
plot templates
84-
</a>
85-
. Either predefined (e.g. confusion matrix, linear) or{' '}
86-
<a href="https://dvc.org/doc/command-reference/plots/templates#custom-templates">
87-
custom Vega-lite templates
88-
</a>
89-
.
90-
</span>
91-
)
92-
}
93-
94-
const InfoIcon = () => (
95-
<Icon icon={Info} width={16} height={16} className={styles.infoIcon} />
96-
)
97-
9834
export const PlotsContainer: React.FC<PlotsContainerProps> = ({
9935
sectionCollapsed,
10036
sectionKey,
@@ -143,28 +79,6 @@ export const PlotsContainer: React.FC<PlotsContainerProps> = ({
14379
})
14480
}
14581

146-
const tooltipContent = (
147-
<div className={styles.infoTooltip}>
148-
<InfoIcon />
149-
{SectionDescription[sectionKey]}
150-
</div>
151-
)
152-
153-
const toggleSection = (e: MouseEvent) => {
154-
e.preventDefault()
155-
if (
156-
!isSelecting([title, SectionDescription[sectionKey].props.children]) &&
157-
!isTooltip(e.target as Element, ['SUMMARY', 'BODY'])
158-
) {
159-
sendMessage({
160-
payload: {
161-
[sectionKey]: !sectionCollapsed
162-
},
163-
type: MessageFromWebviewType.TOGGLE_PLOTS_SECTION
164-
})
165-
}
166-
}
167-
16882
const handleResize = useCallback(
16983
(nbItems: number) => {
17084
if (changeNbItemsPerRow) {
@@ -183,66 +97,55 @@ export const PlotsContainer: React.FC<PlotsContainerProps> = ({
18397
[dispatch, changeNbItemsPerRow, sectionKey]
18498
)
18599

100+
const toggleSection = () =>
101+
sendMessage({
102+
payload: {
103+
[sectionKey]: !sectionCollapsed
104+
},
105+
type: MessageFromWebviewType.TOGGLE_PLOTS_SECTION
106+
})
107+
186108
return (
187-
<div className={styles.plotsContainerWrapper} data-testid="plots-container">
188-
<details open={open} className={styles.plotsContainer}>
189-
<summary onClick={toggleSection}>
190-
<Icon
191-
icon={open ? ChevronDown : ChevronRight}
192-
data-testid="plots-container-details-chevron"
193-
width={20}
194-
height={20}
195-
className={styles.detailsIcon}
109+
<SectionContainer
110+
menuItems={menuItems}
111+
sectionCollapsed={sectionCollapsed}
112+
sectionKey={sectionKey}
113+
title={title}
114+
onToggleSection={toggleSection}
115+
>
116+
{changeNbItemsPerRow && hasItems && maxNbPlotsPerRow > 1 && (
117+
<div
118+
className={styles.nbItemsPerRowSlider}
119+
data-testid="nb-items-per-row-slider"
120+
>
121+
<MinMaxSlider
122+
maximum={-1}
123+
minimum={-maxNbPlotsPerRow}
124+
label="Plot Width"
125+
onChange={handleResize}
126+
defaultValue={-nbItemsPerRow}
196127
/>
197-
{title}
198-
<Tooltip content={tooltipContent} placement="bottom-end" interactive>
199-
<div
200-
className={styles.infoTooltipToggle}
201-
data-testid="info-tooltip-toggle"
128+
</div>
129+
)}
130+
{open && (
131+
<div
132+
className={cx({
133+
[styles.plotsWrapper]: sectionKey !== Section.COMPARISON_TABLE,
134+
[styles.smallPlots]: nbItemsPerRow >= 4
135+
})}
136+
style={
137+
{
138+
'--nbPerRow': nbItemsPerRow
139+
} as DetailedHTMLProps<
140+
HTMLAttributes<HTMLDivElement>,
141+
HTMLDivElement
202142
>
203-
<InfoIcon />
204-
</div>
205-
</Tooltip>
206-
</summary>
207-
{changeNbItemsPerRow && hasItems && maxNbPlotsPerRow > 1 && (
208-
<div
209-
className={styles.nbItemsPerRowSlider}
210-
data-testid="nb-items-per-row-slider"
211-
>
212-
<MinMaxSlider
213-
maximum={-1}
214-
minimum={-maxNbPlotsPerRow}
215-
label="Plot Width"
216-
onChange={handleResize}
217-
defaultValue={-nbItemsPerRow}
218-
/>
219-
</div>
220-
)}
221-
{open && (
222-
<div
223-
className={cx({
224-
[styles.plotsWrapper]: sectionKey !== Section.COMPARISON_TABLE,
225-
[styles.smallPlots]: nbItemsPerRow >= 4
226-
})}
227-
style={
228-
{
229-
'--nbPerRow': nbItemsPerRow
230-
} as DetailedHTMLProps<
231-
HTMLAttributes<HTMLDivElement>,
232-
HTMLDivElement
233-
>
234-
}
235-
data-testid="plots-wrapper"
236-
>
237-
{children}
238-
</div>
239-
)}
240-
</details>
241-
{menuItems.length > 0 && (
242-
<div className={styles.iconMenu}>
243-
<IconMenu items={menuItems} />
143+
}
144+
data-testid="plots-wrapper"
145+
>
146+
{children}
244147
</div>
245148
)}
246-
</div>
149+
</SectionContainer>
247150
)
248151
}

webview/src/plots/components/styles.module.scss

Lines changed: 0 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -8,38 +8,6 @@ $gap: 20px;
88
height: 100%;
99
}
1010

11-
.plotsContainer {
12-
width: 100%;
13-
14-
summary {
15-
list-style-type: none;
16-
font-family: var(--vscode-font-family);
17-
margin: 14px 10px;
18-
font-weight: bold;
19-
font-size: 1.25rem;
20-
display: flex;
21-
align-items: center;
22-
width: max-content;
23-
cursor: pointer;
24-
}
25-
}
26-
27-
.plotsContainerWrapper {
28-
position: relative;
29-
}
30-
31-
.detailsIcon {
32-
fill: $fg-color;
33-
margin-bottom: -4px;
34-
}
35-
36-
.iconMenu {
37-
position: absolute;
38-
right: $gap;
39-
top: -15px;
40-
z-index: 10;
41-
}
42-
4311
.plotsWrapper {
4412
width: 100%;
4513
}
@@ -256,38 +224,6 @@ $gap: 20px;
256224
}
257225
}
258226

259-
.infoTooltipToggle {
260-
display: flex;
261-
align-items: center;
262-
cursor: initial;
263-
}
264-
265-
.infoIcon {
266-
fill: $accent-color;
267-
margin-left: 6px;
268-
}
269-
270-
.infoTooltip {
271-
max-width: 340px;
272-
margin-left: 5px;
273-
white-space: normal;
274-
display: flex;
275-
gap: 4px;
276-
line-height: 16px;
277-
font-size: 13px;
278-
font-weight: 400;
279-
cursor: auto;
280-
281-
svg {
282-
min-width: 16px;
283-
min-height: 16px;
284-
}
285-
286-
a {
287-
text-decoration: none;
288-
}
289-
}
290-
291227
.nbItemsPerRowSlider {
292228
display: flex;
293229
justify-content: end;

0 commit comments

Comments
 (0)