Skip to content

Commit f031aa4

Browse files
authored
DataGrid: Fix header borders being cut off above the vertical scrollbar (T1306973) (DevExpress#34373)
Co-authored-by: Alyar <>
1 parent 7011751 commit f031aa4

10 files changed

Lines changed: 163 additions & 10 deletions

File tree

17.1 KB
Loading
17.1 KB
Loading

e2e/testcafe-devextreme/tests/dataGrid/common/scrolling.ts

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { createScreenshotsComparer } from 'devextreme-screenshot-comparer';
33
import DataGrid from 'devextreme-testcafe-models/dataGrid';
44
import { ClassNames } from 'devextreme-testcafe-models/dataGrid/classNames';
55
import type { DataGridScrollMode } from 'devextreme/ui/data_grid';
6-
import { insertStylesheetRulesToPage } from '../../../helpers/domUtils';
6+
import { insertStylesheetRulesToPage, removeStylesheetRulesFromPage } from '../../../helpers/domUtils';
77
import url from '../../../helpers/getPageUrl';
88
import { createWidget } from '../../../helpers/createWidget';
99
import { salesApiMock } from './apiMocks/salesApiMock';
@@ -363,6 +363,69 @@ test('Scroll position after grouping when RTL (T388508)', async (t) => {
363363
}],
364364
}));
365365

366+
[false, true].forEach((rtlEnabled) => {
367+
test(`Headers should have a border before the scrollbar gutter when the vertical scrollbar occupies space (rtlEnabled = ${rtlEnabled}) (T1306973)`, async (t) => {
368+
// arrange, act
369+
const { takeScreenshot, compareResults } = createScreenshotsComparer(t);
370+
const dataGrid = new DataGrid('#container');
371+
372+
await t
373+
.expect(dataGrid.isReady())
374+
.ok();
375+
376+
const headersElement = dataGrid.getHeaders().element;
377+
const paddingProperty = rtlEnabled ? 'padding-left' : 'padding-right';
378+
const padding = parseFloat(await headersElement.getStyleProperty(paddingProperty));
379+
380+
// assert
381+
await t
382+
.expect(headersElement.hasClass('dx-datagrid-scroller-spacing'))
383+
.ok()
384+
.expect(padding)
385+
.eql(14);
386+
387+
await testScreenshot(
388+
t,
389+
takeScreenshot,
390+
`grid-headers-scroller-spacing-border${rtlEnabled ? '-rtl' : ''}.png`,
391+
{ element: '#container' },
392+
);
393+
394+
await t
395+
.expect(compareResults.isValid())
396+
.ok(compareResults.errorMessages());
397+
}).before(async () => {
398+
await insertStylesheetRulesToPage(`
399+
::-webkit-scrollbar { -webkit-appearance: none; width: 14px; height: 14px; }
400+
::-webkit-scrollbar-thumb { background-color: rgba(0, 0, 0, .5); border-radius: 7px; }
401+
::-webkit-scrollbar-track { background-color: #fafafa; border-${rtlEnabled ? 'right' : 'left'}: 1px solid #e0e0e0; }
402+
`);
403+
404+
return createWidget('dxDataGrid', {
405+
rtlEnabled,
406+
width: 700,
407+
height: 300,
408+
showBorders: true,
409+
dataSource: getData(30, 5),
410+
columns: ['field_0', 'field_1', 'field_2', 'field_3', 'field_4'],
411+
filterRow: {
412+
visible: true,
413+
},
414+
summary: {
415+
totalItems: [{
416+
column: 'field_0',
417+
summaryType: 'count',
418+
}],
419+
},
420+
scrolling: {
421+
useNative: true,
422+
},
423+
});
424+
}).after(async () => {
425+
await removeStylesheetRulesFromPage();
426+
});
427+
});
428+
366429
test('Header container should have padding-right after expanding the master row with a detail grid when using native scrolling (T1004507)', async (t) => {
367430
const dataGrid = new DataGrid('#container');
368431
const { takeScreenshot, compareResults } = createScreenshotsComparer(t);

packages/devextreme-scss/scss/widgets/fluent/gridBase/_index.scss

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -628,6 +628,12 @@ $fluent-grid-base-group-panel-message-line-height: $fluent-button-text-line-heig
628628
}
629629
}
630630

