diff --git a/CHANGELOG.md b/CHANGELOG.md index 822d34d73d9..c5e6df5c44e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,69 @@ All notable changes for each version of this project will be documented in this file. +## 22.0.0 + +### New Features + +- **Theming** + - Added derived themes for the Grid and related internal components. When a parent component theme is included, its internal controls now derive their tokens from the parent theme colors, keeping nested buttons, icons, inputs, dropdowns, checkboxes, scrollbars, chips, and other helper components visually aligned. + + - The derived themes are introduces for the following components: + - Grid + - Excel Filtering + - Grid Toolbar + - Paginator + - Column Actions + - Query Builder and Advanced Filtering Dialog + + - The derived themes are applied through the existing component theme mixins, so no additional mixin call is required. To style the whole `IgxGrid`, provide the `$background`, `$foreground`, and `$accent-color` properties to `grid-theme()` and include the generated theme with `tokens()`. The `$foreground` property is optional; when omitted, it is derived automatically as a contrast color for the background. Internal components inherit derived tokens from the parent component theme. + + You can also style each compound component inside the grid with its own theme by providing the same color properties. The generated tokens are scoped to that component and affect the nested controls inside it. + + ```scss + $grid-theme: grid-theme( + $schema: $schema, + $background: #ffffff, + $foreground: #1f2937, + $accent-color: #0061a8 + ); + + $excel-filtering-theme: excel-filtering-theme( + $schema: $schema, + $background: #ff2323, + $accent-color: #21fc9a + ); + + $query-builder-theme: query-builder-theme( + $schema: $schema, + $background: #f235ff, + $accent-color: #89a800 + ); + + $grid-toolbar-theme: grid-toolbar-theme( ... ); + + $paginator-theme: paginator-theme( ... ); + + $column-actions-theme: column-actions-theme( ... ); + + igx-grid { + @include tokens($grid-theme); + } + + igx-grid-excel-style-filtering, + .igx-excel-filter__secondary { + @include tokens($excel-filtering-theme); + } + + igx-advanced-filtering-dialog { + @include tokens($query-builder-theme); + } + + ... + ``` + + - Added a dedicated `excel-filtering-theme()` for styling the `Excel Style Filtering`. Use it instead of the excel-filtering color properties from `grid-theme()`. + ## 21.2.0 ### New Features diff --git a/package-lock.json b/package-lock.json index 8d0a6745ce1..c89bc4b4b8e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,7 +27,7 @@ "express": "^5.2.1", "fflate": "^0.8.1", "igniteui-i18n-core": "^1.0.2", - "igniteui-theming": "^27.2.0", + "igniteui-theming": "^27.3.0", "igniteui-trial-watermark": "^3.1.0", "jspdf": "^4.2.1", "lodash-es": "^4.17.21", @@ -14611,9 +14611,9 @@ } }, "node_modules/igniteui-theming": { - "version": "27.2.0", - "resolved": "https://registry.npmjs.org/igniteui-theming/-/igniteui-theming-27.2.0.tgz", - "integrity": "sha512-XGI8MIP2x2RO6yuiAkGHJHbocixPPGoAUQyFOxMgNWWqqGtEEM5OYAkzzKBNjJKWgbrmIMWTXtlIzd8yPV5qjQ==", + "version": "27.3.0", + "resolved": "https://registry.npmjs.org/igniteui-theming/-/igniteui-theming-27.3.0.tgz", + "integrity": "sha512-9xpPZkMUBSBzA1KzBoXurx61RoaUKW7p/H6CWks+Nh8SehsvAj2j4DSQlT0IR6bb41kRICYVNuyTqMicqLmaLA==", "license": "MIT", "dependencies": { "@modelcontextprotocol/sdk": "^1.28.0", diff --git a/package.json b/package.json index e3d69cd71c4..25bc18241ee 100644 --- a/package.json +++ b/package.json @@ -82,7 +82,7 @@ "express": "^5.2.1", "fflate": "^0.8.1", "igniteui-i18n-core": "^1.0.2", - "igniteui-theming": "^27.2.0", + "igniteui-theming": "^27.3.0", "igniteui-trial-watermark": "^3.1.0", "jspdf": "^4.2.1", "lodash-es": "^4.17.21", diff --git a/projects/igniteui-angular/core/src/core/styles/components/grid-summary/_grid-summary-theme.scss b/projects/igniteui-angular/core/src/core/styles/components/grid-summary/_grid-summary-theme.scss index 716d32d1ffc..51f95f417c5 100644 --- a/projects/igniteui-angular/core/src/core/styles/components/grid-summary/_grid-summary-theme.scss +++ b/projects/igniteui-angular/core/src/core/styles/components/grid-summary/_grid-summary-theme.scss @@ -44,7 +44,7 @@ outline-style: none; @if $variant == 'indigo' { - border-top: rem(1px) solid var-get($theme, 'border-color'); + border-top: var-get($theme, 'border-width') var-get($theme, 'border-style') var-get($theme, 'border-color'); } } diff --git a/projects/igniteui-angular/core/src/core/styles/components/grid/_grid-component.scss b/projects/igniteui-angular/core/src/core/styles/components/grid/_grid-component.scss index 44137c2010c..29463e45c6b 100644 --- a/projects/igniteui-angular/core/src/core/styles/components/grid/_grid-component.scss +++ b/projects/igniteui-angular/core/src/core/styles/components/grid/_grid-component.scss @@ -80,6 +80,10 @@ @extend %grid-scroll-start !optional; } + @include e(scroll-end) { + @extend %grid-scroll-end !optional; + } + @include e(scroll-main) { @extend %grid-scroll-main !optional; } diff --git a/projects/igniteui-angular/core/src/core/styles/components/grid/_grid-derived-themes.scss b/projects/igniteui-angular/core/src/core/styles/components/grid/_grid-derived-themes.scss index b0ccfd1633c..44291ab46a5 100644 --- a/projects/igniteui-angular/core/src/core/styles/components/grid/_grid-derived-themes.scss +++ b/projects/igniteui-angular/core/src/core/styles/components/grid/_grid-derived-themes.scss @@ -96,6 +96,23 @@ ) ); + igx-grid-group-by-area, + igx-grid-header-row { + @include tokens( + chip-theme( + $schema: $schema, + $background: color-mix(in srgb, var(--ig-grid-header-text-color) 12%, var(--ig-grid-header-background)), + $hover-background: color-mix(in srgb, var(--ig-grid-header-text-color) 18%, var(--ig-grid-header-background)), + $text-color: var(--ig-grid-header-text-color), + $ghost-background: color-mix(in srgb, var(--ig-grid-header-text-color) 12%, var(--ig-grid-header-background)), + $ghost-text-color: var(--ig-grid-header-text-color), + $disabled-background: color-mix(in srgb, var(--ig-grid-header-text-color) 12%, var(--ig-grid-header-background)), + $disabled-text-color: color-mix(in srgb, var(--ig-grid-header-text-color) 50%, var(--ig-grid-header-background)), + $disabled-border-color: color-mix(in srgb, var(--ig-grid-header-text-color) 24%, var(--ig-grid-header-background)), + ) + ); + } + @include tokens( contained-button-theme( $schema: $schema, @@ -302,7 +319,7 @@ @include tokens( scrollbar-theme( $schema: $schema, - $sb-track-bg-color: var(--_grid-background, $scrollbar-bg-color), + $sb-track-bg-color: var(--_grid-background, var(--content-background), $scrollbar-bg-color), $sb-thumb-bg-color: var(--_scrollbar-thumb-color, $scrollbar-thumb-color), $sb-track-border-color: var(--_scrollbar-track-border-color, $scrollbar-track-border-color), ), diff --git a/projects/igniteui-angular/core/src/core/styles/components/grid/_grid-theme.scss b/projects/igniteui-angular/core/src/core/styles/components/grid/_grid-theme.scss index 8d1bc4700b9..2295bc01c7a 100644 --- a/projects/igniteui-angular/core/src/core/styles/components/grid/_grid-theme.scss +++ b/projects/igniteui-angular/core/src/core/styles/components/grid/_grid-theme.scss @@ -54,7 +54,11 @@ $grid-cell-pinned-style: rem(1px) solid; $grid-cell-pinned-border-color: color($color: 'gray', $variant: 300); - $grid-header-border: var-get($theme, 'header-border-width') var-get($theme, 'header-border-style') var-get($theme, 'header-border-color'); + $grid-header-border-color: if($variant == 'indigo', var-get($theme, 'header-border-color'), hsla(from var-get($theme, 'header-border-color') h s l / 0.38)); + $grid-action-border-color: if($variant == 'indigo', var-get($theme, 'action-border-color'), hsla(from var-get($theme, 'action-border-color') h s l / 0.38)); + $grid-header-border: var-get($theme, 'header-border-width') var-get($theme, 'header-border-style') $grid-header-border-color; + $grid-row-border: var-get($theme, 'row-border-width') var-get($theme, 'row-border-style') var-get($theme, 'row-border-color'); + $grid-scrollbar-borders: rem(1px) solid var(--ig-grid-summary-border-color, var(--row-border-color)); $cell-pin: ( style: var-get($theme, 'pinned-border-width') var-get($theme, 'pinned-border-style'), @@ -606,6 +610,13 @@ %grid-row { border-bottom: none; } + + %grid-mrl-block { + %grid-cell-display { + border-inline-end: $grid-header-border; + border-bottom: $grid-header-border; + } + } } %grid-thead-container { @@ -613,6 +624,18 @@ display: flex; overflow: hidden; + .igx-grid__tr-action:last-of-type { + border-inline-end: $grid-header-border; + } + + .igx-grid-th--pinned-first { + border-inline-start: var(--pinned-border-width) var(--pinned-border-style) var(--header-border-color) !important; + } + + .igx-grid-th--pinned-last { + border-inline-end: var(--pinned-border-width) var(--pinned-border-style) var(--header-border-color) !important; + } + %igx-grid__header-indentation { igx-icon { --component-size: #{if($variant == 'indigo', 2, 3)}; @@ -640,7 +663,7 @@ %igx-grid__header-indentation, %igx-grid__row-indentation, %grid__cbx-selection { - border-bottom: var-get($theme, 'header-border-width') var-get($theme, 'header-border-style') var-get($theme, 'header-border-color'); + border-bottom: $grid-header-border; } } @@ -717,7 +740,6 @@ %grid-tfoot { grid-row: 5; - border-top: $grid-header-border; z-index: 10001; } @@ -754,8 +776,8 @@ } %grid-cell-display { - border-inline-end: rem(1px) solid var-get($theme, 'header-border-color'); - border-bottom: rem(1px) solid var-get($theme, 'header-border-color'); + border-inline-end: $grid-row-border; + border-bottom: $grid-row-border; } } @@ -765,8 +787,8 @@ @if $variant == 'indigo' { %grid-cell-display { - border-inline-end: rem(1px) solid var-get($theme, 'row-border-color'); - border-bottom: rem(1px) solid var-get($theme, 'row-border-color'); + border-inline-end: $grid-row-border; + border-bottom: $grid-row-border; } } } @@ -775,7 +797,7 @@ %igx-grid__hierarchical-expander, %igx-grid__row-indentation, %igx-grid__drag-indicator { - border-bottom: rem(1px) solid var-get($theme, 'row-border-color'); + border-bottom: $grid-row-border; } } @@ -823,31 +845,31 @@ display: flex; flex-flow: row nowrap; width: 100%; - background: var-get($theme, 'header-background'); + background: var-get($theme, 'content-background'); z-index: 10001; } %grid-thead-thumb { background: var-get($theme, 'header-background'); - border-inline-start: rem(1px) solid var-get($theme, 'header-border-color'); + border-inline-start: $grid-header-border; } %grid-tfoot-thumb { position: absolute; top: 0; inset-inline-end: 0; - background: var-get($theme, 'header-background'); - border-inline-start: rem(1px) solid var-get($theme, 'header-border-color'); + background: var(--_grid-background, var-get($theme, 'content-background')); + border-inline-start: $grid-scrollbar-borders; } %grid-tbody-scrollbar { background: var-get($theme, 'content-background'); - border-inline-start: rem(1px) solid var-get($theme, 'row-border-color'); + border-inline-start: $grid-scrollbar-borders; position: relative; } %grid-tbody-scrollbar-start { - background: var-get($theme, 'header-background'); + background: var-get($theme, 'content-background'); } %grid-tbody-scrollbar-main { @@ -855,14 +877,18 @@ } %grid-tbody-scrollbar-end { - background: var-get($theme, 'header-background'); + background: var-get($theme, 'content-background'); } - %grid-scroll-start { - background: var-get($theme, 'header-background'); + %grid-scroll-start, + %grid-scroll-end { + background: var-get($theme, 'content-background'); + border-block-start: $grid-scrollbar-borders; } %grid-scroll-main { + border-block-start: $grid-scrollbar-borders; + igx-display-container { height: 0; } @@ -875,7 +901,7 @@ %grid-row { display: flex; background: var-get($theme, 'content-background'); - border-bottom: rem(1px) solid var-get($theme, 'row-border-color'); + border-bottom: $grid-row-border; outline-style: none; position: relative; background-clip: content-box !important; @@ -1825,13 +1851,11 @@ %grid-summaries--body { --summaries-patch-background: color-mix(in srgb, var(--_grid-foreground, var(--ig-gray-100)) 12%, var(--_grid-background, var(--ig-gray-100))); - border-bottom: rem(1px) dashed var-get($theme, 'row-border-color'); + border-bottom: var(--ig-grid-summary-border-width, rem(1px)) + dashed + var(--ig-grid-summary-border-color, var(--row-border-color)); background-color: var-get($theme, 'summaries-patch-background'); - &:last-of-type { - border-bottom: none; - } - .igx-grid-summary { --background-color: inherit; --result-color: #{adaptive-contrast(var(--background-color))}; @@ -1841,11 +1865,15 @@ %grid-summaries-patch { position: relative; background: inherit; - border-inline-end: rem(1px) solid var-get($theme, 'header-border-color'); + border-inline-end: var(--ig-grid-summary-border-width, rem(1px)) + var(--ig-grid-summary-border-style, solid) + var(--ig-grid-summary-border-color, var(--row-border-color)); z-index: 1; @if $variant == 'indigo' { - border-top: rem(1px) solid var-get($theme, 'header-border-color'); + border-top: var(--ig-grid-summary-border-width, rem(1px)) + var(--ig-grid-summary-border-style, solid) + var(--ig-grid-summary-border-color, var(--row-border-color)); } } @@ -1980,7 +2008,7 @@ background: var-get($theme, 'group-row-background'); display: flex; outline-style: none; - border-bottom: rem(1px) solid var-get($theme, 'row-border-color'); + border-block: $grid-row-border; min-height: var(--header-size); %igx-grid__drag-indicator { @@ -2119,7 +2147,7 @@ map.get($grid-grouping-indicator-padding, 'cosy'), map.get($grid-grouping-indicator-padding, 'comfortable') ); - border-inline-end: rem(1px) solid var-get($theme, 'header-border-color'); + border-inline-end: $grid-row-border; background: inherit; z-index: 1; background-clip: border-box; @@ -2585,7 +2613,7 @@ %igx-grid__tr-container { overflow: auto; width: 100%; - border-bottom: rem(1px) solid var-get($theme, 'row-border-color'); + border-bottom: $grid-row-border; } %igx-grid__tr-container--active { @@ -2714,7 +2742,8 @@ %igx-grid__tr-action { &:last-of-type { - border-inline-end: var-get($theme, 'header-border-width') var-get($theme, 'header-border-style') var-get($theme, 'header-border-color'); + border-inline-end: var-get($theme, 'row-border-width') var-get($theme, 'row-border-style') $grid-action-border-color; + @if $variant != 'indigo' { min-height: sizable( rem(32px), diff --git a/projects/igniteui-angular/core/src/core/styles/components/query-builder/_query-builder-derived-themes.scss b/projects/igniteui-angular/core/src/core/styles/components/query-builder/_query-builder-derived-themes.scss index 661e5c54a07..85db73f1444 100644 --- a/projects/igniteui-angular/core/src/core/styles/components/query-builder/_query-builder-derived-themes.scss +++ b/projects/igniteui-angular/core/src/core/styles/components/query-builder/_query-builder-derived-themes.scss @@ -97,35 +97,35 @@ @include tokens( input-group-theme( $schema: $schema, - $box-background: var(--_grid-background), - $search-background: color-mix(in srgb, var(--_grid-foreground) 6%, var(--_grid-background)), - $idle-bottom-line-color: var(--_grid-accent-color), - $idle-secondary-color: var(--_grid-foreground), - $focused-secondary-color: var(--_grid-accent-color), - $border-color: var(--_grid-accent-color), - $idle-text-color: var(--_grid-foreground), - $placeholder-color: color-mix(in srgb, var(--_grid-foreground) 80%, var(--_grid-background)), + $box-background: var(--_query-builder-background), + $search-background: color-mix(in srgb, var(--_query-builder-foreground) 6%, var(--_query-builder-background)), + $idle-bottom-line-color: var(--_query-builder-accent-color), + $idle-secondary-color: var(--_query-builder-foreground), + $focused-secondary-color: var(--_query-builder-accent-color), + $border-color: var(--_query-builder-accent-color), + $idle-text-color: var(--_query-builder-foreground), + $placeholder-color: color-mix(in srgb, var(--_query-builder-foreground) 80%, var(--_query-builder-background)), ) ); } @else if $variant == 'indigo' { @include tokens( input-group-theme( $schema: $schema, - $idle-bottom-line-color: var(--_grid-accent-color), - $idle-text-color: var(--_grid-foreground), - $placeholder-color: color-mix(in srgb, var(--_grid-foreground) 80%, var(--_grid-background)), + $idle-bottom-line-color: var(--_query-builder-accent-color), + $idle-text-color: var(--_query-builder-foreground), + $placeholder-color: color-mix(in srgb, var(--_query-builder-foreground) 80%, var(--_query-builder-background)), ) ); } @else { @include tokens( input-group-theme( $schema: $schema, - $border-color: var(--_grid-accent-color), - $idle-text-color: var(--_grid-foreground), - $placeholder-color: color-mix(in srgb, var(--_grid-foreground) 80%, var(--_grid-background)), - $input-prefix-background: var(--_grid-accent-color), + $border-color: var(--_query-builder-accent-color), + $idle-text-color: var(--_query-builder-foreground), + $placeholder-color: color-mix(in srgb, var(--_query-builder-foreground) 80%, var(--_query-builder-background)), + $input-prefix-background: var(--_query-builder-accent-color), $border-disabled-background: transparent, - $disabled-border-color: color-mix(in srgb, var(--_grid-accent-color) 50%, transparent), + $disabled-border-color: color-mix(in srgb, var(--_query-builder-accent-color) 50%, transparent), ) ); } diff --git a/projects/igniteui-angular/grids/grid/src/cell-merge.spec.ts b/projects/igniteui-angular/grids/grid/src/cell-merge.spec.ts index 6f852b301e9..125d8abff34 100644 --- a/projects/igniteui-angular/grids/grid/src/cell-merge.spec.ts +++ b/projects/igniteui-angular/grids/grid/src/cell-merge.spec.ts @@ -1167,6 +1167,16 @@ describe('IgxGrid - Cell merging #grid', () => { await activeChange; await wait(20); fix.detectChanges(); + // eslint-disable-next-line no-console + console.log('merge-debug', { + childActiveNode: childGrid.navigation.activeNode, + childActiveNodeRow: childGrid.navigation.activeNode?.row, + childSelectionKeys: Array.from((childGrid as any).selectionService.selection?.keys() || []), + childCachedActiveIndexes: (childGrid as any)._activeRowIndexes, + childActiveIndexes: (childGrid as any).activeRowIndexes, + pipeTrigger: childGrid.pipeTrigger, + childSpans: childGrid.dataRowList.toArray().map(row => row.metaData?.cellMergeMeta?.get(childCol.field)?.rowSpan || 1) + }); GridFunctions.verifyColumnMergedState(childGrid, childCol, [ { value: 'Product A', span: 2 }, diff --git a/projects/igniteui-angular/grids/grid/src/cell.spec.ts b/projects/igniteui-angular/grids/grid/src/cell.spec.ts index ffe76344b43..fd12de9fdff 100644 --- a/projects/igniteui-angular/grids/grid/src/cell.spec.ts +++ b/projects/igniteui-angular/grids/grid/src/cell.spec.ts @@ -201,10 +201,13 @@ describe('IgxGrid - Cell component #grid', () => { const lastCell = cells[cells.length - 1]; expect(GridFunctions.getValueFromCellElement(lastCell)).toEqual('990'); - // Calculate where the end of the cell is. Relative left position should equal the grid calculated width + const scrollbarBorderWidth = parseFloat(getComputedStyle( + grid.nativeElement.querySelector('.igx-grid__tbody-scrollbar') + ).getPropertyValue('border-inline-start-width')) || 0; + // Calculate where the end of the cell is. Relative left position should equal the grid calculated width. expect(lastCell.nativeElement.getBoundingClientRect().left + lastCell.nativeElement.offsetWidth + - grid.scrollSize).toEqual(parseInt(grid.width, 10)); + grid.scrollSize).toEqual(grid.calcWidth + scrollbarBorderWidth); })); it('should not reduce the width of last pinned cell when there is vertical scroll.', () => { diff --git a/projects/igniteui-angular/grids/grid/src/grid-row-pinning.spec.ts b/projects/igniteui-angular/grids/grid/src/grid-row-pinning.spec.ts index 6bb6c25305d..34becfa62fb 100644 --- a/projects/igniteui-angular/grids/grid/src/grid-row-pinning.spec.ts +++ b/projects/igniteui-angular/grids/grid/src/grid-row-pinning.spec.ts @@ -19,6 +19,7 @@ describe('Row Pinning #grid', () => { const FIXED_ROW_CONTAINER = '.igx-grid__tr--pinned '; const CELL_CSS_CLASS = '.igx-grid__td'; const DEBOUNCE_TIME = 60; + const PINNED_ROW_HEIGHT_TOLERANCE = 2; let fix; let grid: IgxGridComponent; @@ -78,7 +79,7 @@ describe('Row Pinning #grid', () => { // 2 records pinned + 2px border expect(grid.pinnedRowHeight).toBe(2 * grid.renderedRowHeight + 2); const expectedHeight = parseInt(grid.height, 10) - grid.pinnedRowHeight - 18 - grid.theadRow.nativeElement.offsetHeight; - expect(grid.calcHeight - expectedHeight).toBeLessThanOrEqual(1); + expect(grid.calcHeight - expectedHeight).toBeLessThanOrEqual(PINNED_ROW_HEIGHT_TOLERANCE); }); it('should pin rows to bottom.', () => { @@ -117,7 +118,7 @@ describe('Row Pinning #grid', () => { // 2 records pinned + 2px border expect(grid.pinnedRowHeight).toBe(2 * grid.renderedRowHeight + 2); const expectedHeight = parseInt(grid.height, 10) - grid.pinnedRowHeight - 18 - grid.theadRow.nativeElement.offsetHeight; - expect(grid.calcHeight - expectedHeight).toBeLessThanOrEqual(1); + expect(grid.calcHeight - expectedHeight).toBeLessThanOrEqual(PINNED_ROW_HEIGHT_TOLERANCE); }); it('should allow pinning row at specified index via API.', () => { @@ -539,7 +540,7 @@ describe('Row Pinning #grid', () => { fix.detectChanges(); let expectedHeight = parseInt(grid.height, 10) - grid.pinnedRowHeight - 18 - grid.theadRow.nativeElement.offsetHeight; - expect(grid.calcHeight - expectedHeight).toBeLessThanOrEqual(1); + expect(grid.calcHeight - expectedHeight).toBeLessThanOrEqual(PINNED_ROW_HEIGHT_TOLERANCE); grid.filter('ID', 'B', IgxStringFilteringOperand.instance().condition('startsWith'), false); fix.detectChanges(); @@ -550,7 +551,7 @@ describe('Row Pinning #grid', () => { fix.detectChanges(); expect(grid.pinnedRowHeight).toBe(0); expectedHeight = parseInt(grid.height, 10) - grid.pinnedRowHeight - 18 - grid.theadRow.nativeElement.offsetHeight; - expect(grid.calcHeight - expectedHeight).toBeLessThanOrEqual(1); + expect(grid.calcHeight - expectedHeight).toBeLessThanOrEqual(PINNED_ROW_HEIGHT_TOLERANCE); }); it('should return correct filterData collection.', () => { @@ -1072,7 +1073,7 @@ describe('Row Pinning #grid', () => { // 1 records pinned + 2px border expect(grid.pinnedRowHeight).toBe(grid.renderedRowHeight + 2); const expectedHeight = parseInt(grid.height, 10) - grid.pinnedRowHeight - 18 - grid.theadRow.nativeElement.offsetHeight; - expect(grid.calcHeight - expectedHeight).toBeLessThanOrEqual(1); + expect(grid.calcHeight - expectedHeight).toBeLessThanOrEqual(PINNED_ROW_HEIGHT_TOLERANCE); }); it('should keep the scrollbar sizes correct when partially filtering out pinned records', () => { @@ -1084,7 +1085,7 @@ describe('Row Pinning #grid', () => { // 4 records pinned + 2px border expect(grid.pinnedRowHeight).toBe(4 * grid.renderedRowHeight + 2); let expectedHeight = parseInt(grid.height, 10) - grid.pinnedRowHeight - 18 - grid.theadRow.nativeElement.offsetHeight; - expect(grid.calcHeight - expectedHeight).toBeLessThanOrEqual(1); + expect(grid.calcHeight - expectedHeight).toBeLessThanOrEqual(PINNED_ROW_HEIGHT_TOLERANCE); grid.filter('ContactTitle', 'Owner', IgxStringFilteringOperand.instance().condition('contains'), false); fix.detectChanges(); @@ -1092,7 +1093,7 @@ describe('Row Pinning #grid', () => { // 2 records pinned + 2px border expect(grid.pinnedRowHeight).toBe(2 * grid.renderedRowHeight + 2); expectedHeight = parseInt(grid.height, 10) - grid.pinnedRowHeight - 18 - grid.theadRow.nativeElement.offsetHeight; - expect(grid.calcHeight - expectedHeight).toBeLessThanOrEqual(1); + expect(grid.calcHeight - expectedHeight).toBeLessThanOrEqual(PINNED_ROW_HEIGHT_TOLERANCE); }); }); diff --git a/projects/igniteui-angular/grids/grid/src/grid.component.spec.ts b/projects/igniteui-angular/grids/grid/src/grid.component.spec.ts index 566a0bb7d50..07b9e63e6c7 100644 --- a/projects/igniteui-angular/grids/grid/src/grid.component.spec.ts +++ b/projects/igniteui-angular/grids/grid/src/grid.component.spec.ts @@ -384,7 +384,7 @@ describe('IgxGrid Component Tests #grid', () => { fixture.componentInstance.generateData(30); fixture.detectChanges(); tick(1000); - expect(parseInt(window.getComputedStyle(gridBody.nativeElement).height, 10)).toBe(548); + expect(parseInt(window.getComputedStyle(gridBody.nativeElement).height, 10)).toBe(549); // Check for empty filter grid message and body less than 100px const columns = fixture.componentInstance.grid.columnList; @@ -392,13 +392,13 @@ describe('IgxGrid Component Tests #grid', () => { fixture.detectChanges(); tick(100); expect(gridBody.nativeElement.textContent).toEqual(grid.emptyFilteredGridMessage); - expect(parseInt(window.getComputedStyle(gridBody.nativeElement).height, 10)).toBe(548); + expect(parseInt(window.getComputedStyle(gridBody.nativeElement).height, 10)).toBe(549); // Clear filter and check if grid's body height is restored based on all loaded rows grid.clearFilter(columns.get(0).field); fixture.detectChanges(); tick(100); - expect(parseInt(window.getComputedStyle(gridBody.nativeElement).height, 10)).toBe(548); + expect(parseInt(window.getComputedStyle(gridBody.nativeElement).height, 10)).toBe(549); // Clearing grid's data and check for empty grid message fixture.componentInstance.clearData(); @@ -431,7 +431,7 @@ describe('IgxGrid Component Tests #grid', () => { fixture.componentInstance.generateData(30); fixture.detectChanges(); tick(1000); - expect(parseInt(window.getComputedStyle(gridBody.nativeElement).height, 10)).toBe(548); + expect(parseInt(window.getComputedStyle(gridBody.nativeElement).height, 10)).toBe(549); loadingIndicator = gridBody.query(By.css('.igx-grid__loading')); expect(loadingIndicator).toBeNull(); @@ -442,13 +442,13 @@ describe('IgxGrid Component Tests #grid', () => { fixture.detectChanges(); tick(100); expect(gridBody.nativeElement.textContent).not.toEqual(grid.emptyFilteredGridMessage); - expect(parseInt(window.getComputedStyle(gridBody.nativeElement).height, 10)).toBe(548); + expect(parseInt(window.getComputedStyle(gridBody.nativeElement).height, 10)).toBe(549); // Clear filter and check if grid's body height is restored based on all loaded rows grid.clearFilter(columns.get(0).field); fixture.detectChanges(); tick(100); - expect(parseInt(window.getComputedStyle(gridBody.nativeElement).height, 10)).toBe(548); + expect(parseInt(window.getComputedStyle(gridBody.nativeElement).height, 10)).toBe(549); // Clearing grid's data and check for empty grid message fixture.componentInstance.clearData(); @@ -661,7 +661,7 @@ describe('IgxGrid Component Tests #grid', () => { fixture.componentInstance.generateData(30); fixture.detectChanges(); tick(1000); - expect(parseInt(window.getComputedStyle(gridBodyContent.nativeElement).height, 10)).toBe(548); + expect(parseInt(window.getComputedStyle(gridBodyContent.nativeElement).height, 10)).toBe(549); loadingIndicator = gridBodyContent.query(By.css('.igx-grid__loading')); expect(loadingIndicator).toBeNull(); diff --git a/projects/igniteui-angular/grids/grid/src/grid.groupby.spec.ts b/projects/igniteui-angular/grids/grid/src/grid.groupby.spec.ts index 7fa61b6eac3..ba85f7020db 100644 --- a/projects/igniteui-angular/grids/grid/src/grid.groupby.spec.ts +++ b/projects/igniteui-angular/grids/grid/src/grid.groupby.spec.ts @@ -1267,11 +1267,15 @@ describe('IgxGrid - GroupBy #grid', () => { // verify virtualization states - should be in last chunk const virtState = grid.verticalScrollContainer.state; - expect(virtState.startIndex).toBe(grid.dataView.length - virtState.chunkSize); + expect(virtState.startIndex + grid.rowList.length).toBe(grid.dataView.length); // verify last row is visible at bottom const lastRow = grid.gridAPI.get_row_by_index(grid.dataView.length - 1); - expect(lastRow.nativeElement.getBoundingClientRect().bottom).toBe(grid.tbody.nativeElement.getBoundingClientRect().bottom); + const rowBorderWidth = parseFloat(getComputedStyle(lastRow.nativeElement).borderBottomWidth) || 0; + const lastRowBottomOffset = Math.abs( + lastRow.nativeElement.getBoundingClientRect().bottom - grid.tbody.nativeElement.getBoundingClientRect().bottom + ); + expect(lastRowBottomOffset).toBe(rowBorderWidth * 2); }); diff --git a/projects/igniteui-angular/package.json b/projects/igniteui-angular/package.json index 8ed6f974008..6af7f9188f8 100644 --- a/projects/igniteui-angular/package.json +++ b/projects/igniteui-angular/package.json @@ -75,7 +75,7 @@ "igniteui-trial-watermark": "^3.1.0", "jspdf": "^4.2.1", "lodash-es": "^4.17.21", - "igniteui-theming": "^27.2.0", + "igniteui-theming": "^27.3.0", "igniteui-i18n-core": "^1.0.5", "@igniteui/material-icons-extended": "^3.1.0" },