Skip to content

Commit c8fe01b

Browse files
committed
feat(grid): display margin shadow if scrollable
1 parent bf76a2f commit c8fe01b

File tree

6 files changed

+52
-5
lines changed

6 files changed

+52
-5
lines changed

projects/angular/components/ui-grid/src/_ui-grid-variables.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ $ui-grid-header-pressed-color: var(--color-data-grid-pressed, #EAECED);
66
$header-background-color: var(--color-background-secondary, #f4f5f7);
77
$grid-actions-box-shadow: var(--color-background, #ffffff);
88
$highlighted-entity-color: var(--color-primary, #0067df);
9+
$scroll-margin-shadow-color: var(--color-background-inverse, #182027);

projects/angular/components/ui-grid/src/_ui-grid.theme.scss

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,18 @@ $ui-grid-opacity-transition: opacity $ui-grid-default-transition;
215215
background-color: $ui-grid-row-hover-color;
216216
}
217217
}
218+
219+
.grid-margin-shadow {
220+
position: sticky;
221+
right: 0;
222+
height: 100%;
223+
224+
@if $is-dark {
225+
box-shadow: -7px 20px 20px 4px #000000;
226+
} @else {
227+
box-shadow: -3px 5px 20px 1.6px $scroll-margin-shadow-color;
228+
}
229+
}
218230
}
219231

220232
.ui-grid-sort-icon {

projects/angular/components/ui-grid/src/ui-grid.component.html

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,7 @@
283283
class="ui-grid-header-cell ui-grid-scroll-size-compensation-cell ui-grid-feature-cell">
284284
</div>
285285
<div *ngIf="refreshable"
286+
[class.refresh-shadow]="shouldDisplayContainerShadow$ | async"
286287
class="ui-grid-header-cell ui-grid-refresh-cell ui-grid-feature-cell"
287288
role="columnheader">
288289
<button [matTooltip]="intl.refreshTooltip"
@@ -565,9 +566,13 @@
565566
class="ui-grid-cell ui-grid-refresh-cell ui-grid-feature-cell">
566567
</div>
567568

569+
<div *ngIf="!actions && (shouldDisplayContainerShadow$ | async)"
570+
class="grid-margin-shadow ui-grid-feature-cell"></div>
571+
568572
<div *ngIf="!isProjected &&
569573
!!actions"
570574
[class.ui-grid-sticky-element]="isScrollable"
575+
[class.grid-margin-shadow]="shouldDisplayContainerShadow$ | async"
571576
role="gridcell"
572577
class="ui-grid-cell ui-grid-action-cell ui-grid-feature-cell">
573578
<div [class.sticky-grid-action-cell-container]="isScrollable"

projects/angular/components/ui-grid/src/ui-grid.component.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -693,6 +693,10 @@ ui-grid {
693693
&.ui-grid-refresh-cell {
694694
position: sticky;
695695
right: 0;
696+
697+
&.refresh-shadow {
698+
box-shadow: -16px 0px 16px -4px $ui-grid-row-hover-color;
699+
}
696700
}
697701

698702
&.ui-grid-action-cell {

projects/angular/components/ui-grid/src/ui-grid.component.spec.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4856,6 +4856,13 @@ describe('Component: UiGrid', () => {
48564856
expect(gridTable.nativeElement.style.minWidth).toBe(columnWidthSum + 'px');
48574857
}));
48584858

4859+
it('should display margin shadow when the grid has horizontal scroll', fakeAsync(() => {
4860+
const widths = [250, 1000, 330, 400, 100, 100]; // large enough too cause overflow
4861+
beforeConfig({ widths });
4862+
const tableMarginShadowDivs = fixture.debugElement.queryAll(By.css('.grid-margin-shadow'));
4863+
expect(tableMarginShadowDivs.length).toBe(widths.length);
4864+
}));
4865+
48594866
it('should increase the width of last column if default column width sum does not fill the table', fakeAsync(() => {
48604867
const widths = [50, 50, 0, 50, 50, 50];
48614868
const lastColumnIdx = 4; // refresh btn & 1 missing column
@@ -5028,13 +5035,13 @@ describe('Component: UiGrid', () => {
50285035
expect(+newMinWidth.replace('px', '')).toBeLessThan(+startingMinWidth.replace('px', ''));
50295036
}));
50305037

5031-
it(`should set overflow to visible if total width of columns does not exceed container width`, fakeAsync(() => {
5038+
it(`should set overflow to visible and hide margin shadow if total width of columns does not exceed container width`, fakeAsync(() => {
50325039
const gridTable = fixture.debugElement.query(By.css('.ui-grid-table'));
50335040
const options = fixture.debugElement
50345041
.queryAll(By.css('.ui-grid-toggle-panel .mat-mdc-option:not(.mdc-list-item--disabled)'));
50355042

50365043
expect(gridTable.styles.overflow).toEqual('visible');
5037-
5044+
expect(fixture.debugElement.queryAll(By.css('.grid-margin-shadow')).length).toBe(6);
50385045
options.forEach(o => {
50395046
const checkbox = o.query(By.css('.mat-pseudo-checkbox'));
50405047
checkbox.nativeElement.dispatchEvent(EventGenerator.click);
@@ -5044,6 +5051,7 @@ describe('Component: UiGrid', () => {
50445051
fixture.detectChanges();
50455052

50465053
expect(gridTable.styles.overflow).toEqual('hidden');
5054+
expect(fixture.debugElement.queryAll(By.css('.grid-margin-shadow')).length).toBe(0);
50475055
}));
50485056
});
50495057

projects/angular/components/ui-grid/src/ui-grid.component.ts

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import {
55
BehaviorSubject,
66
combineLatest,
77
defer,
8+
fromEvent,
9+
iif,
810
merge,
911
Observable,
1012
of,
@@ -25,6 +27,7 @@ import {
2527
take,
2628
takeUntil,
2729
tap,
30+
throttleTime,
2831
} from 'rxjs/operators';
2932

3033
import {
@@ -110,6 +113,7 @@ const EXCLUDED_ROW_SELECTION_ELEMENTS = ['a', 'button', 'input', 'textarea', 'se
110113
const REFRESH_WIDTH = 50;
111114
const DEFAULT_VIRTUAL_SCROLL_ITEM_SIZE = 48;
112115
const DEFAULT_VIRTUAL_SCROLL_HIGH_DENSITY_ITEM_SIZE = 32;
116+
const SCROLL_LIMIT_FOR_DISPLAYING_SHADOW = 10;
113117

114118
@Component({
115119
selector: 'ui-grid',
@@ -827,6 +831,20 @@ export class UiGridComponent<T extends IGridDataEntry>
827831
shareReplay(1),
828832
);
829833

834+
shouldDisplayContainerShadow$ = defer(() => merge(
835+
fromEvent(this._ref.nativeElement.querySelector('.ui-grid-table-container')!, 'scroll').pipe(
836+
throttleTime(50, undefined, { trailing: true }),
837+
map((event: any) => {
838+
const { scrollWidth, scrollLeft, clientWidth } = event.target;
839+
return Math.abs(scrollWidth - clientWidth - scrollLeft) >= SCROLL_LIMIT_FOR_DISPLAYING_SHADOW;
840+
}),
841+
),
842+
this.isOverflown$,
843+
)).pipe(
844+
distinctUntilChanged(),
845+
shareReplay(),
846+
);
847+
830848
areFilersCollapsed$: Observable<boolean>;
831849

832850
/**
@@ -862,10 +880,10 @@ export class UiGridComponent<T extends IGridDataEntry>
862880
shareReplay(1),
863881
);
864882

865-
isOverflown$ = this.minWidth$.pipe(
883+
isOverflown$ = iif(() => this.isScrollable, this.minWidth$.pipe(
866884
map(minWidth => this._isOverflown(minWidth)),
867885
distinctUntilChanged(),
868-
);
886+
), of(false));
869887

870888
tableOverflowStyle$ = this.isOverflown$.pipe(
871889
map(value => value ? 'visible' : 'hidden'),
@@ -1342,7 +1360,6 @@ export class UiGridComponent<T extends IGridDataEntry>
13421360
}, 0);
13431361

13441362
return widthsPxSum + this._otherActionsWidth;
1345-
13461363
}
13471364

13481365
private get _otherActionsWidth() {

0 commit comments

Comments
 (0)