Skip to content

Commit 34ed830

Browse files
authored
Switch experiment table radio buttons to plot icons (#4121)
* switch experiment table radio buttons to plot icons * move towards Studio design * self review * move fill to background color * shrink icon and change selected color
1 parent 680877e commit 34ed830

File tree

8 files changed

+90
-104
lines changed

8 files changed

+90
-104
lines changed

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -668,10 +668,10 @@ describe('App', () => {
668668

669669
expect(screen.queryByRole('tooltip')).not.toBeInTheDocument()
670670

671-
const radioButton = within(getRow(EXPERIMENT_WORKSPACE_ID)).getByTestId(
671+
const plotIcon = within(getRow(EXPERIMENT_WORKSPACE_ID)).getByTestId(
672672
'row-action-plot'
673673
)
674-
fireEvent.mouseEnter(radioButton)
674+
fireEvent.mouseEnter(plotIcon)
675675

676676
advanceTimersByTime(NORMAL_TOOLTIP_DELAY[0])
677677
const tooltip = screen.queryByRole('tooltip')
@@ -692,8 +692,8 @@ describe('App', () => {
692692

693693
expect(screen.queryByRole('tooltip')).not.toBeInTheDocument()
694694

695-
const radioButton = within(getRow('main')).getByTestId('row-action-star')
696-
fireEvent.mouseEnter(radioButton)
695+
const starIcon = within(getRow('main')).getByTestId('row-action-star')
696+
fireEvent.mouseEnter(starIcon)
697697

698698
advanceTimersByTime(NORMAL_TOOLTIP_DELAY[0])
699699
const tooltip = screen.queryByRole('tooltip')

webview/src/experiments/components/table/body/Cell.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { flexRender } from '@tanstack/react-table'
22
import React, { ReactNode } from 'react'
3+
import { VSCodeProgressRing } from '@vscode/webview-ui-toolkit/react'
34
import cx from 'classnames'
5+
import { isRunning } from 'dvc/src/experiments/webview/contract'
46
import { CellRowActionsProps, CellRowActions } from './CellRowActions'
57
import styles from '../styles.module.scss'
68
import { CellValue, isValueWithChanges } from '../content/Cell'
@@ -59,6 +61,12 @@ export const FirstCell: React.FC<
5961
<div className={styles.innerCell} style={{ width: getSize() }}>
6062
<CellRowActions status={status} {...rowActionsProps} />
6163
<RowExpansionButton row={row} />
64+
{isRunning(status) && (
65+
<VSCodeProgressRing
66+
className={cx(styles.running, 'chromatic-ignore')}
67+
/>
68+
)}
69+
6270
{getIsPlaceholder() ? null : (
6371
<ErrorTooltip error={error}>
6472
<div

webview/src/experiments/components/table/body/CellRowActions.tsx

Lines changed: 48 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,24 @@ import { Indicator } from '../Indicators'
99
import { addStarredFilter, openPlotsWebview } from '../../../util/messages'
1010
import styles from '../styles.module.scss'
1111
import { clickAndEnterProps } from '../../../../util/props'
12-
import { Clock, StarFull, StarEmpty } from '../../../../shared/components/icons'
12+
import {
13+
Clock,
14+
StarFull,
15+
StarEmpty,
16+
GraphScatter
17+
} from '../../../../shared/components/icons'
18+
import { Icon } from '../../../../shared/components/Icon'
1319

1420
export type CellRowActionsProps = {
15-
bulletColor?: string
1621
isRowSelected: boolean
22+
plotColor?: string
1723
showSubRowStates: boolean
1824
starred?: boolean
1925
status?: ExperimentStatus
2026
subRowStates: {
27+
plotSelections: number
2128
selections: number
2229
stars: number
23-
plotSelections: number
2430
}
2531
toggleExperiment: () => void
2632
toggleRowSelection: () => void
@@ -37,12 +43,12 @@ type CellRowActionProps = {
3743
}
3844

3945
const CellRowAction: React.FC<CellRowActionProps> = ({
46+
children,
47+
onClick,
4048
showSubRowStates,
4149
subRowsAffected,
42-
children,
4350
testId,
44-
tooltipContent,
45-
onClick
51+
tooltipContent
4652
}) => {
4753
const count = (showSubRowStates && subRowsAffected) || 0
4854

@@ -81,13 +87,13 @@ const ClickableTooltipContent: React.FC<ClickableTooltipContentProps> = ({
8187
)
8288

8389
export const CellRowActions: React.FC<CellRowActionsProps> = ({
84-
bulletColor,
90+
plotColor,
8591
status,
8692
toggleExperiment,
8793
isRowSelected,
8894
showSubRowStates,
8995
starred,
90-
subRowStates: { selections, stars, plotSelections },
96+
subRowStates: { plotSelections, selections, stars },
9197
toggleRowSelection,
9298
toggleStarred
9399
}) => {
@@ -104,6 +110,40 @@ export const CellRowActions: React.FC<CellRowActionsProps> = ({
104110
checked={isRowSelected}
105111
/>
106112
</CellRowAction>
113+
{isQueued(status) ? (
114+
<div className={styles.rowActions}>
115+
<span className={styles.queued}>
116+
<Clock />
117+
</span>
118+
</div>
119+
) : (
120+
<CellRowAction
121+
showSubRowStates={showSubRowStates}
122+
subRowsAffected={plotSelections}
123+
testId="row-action-plot"
124+
tooltipContent={
125+
<ClickableTooltipContent
126+
clickableText="Open the plots view"
127+
helperText={getTooltipContent(!!plotColor, 'plot')}
128+
onClick={openPlotsWebview}
129+
/>
130+
}
131+
onClick={toggleExperiment}
132+
>
133+
<Icon
134+
className={styles.plotBox}
135+
style={
136+
plotColor
137+
? {
138+
backgroundColor: plotColor,
139+
fill: 'var(--vscode-editor-foreground)'
140+
}
141+
: {}
142+
}
143+
icon={GraphScatter}
144+
/>
145+
</CellRowAction>
146+
)}
107147
<CellRowAction
108148
showSubRowStates={showSubRowStates}
109149
subRowsAffected={stars}
@@ -127,29 +167,6 @@ export const CellRowActions: React.FC<CellRowActionsProps> = ({
127167
{starred ? <StarFull /> : <StarEmpty />}
128168
</div>
129169
</CellRowAction>
130-
{isQueued(status) ? (
131-
<div className={styles.rowActions}>
132-
<span className={styles.queued}>
133-
<Clock />
134-
</span>
135-
</div>
136-
) : (
137-
<CellRowAction
138-
showSubRowStates={showSubRowStates}
139-
subRowsAffected={plotSelections}
140-
testId="row-action-plot"
141-
tooltipContent={
142-
<ClickableTooltipContent
143-
clickableText="Open the plots view"
144-
helperText={getTooltipContent(!!bulletColor, 'plot')}
145-
onClick={openPlotsWebview}
146-
/>
147-
}
148-
onClick={toggleExperiment}
149-
>
150-
<span className={styles.bullet} style={{ color: bulletColor }} />
151-
</CellRowAction>
152-
)}
153170
</>
154171
)
155172
}

webview/src/experiments/components/table/body/Row.tsx

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import cx from 'classnames'
22
import React, { useCallback, useContext, useMemo } from 'react'
33
import { useSelector } from 'react-redux'
44
import { EXPERIMENT_WORKSPACE_ID } from 'dvc/src/cli/dvc/contract'
5-
import { isQueued, isRunning } from 'dvc/src/experiments/webview/contract'
65
import { FirstCell, CellWrapper } from './Cell'
76
import { RowContextMenu } from './RowContextMenu'
87
import styles from '../styles.module.scss'
@@ -24,9 +23,8 @@ export const RowContent: React.FC<
2423
const changes = useSelector(
2524
(state: ExperimentsState) => state.tableData.changes
2625
)
27-
const { getVisibleCells, original, index, getIsExpanded, subRows } = row
28-
const { branch, displayColor, error, starred, id, status, selected } =
29-
original
26+
const { getVisibleCells, original, getIsExpanded, subRows } = row
27+
const { branch, displayColor, error, starred, id } = original
3028
const [firstCell, ...cells] = getVisibleCells()
3129
const isWorkspace = id === EXPERIMENT_WORKSPACE_ID
3230
const changesIfWorkspace = isWorkspace ? changes : undefined
@@ -68,11 +66,6 @@ export const RowContent: React.FC<
6866
}
6967
}, [subRows, selectedRows])
7068

71-
const running = isRunning(status)
72-
const queued = isQueued(status)
73-
const unselected = selected === false
74-
const isOdd = index % 2 !== 0 && !isRowSelected
75-
7669
return (
7770
<ContextMenu content={<RowContextMenu row={row} />}>
7871
<tr
@@ -82,14 +75,6 @@ export const RowContent: React.FC<
8275
styles.bodyRow,
8376
styles.row,
8477
{
85-
[styles.runningExperiment]: running,
86-
[styles.queuedExperiment]: queued,
87-
[styles.unselectedExperiment]: !running && !queued && unselected,
88-
[styles.normalExperiment]: !running && !queued && !unselected,
89-
[styles.oddRow]: isOdd,
90-
[styles.evenRow]: !isOdd,
91-
[styles.workspaceRow]: isWorkspace,
92-
[styles.normalRow]: !isWorkspace,
9378
[styles.rowSelected]: isRowSelected
9479
}
9580
)}
@@ -100,7 +85,7 @@ export const RowContent: React.FC<
10085
<FirstCell
10186
cell={firstCell}
10287
changesIfWorkspace={!!changesIfWorkspace?.length}
103-
bulletColor={displayColor}
88+
plotColor={displayColor}
10489
starred={starred}
10590
isRowSelected={isRowSelected}
10691
showSubRowStates={!getIsExpanded() && !isWorkspace}

webview/src/experiments/components/table/styles.module.scss

Lines changed: 19 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ $row-border: 1px solid $border-color;
1010
$edge-padding: 0.8rem;
1111
$cell-padding: 0.5rem;
1212
$workspace-row-edge-margin: $edge-padding - $cell-padding;
13-
$bullet-size: calc(var(--design-unit) * 4px);
1413
$badge-size: 0.85rem;
1514

1615
// Extendable Silent Rules
@@ -451,6 +450,10 @@ $badge-size: 0.85rem;
451450
visibility: hidden;
452451
}
453452

453+
.plotBox {
454+
visibility: visible;
455+
}
456+
454457
.timestampInnerCell {
455458
height: 42px;
456459
}
@@ -576,7 +579,7 @@ $badge-size: 0.85rem;
576579
height: 100%;
577580

578581
&:first-child {
579-
margin-right: 20px;
582+
margin-right: 4px;
580583
}
581584

582585
.nestedRow & {
@@ -626,57 +629,23 @@ $badge-size: 0.85rem;
626629
font-size: 0.65rem;
627630
}
628631

629-
.bullet {
630-
visibility: visible;
631-
align-items: center;
632-
background: $checkbox-background;
633-
border-radius: $bullet-size;
634-
border: calc(var(--border-width) * 1px) solid $checkbox-border;
635-
color: $icon-color;
632+
.plotBox {
633+
background-color: $checkbox-background;
634+
border-radius: $checkbox-border-radius;
635+
border: $checkbox-border-width solid $checkbox-border;
636636
cursor: pointer;
637637
display: flex;
638-
height: $bullet-size;
639-
justify-content: center;
640-
outline: none;
641-
padding: 0;
642-
position: relative;
643-
width: $bullet-size;
644-
645-
&::before {
646-
display: inline-block;
647-
position: relative;
648-
content: '';
649-
border-radius: 99px;
650-
width: 6px;
651-
height: 6px;
652-
z-index: 2;
653-
654-
.normalExperiment & {
655-
line-height: 0;
656-
background: currentcolor;
657-
border-radius: 100%;
658-
}
659-
660-
.unselectedExperiment & {
661-
width: 4px;
662-
height: 4px;
663-
vertical-align: middle;
664-
border: 1px solid $icon-color;
665-
background-color: $checkbox-background;
666-
}
638+
height: $checkbox-size;
639+
width: $checkbox-size;
640+
padding: 2px;
641+
}
667642

668-
.runningExperiment & {
669-
width: 4px;
670-
height: 4px;
671-
vertical-align: middle;
672-
border: 1.5px solid $checkbox-background;
673-
border-radius: 100%;
674-
border-right: 1.5px solid currentcolor;
675-
border-top: 1.5px solid currentcolor;
676-
animation: spin 1s cubic-bezier(0.53, 0.21, 0.29, 0.67) infinite;
677-
background-color: $checkbox-background;
678-
}
679-
}
643+
.running {
644+
display: inline-flex;
645+
height: 12px;
646+
width: 12px;
647+
margin-right: 8px;
648+
margin-left: -20px;
680649
}
681650

682651
.queued {

webview/src/plots/components/ribbon/RibbonBlock.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { Revision } from 'dvc/src/plots/webview/contract'
22
import React from 'react'
3+
import cx from 'classnames'
34
import { VSCodeProgressRing } from '@vscode/webview-ui-toolkit/react'
45
import styles from './styles.module.scss'
56
import { RibbonBlockTooltip } from './RibbonBlockTooltip'
@@ -19,7 +20,9 @@ const RevisionIcon: React.FC<{ fetched: boolean; errors?: string[] }> = ({
1920
}) => (
2021
<div className={styles.iconPlaceholder}>
2122
{fetched && errors && '!'}
22-
{!fetched && <VSCodeProgressRing className={styles.fetching} />}
23+
{!fetched && (
24+
<VSCodeProgressRing className={cx(styles.fetching, 'chromatic-ignore')} />
25+
)}
2326
</div>
2427
)
2528

webview/src/shared/components/Icon.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ export type IconValue = (props: SVGProps<SVGSVGElement>) => JSX.Element
44
interface IconProps {
55
icon: IconValue
66
className?: string
7+
style?: { [key: string]: string | undefined }
78
width?: number
89
height?: number
910
}

webview/src/shared/variables.scss

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ $selected-icon-color: var(
4242
$row-action-star-checked: var(--vscode-editorLightBulb-foreground);
4343
$checkbox-background: var(--checkbox-background);
4444
$checkbox-border: var(--checkbox-border);
45+
$checkbox-border-radius: calc(var(--checkbox-corner-radius) * 1px);
46+
$checkbox-border-width: calc(var(--border-width) * 1px);
47+
$checkbox-size: calc(var(--design-unit) * 4px + 2px);
4548
$indicator-badge-background: var(--vscode-activityBarBadge-background);
4649
$indicator-badge-foreground: var(--vscode-activityBarBadge-foreground);
4750
$disabled-opacity: var(--disabled-opacity);

0 commit comments

Comments
 (0)