631+
.dx-#{$widget-name}-headers.dx-#{$widget-name}-scroller-spacing {
632+
> .dx-#{$widget-name}-scroll-container:not(.dx-#{$widget-name}-content-fixed) {
633+
box-shadow: 1px 0 0 $datagrid-border-color;
634+
}
635+
}
636+
631637
.dx-#{$widget-name}-filter-row {
632638
background-color: $datagrid-filter-row-background-color;
633639

@@ -976,6 +982,12 @@ $fluent-grid-base-group-panel-message-line-height: $fluent-button-text-line-heig
976982
}
977983
}
978984

985+
.dx-#{$widget-name}-headers.dx-#{$widget-name}-scroller-spacing {
986+
> .dx-#{$widget-name}-scroll-container:not(.dx-#{$widget-name}-content-fixed) {
987+
box-shadow: -1px 0 0 $datagrid-border-color;
988+
}
989+
}
990+
979991
.dx-#{$widget-name}-rowsview {
980992
&.dx-scrollable-scrollbars-alwaysvisible.dx-scrollable-both .dx-scrollable-wrapper .dx-scrollable-container .dx-scrollable-content {
981993
padding-left: 0;

packages/devextreme-scss/scss/widgets/generic/gridBase/_index.scss

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,12 @@ $generic-grid-base-cell-input-height: math.round($generic-base-line-height * $ge
442442
}
443443
}
444444

445+
.dx-#{$widget-name}-headers.dx-#{$widget-name}-scroller-spacing {
446+
> .dx-#{$widget-name}-scroll-container:not(.dx-#{$widget-name}-content-fixed) {
447+
box-shadow: 1px 0 0 $datagrid-border-color;
448+
}
449+
}
450+
445451
.dx-#{$widget-name}-filter-row {
446452
.dx-menu {
447453
.dx-overlay-content {
@@ -837,6 +843,12 @@ $generic-grid-base-cell-input-height: math.round($generic-base-line-height * $ge
837843
}
838844
}
839845

846+
.dx-#{$widget-name}-headers.dx-#{$widget-name}-scroller-spacing {
847+
> .dx-#{$widget-name}-scroll-container:not(.dx-#{$widget-name}-content-fixed) {
848+
box-shadow: -1px 0 0 $datagrid-border-color;
849+
}
850+
}
851+
840852
.dx-#{$widget-name}-filter-row {
841853
.dx-menu {
842854
.dx-menu-item-has-submenu.dx-menu-item-has-icon {

packages/devextreme-scss/scss/widgets/material/gridBase/_index.scss

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -602,6 +602,12 @@ $material-grid-base-group-panel-message-line-height: $material-button-text-line-
602602

603603
}
604604

605+
.dx-#{$widget-name}-headers.dx-#{$widget-name}-scroller-spacing {
606+
> .dx-#{$widget-name}-scroll-container:not(.dx-#{$widget-name}-content-fixed) {
607+
box-shadow: 1px 0 0 $datagrid-border-color;
608+
}
609+
}
610+
605611
.dx-#{$widget-name}-filter-row {
606612
background-color: $datagrid-filter-row-background-color;
607613

@@ -952,6 +958,12 @@ $material-grid-base-group-panel-message-line-height: $material-button-text-line-
952958
}
953959
}
954960

