Skip to content

Commit e9d0009

Browse files
authored
[Runs table] Moves expand button to layout container and fixes sidebar scroll (#6837)
## Motivation for features / changes - Moving the expand button out of the runs table is required to make it compatible with the upcoming sticky add column b/332788091 - When the table is both vertically long and horizontally wide, it's very difficult to scroll horizontally: users must scroll all the way to the bottom of the table in order to access the horizontal scroll bar. b/332720882 ## Technical description of changes - Moves the "expand button" from inside the runs data table to the LayoutContainer (in the side bar). - Moves the "overflow" css property from the runs table to RunsSelectorComponent (the runs table wrapper) - Makes the runs table header sticky. This was already set, but wasn't being applied due to a missing "position: relative" parent. ## Screenshots of UI changes (or N/A) sticky header: ![image](https://github.com/tensorflow/tensorboard/assets/736199/f2569648-6395-4411-9302-f626b6bd5e9f) expand table button: ![image](https://github.com/tensorflow/tensorboard/assets/736199/35b2e624-f015-41dc-9114-0cab63b70eef)
1 parent 4023658 commit e9d0009

File tree

8 files changed

+95
-93
lines changed

8 files changed

+95
-93
lines changed

tensorboard/webapp/core/views/layout_container.scss

+57-15
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,34 @@ limitations under the License.
2424

2525
.sidebar {
2626
max-width: 80vw;
27+
position: relative;
2728
}
2829

2930
.resizer,
30-
.expand {
31+
.expand-collapsed-sidebar {
3132
@include tb-theme-foreground-prop(border-color, border);
3233
box-sizing: border-box;
3334
flex: 0 0;
3435
justify-self: stretch;
3536
}
3637

37-
.expand {
38+
.expand-collapsed-sidebar {
3839
width: 20px;
40+
align-items: center;
41+
background: transparent;
42+
border-style: solid;
43+
border-width: 0 1px 0 0;
44+
color: inherit;
45+
contain: content;
46+
cursor: pointer;
47+
display: flex;
48+
justify-self: stretch;
49+
padding: 0;
50+
51+
mat-icon {
52+
transform: rotate(-90deg);
53+
transform-origin: center;
54+
}
3955
}
4056

4157
.resizer {
@@ -63,20 +79,46 @@ limitations under the License.
6379
}
6480
}
6581

66-
.expand {
67-
align-items: center;
68-
background: transparent;
69-
border-style: solid;
70-
border-width: 0 1px 0 0;
71-
color: inherit;
72-
contain: content;
73-
cursor: pointer;
82+
.full-screen-toggle {
83+
opacity: 0;
84+
position: absolute;
85+
height: 100%;
86+
// Ensure the button is on the right side then add 2px for the drag target.
87+
left: calc(100% + 2px);
88+
top: 0;
89+
z-index: 1;
7490
display: flex;
75-
justify-self: stretch;
76-
padding: 0;
91+
align-items: center;
7792

78-
mat-icon {
79-
transform: rotate(-90deg);
80-
transform-origin: center;
93+
&:hover {
94+
opacity: 0.8;
95+
}
96+
97+
&.full-screen {
98+
left: unset;
99+
right: 0;
100+
}
101+
102+
.full-screen-btn {
103+
$_arrow_size: 16px;
104+
$_arrow_button_size: calc($_arrow_size + 4px);
105+
106+
background-color: gray;
107+
padding: 0;
108+
min-width: $_arrow_button_size;
109+
width: $_arrow_button_size;
110+
111+
&.expand {
112+
border-radius: 0 $_arrow_button_size $_arrow_button_size 0;
113+
}
114+
115+
&.collapse {
116+
border-radius: $_arrow_button_size 0 0 $_arrow_button_size;
117+
}
118+
119+
.expand-collapse-icon {
120+
font-size: $_arrow_size;
121+
margin-right: 0; // Removes default
122+
}
81123
}
82124
}

tensorboard/webapp/core/views/layout_container.ts

+26-2
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import {Store} from '@ngrx/store';
2222
import {fromEvent, Observable, Subject} from 'rxjs';
2323
import {combineLatestWith, filter, map, takeUntil} from 'rxjs/operators';
2424
import {MouseEventButtons} from '../../util/dom';
25-
import {sideBarWidthChanged} from '../actions';
25+
import {runsTableFullScreenToggled, sideBarWidthChanged} from '../actions';
2626
import {State} from '../state';
2727
import {
2828
getRunsTableFullScreen,
@@ -34,7 +34,7 @@ import {
3434
template: `
3535
<button
3636
*ngIf="(width$ | async) === 0"
37-
class="expand"
37+
class="expand-collapsed-sidebar"
3838
(click)="expandSidebar()"
3939
>
4040
<mat-icon svgIcon="expand_more_24px"></mat-icon>
@@ -47,6 +47,26 @@ import {
4747
[style.maxWidth.%]="(runsTableFullScreen$ | async) ? 100 : ''"
4848
>
4949
<ng-content select="[sidebar]"></ng-content>
50+
<div
51+
class="full-screen-toggle"
52+
[ngClass]="{'full-screen': (runsTableFullScreen$ | async)}"
53+
>
54+
<button
55+
mat-button
56+
class="full-screen-btn"
57+
[ngClass]="(runsTableFullScreen$ | async) ? 'collapse' : 'expand'"
58+
(click)="toggleFullScreen()"
59+
>
60+
<mat-icon
61+
class="expand-collapse-icon"
62+
[svgIcon]="
63+
(runsTableFullScreen$ | async)
64+
? 'arrow_back_24px'
65+
: 'arrow_forward_24px'
66+
"
67+
></mat-icon>
68+
</button>
69+
</div>
5070
</nav>
5171
<div
5272
*ngIf="(width$ | async) > 0"
@@ -125,4 +145,8 @@ export class LayoutContainer implements OnDestroy {
125145
})
126146
);
127147
}
148+
149+
toggleFullScreen() {
150+
this.store.dispatch(runsTableFullScreenToggled());
151+
}
128152
}

tensorboard/webapp/core/views/layout_test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ describe('layout test', () => {
6767
let dispatchedActions: Action[] = [];
6868

6969
const byCss = {
70-
EXPANDER: By.css('.expand'),
70+
EXPANDER: By.css('.expand-collapsed-sidebar'),
7171
RESIZER: By.css('.resizer'),
7272
SIDEBAR_CONTAINER: By.css('nav'),
7373
LAYOUT: By.directive(LayoutContainer),

tensorboard/webapp/runs/views/runs_selector/runs_selector_component.ts

+7
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,13 @@ import {RunsTableColumn} from '../runs_table/types';
2525
`,
2626
styles: [
2727
`
28+
:host {
29+
display: block;
30+
height: 100%;
31+
width: 100%;
32+
overflow: auto;
33+
}
34+
2835
runs-table {
2936
height: 100%;
3037
}

tensorboard/webapp/runs/views/runs_table/runs_data_table.ng.html

-13
Original file line numberDiff line numberDiff line change
@@ -106,16 +106,3 @@
106106
</ng-container>
107107
</tb-data-table>
108108
</div>
109-
<div class="full-screen-toggle" [ngClass]="{'full-screen': isFullScreen}">
110-
<button
111-
mat-button
112-
class="full-screen-btn"
113-
[ngClass]="isFullScreen ? 'collapse' : 'expand'"
114-
(click)="toggleFullScreen.emit()"
115-
>
116-
<mat-icon
117-
class="expand-collapse-icon"
118-
[svgIcon]="isFullScreen ? 'arrow_back_24px' : 'arrow_forward_24px'"
119-
></mat-icon>
120-
</button>
121-
</div>

tensorboard/webapp/runs/views/runs_table/runs_data_table.scss

+4-51
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,13 @@ limitations under the License.
1515
@use '@angular/material' as mat;
1616
@import 'tensorboard/webapp/theme/tb_theme';
1717
$_circle-size: 20px;
18-
$_arrow_size: 16px;
1918

2019
:host {
21-
width: 100%;
22-
}
20+
min-width: 100%;
2321

24-
:host {
25-
overflow-y: auto;
26-
width: 100%;
22+
& ::ng-deep tb-data-table .data-table {
23+
@include tb-theme-foreground-prop(border-top, border, 1px solid);
24+
}
2725
}
2826

2927
.color-container {
@@ -72,49 +70,7 @@ tb-data-table-header-cell:last-of-type {
7270
width: 40px;
7371
}
7472

75-
.full-screen-toggle {
76-
opacity: 0;
77-
position: absolute;
78-
height: 100%;
79-
// Ensure the button is on the right side then add 2px for the drag target.
80-
left: calc(100% + 2px);
81-
top: 0;
82-
z-index: 1;
83-
display: flex;
84-
align-items: center;
85-
86-
&:hover {
87-
opacity: 0.8;
88-
}
89-
90-
&.full-screen {
91-
left: unset;
92-
right: 0;
93-
}
94-
95-
.full-screen-btn {
96-
background-color: gray;
97-
padding: 0;
98-
min-width: $_arrow_size;
99-
width: $_arrow_size;
100-
101-
&.expand {
102-
border-radius: 0 $_arrow_size $_arrow_size 0;
103-
}
104-
105-
&.collapse {
106-
border-radius: $_arrow_size 0 0 $_arrow_size;
107-
}
108-
109-
.expand-collapse-icon {
110-
font-size: $_arrow_size;
111-
width: $_arrow_size;
112-
}
113-
}
114-
}
115-
11673
.filter-row {
117-
@include tb-theme-foreground-prop(border-bottom, border, 1px solid);
11874
display: flex;
11975
align-items: center;
12076
height: 48px;
@@ -125,6 +81,3 @@ tb-data-table-header-cell:last-of-type {
12581
flex-grow: 1;
12682
}
12783
}
128-
.table-container {
129-
overflow-x: auto;
130-
}

tensorboard/webapp/runs/views/runs_table/runs_data_table.ts

-2
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ export class RunsDataTable {
4343
@Input() sortingInfo!: SortingInfo;
4444
@Input() experimentIds!: string[];
4545
@Input() regexFilter!: string;
46-
@Input() isFullScreen!: boolean;
4746
@Input() selectableColumns!: ColumnHeader[];
4847
@Input() numColumnsLoaded!: number;
4948
@Input() numColumnsToLoad!: number;
@@ -57,7 +56,6 @@ export class RunsDataTable {
5756
@Output() onSelectionToggle = new EventEmitter<string>();
5857
@Output() onAllSelectionToggle = new EventEmitter<string[]>();
5958
@Output() onRegexFilterChange = new EventEmitter<string>();
60-
@Output() toggleFullScreen = new EventEmitter();
6159
@Output() onRunColorChange = new EventEmitter<{
6260
runId: string;
6361
newColor: string;

tensorboard/webapp/runs/views/runs_table/runs_table_container.ts

-9
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ import {
4545
getRuns,
4646
getRunSelectorRegexFilter,
4747
getRunsLoadState,
48-
getRunsTableFullScreen,
4948
getRunsTableSortingInfo,
5049
getGroupedRunsTableHeaders,
5150
} from '../../../selectors';
@@ -73,7 +72,6 @@ import {
7372
getFilteredRenderableRuns,
7473
getSelectableColumns,
7574
} from '../../../metrics/views/main_view/common_selectors';
76-
import {runsTableFullScreenToggled} from '../../../core/actions';
7775
import {sortTableDataItems} from './sorting_utils';
7876

7977
const getRunsLoading = createSelector<
@@ -102,7 +100,6 @@ const getRunsLoading = createSelector<
102100
[sortingInfo]="sortingInfo$ | async"
103101
[experimentIds]="experimentIds"
104102
[regexFilter]="regexFilter$ | async"
105-
[isFullScreen]="runsTableFullScreen$ | async"
106103
[loading]="loading$ | async"
107104
(sortDataBy)="sortDataBy($event)"
108105
(orderColumns)="orderColumns($event)"
@@ -111,7 +108,6 @@ const getRunsLoading = createSelector<
111108
(onRunColorChange)="onRunColorChange($event)"
112109
(onRegexFilterChange)="onRegexFilterChange($event)"
113110
(onSelectionDblClick)="onRunSelectionDblClick($event)"
114-
(toggleFullScreen)="toggleFullScreen()"
115111
(addColumn)="addColumn($event)"
116112
(removeColumn)="removeColumn($event)"
117113
(addFilter)="addHparamFilter($event)"
@@ -147,7 +143,6 @@ export class RunsTableContainer implements OnInit, OnDestroy {
147143

148144
regexFilter$ = this.store.select(getRunSelectorRegexFilter);
149145
runsColumns$ = this.store.select(getGroupedRunsTableHeaders);
150-
runsTableFullScreen$ = this.store.select(getRunsTableFullScreen);
151146
selectableColumns$ = this.store.select(getSelectableColumns);
152147
numColumnsLoaded$ = this.store.select(
153148
hparamsSelectors.getNumDashboardHparamsLoaded
@@ -328,10 +323,6 @@ export class RunsTableContainer implements OnInit, OnDestroy {
328323
this.store.dispatch(runColorChanged({runId, newColor}));
329324
}
330325

331-
toggleFullScreen() {
332-
this.store.dispatch(runsTableFullScreenToggled());
333-
}
334-
335326
addColumn({column, nextTo, side}: AddColumnEvent) {
336327
this.store.dispatch(
337328
hparamsActions.dashboardHparamColumnAdded({

0 commit comments

Comments
 (0)