961+
.dx-#{$widget-name}-headers.dx-#{$widget-name}-scroller-spacing {
962+
> .dx-#{$widget-name}-scroll-container:not(.dx-#{$widget-name}-content-fixed) {
963+
box-shadow: -1px 0 0 $datagrid-border-color;
964+
}
965+
}
966+
955967
.dx-#{$widget-name}-rowsview {
956968
&.dx-scrollable-scrollbars-alwaysvisible.dx-scrollable-both .dx-scrollable-wrapper .dx-scrollable-container .dx-scrollable-content {
957969
padding-left: 0;

packages/devextreme/js/__internal/grids/grid_core/__tests__/__mock__/helpers/utils.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@ import $ from '@js/core/renderer';
55
import type { Properties as DataGridProperties } from '@js/ui/data_grid';
66
import DataGrid from '@js/ui/data_grid';
77
import { DataGridModel } from '@ts/grids/data_grid/__tests__/__mock__/model/data_grid';
8-
import type { Controllers } from '@ts/grids/grid_core/m_types';
8+
import type { Controllers, Views } from '@ts/grids/grid_core/m_types';
99

1010
export interface DataGridInstance extends DataGrid {
1111
getController: <T extends keyof Controllers>(name: T) => Controllers[T];
12+
getView: <T extends keyof Views>(name: T) => Views[T];
1213
}
1314

1415
export const SELECTORS = {
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import {
2+
afterEach, beforeEach, describe, expect, it,
3+
} from '@jest/globals';
4+
5+
import {
6+
afterTest, beforeTest, createDataGrid,
7+
} from '../../__tests__/__mock__/helpers/utils';
8+
9+
const SCROLLER_SPACING_CLASS = 'dx-datagrid-scroller-spacing';
10+
11+
describe('ColumnsView scroller spacing (T1306973)', () => {
12+
beforeEach(() => {
13+
beforeTest();
14+
});
15+
16+
afterEach(() => {
17+
afterTest();
18+
});
19+
20+
it('should toggle the scroller spacing class on the headers view', async () => {
21+
const { instance } = await createDataGrid({
22+
dataSource: [{ id: 1, a: 'a', b: 'b' }],
23+
columns: ['a', 'b'],
24+
});
25+
const columnHeadersView = instance.getView('columnHeadersView');
26+
27+
columnHeadersView.setScrollerSpacing(15);
28+
29+
expect(columnHeadersView.element().hasClass(SCROLLER_SPACING_CLASS)).toBe(true);
30+
expect(columnHeadersView.element().css('paddingInlineEnd')).toBe('15px');
31+
32+
columnHeadersView.setScrollerSpacing(0);
33+
34+
expect(columnHeadersView.element().hasClass(SCROLLER_SPACING_CLASS)).toBe(false);
35+
});
36+
37+
it('should toggle the scroller spacing class on the footer view', async () => {
38+
const { instance } = await createDataGrid({
39+
dataSource: [{ id: 1, a: 'a', b: 'b' }],
40+
columns: ['a', 'b'],
41+
summary: {
42+
totalItems: [{ column: 'a', summaryType: 'count' }],
43+
},
44+
});
45+
const footerView = instance.getView('footerView');
46+
47+
footerView.setScrollerSpacing(15);
48+
49+
expect(footerView.element().hasClass(SCROLLER_SPACING_CLASS)).toBe(true);
50+
51+
footerView.setScrollerSpacing(0);
52+
53+
expect(footerView.element().hasClass(SCROLLER_SPACING_CLASS)).toBe(false);
54+
});
55+
});
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
export const CLASSES = {
22
firstCell: 'first-cell',
3+
scrollerSpacing: 'scroller-spacing',
34
};

packages/devextreme/js/__internal/grids/grid_core/views/m_columns_view.ts

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1486,15 +1486,12 @@ export class ColumnsView extends ColumnStateMixin(modules.View) {
14861486
/**
14871487
* @extended: column_fixing
14881488
*/
1489-
public setScrollerSpacing(width) {
1490-
const that = this;
1491-
const $element = that.element();
1492-
const rtlEnabled = that.option('rtlEnabled');
1489+
public setScrollerSpacing(width: number): void {
1490+
const $element = this.element();
14931491

1494-
$element && $element.css({
1495-
paddingLeft: rtlEnabled ? width : '',
1496-
paddingRight: !rtlEnabled ? width : '',
1497-
});
1492+
$element
1493+
?.toggleClass(this.addWidgetPrefix(CLASSES.scrollerSpacing), !!width)
1494+
.css('paddingInlineEnd', width ? `${width}px` : '');
14981495
}
14991496

15001497
protected isScrollbarVisible(isHorizontal) {

0 commit comments

Comments
 (0)