From 2e6c2359ee62fbc8fb46b2e26ad146b8dd6697aa Mon Sep 17 00:00:00 2001 From: Vincent Baaij Date: Thu, 29 Aug 2024 16:17:55 +0200 Subject: [PATCH 01/39] Replace grid web components with regular table elements --- ...crosoft.FluentUI.AspNetCore.Components.xml | 8 + ...ataGridNotVirtualizedLoadingAndEmpty.razor | 2 +- .../Demo/Shared/Pages/Lab/IssueTester.razor | 2 + .../Components/DataGrid/FluentDataGrid.razor | 106 ++++----- .../DataGrid/FluentDataGrid.razor.cs | 10 +- .../DataGrid/FluentDataGrid.razor.css | 202 ++++++++++++++++-- 6 files changed, 266 insertions(+), 64 deletions(-) diff --git a/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml b/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml index 648d2f4e7..7153a96a1 100644 --- a/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml +++ b/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml @@ -1838,6 +1838,14 @@ is small or if you are using pagination. + + + This is applicable only when using . It defines how many additional items will be rendered + before and after the visible region to reduce rendering frequency during scrolling. While higher values can improve + scroll smoothness by rendering more items off-screen, they can also increase initial load times. Finding a balance + based on your data set size and user experience requirements is recommended. The default value is 3. + + This is applicable only when using . It defines an expected height in pixels for diff --git a/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridNotVirtualizedLoadingAndEmpty.razor b/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridNotVirtualizedLoadingAndEmpty.razor index 0af35295a..6e507dc2b 100644 --- a/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridNotVirtualizedLoadingAndEmpty.razor +++ b/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridNotVirtualizedLoadingAndEmpty.razor @@ -53,7 +53,7 @@ grid?.SetLoadingState(true); items = null; - await Task.Delay(2500); + await Task.Delay(1500); items = GenerateSampleGridData(100); grid?.SetLoadingState(false); diff --git a/examples/Demo/Shared/Pages/Lab/IssueTester.razor b/examples/Demo/Shared/Pages/Lab/IssueTester.razor index bcdacb427..08bef4c23 100644 --- a/examples/Demo/Shared/Pages/Lab/IssueTester.razor +++ b/examples/Demo/Shared/Pages/Lab/IssueTester.razor @@ -1,2 +1,4 @@ @page "/issue-tester" +@using FluentUI.Demo.Shared.Pages.DataGrid.Examples + diff --git a/src/Core/Components/DataGrid/FluentDataGrid.razor b/src/Core/Components/DataGrid/FluentDataGrid.razor index 733199fe8..6a3f4d8d1 100644 --- a/src/Core/Components/DataGrid/FluentDataGrid.razor +++ b/src/Core/Components/DataGrid/FluentDataGrid.razor @@ -17,7 +17,7 @@ } - + + + @_renderColumnHeaders + + + @* @_renderColumnHeaders - + *@ } - + @if (Loading) { @_renderLoadingContent @@ -56,6 +61,7 @@ @@ -70,7 +76,8 @@ { @ChildContent } - + + @@ -98,34 +105,35 @@ var rowClass = RowClass?.Invoke(item) ?? null; var rowStyle = RowStyle?.Invoke(item) ?? null; Loading = false; - + + @for (var colIndex = 0; colIndex < _columns.Count; colIndex++) { var col = _columns[colIndex]; string? tooltip = col.Tooltip ? @col.RawCellContent(item) : null; - + @((RenderFragment)(__builder => col.CellContent(__builder, item))) - + } - + } private void RenderPlaceholderRow(RenderTreeBuilder __builder, PlaceholderContext placeholderContext) { string? _rowsDataSize = $"height: {ItemSize}px"; - + @for (var colIndex = 0; colIndex < _columns.Count; colIndex++) { var col = _columns[colIndex]; - + @((RenderFragment)(__builder => col.RenderPlaceholderContent(__builder, placeholderContext))) - + } - + } private void RenderColumnHeaders(RenderTreeBuilder __builder) @@ -140,37 +148,37 @@ else col.ShowSortIcon = false; - - @col.HeaderContent - @if (col == _displayOptionsForColumn) - { -
- @col.ColumnOptions -
- } - @if (ResizableColumns && col == _displayResizeForColumn) - { -
+ +
+ @col.HeaderContent + @if (col == _displayOptionsForColumn) + { +
+ @col.ColumnOptions +
+ } + @if (ResizableColumns && col == _displayResizeForColumn) + { +
- @if (ResizeType is not null) - { - - } + @if (ResizeType is not null) + { + + } -
- } +
+ } - @if (ResizableColumns) - { - - } - + @if (ResizableColumns) + { + + } +
+ } } @@ -181,8 +189,8 @@ return; } // If we use the Blazor components here the renderer gets upset/lost, so we use the web components directly - - + + @if (EmptyContent is null) { @("No data to show!") @@ -191,15 +199,15 @@ { @EmptyContent } - - + + } private void RenderLoadingContent(RenderTreeBuilder __builder) { - - + + @if (LoadingContent is null) { @@ -210,7 +218,7 @@ { @LoadingContent } - - + + } } diff --git a/src/Core/Components/DataGrid/FluentDataGrid.razor.cs b/src/Core/Components/DataGrid/FluentDataGrid.razor.cs index a72e9acc5..97fcf3403 100644 --- a/src/Core/Components/DataGrid/FluentDataGrid.razor.cs +++ b/src/Core/Components/DataGrid/FluentDataGrid.razor.cs @@ -76,6 +76,14 @@ public partial class FluentDataGrid : FluentComponentBase, IHandleEve [Parameter] public bool Virtualize { get; set; } + /// + /// This is applicable only when using . It defines how many additional items will be rendered + /// before and after the visible region to reduce rendering frequency during scrolling. While higher values can improve + /// scroll smoothness by rendering more items off-screen, they can also increase initial load times. Finding a balance + /// based on your data set size and user experience requirements is recommended. The default value is 3. + /// + [Parameter] public int OverscanCount { get; set; } = 3; + /// /// This is applicable only when using . It defines an expected height in pixels for /// each row, allowing the virtualization mechanism to fetch the correct number of items to match the display @@ -678,7 +686,7 @@ private string AriaSortValue(ColumnBase column) private string? GridClass() { - var value = $"{Class} {(_pendingDataLoadCancellationTokenSource is null ? null : "loading")}".Trim(); + var value = $"{Class} fluent-data-grid {(_pendingDataLoadCancellationTokenSource is null ? null : "loading")}".Trim(); if (AutoFit) { diff --git a/src/Core/Components/DataGrid/FluentDataGrid.razor.css b/src/Core/Components/DataGrid/FluentDataGrid.razor.css index d371ef5f6..355ff3f10 100644 --- a/src/Core/Components/DataGrid/FluentDataGrid.razor.css +++ b/src/Core/Components/DataGrid/FluentDataGrid.razor.css @@ -1,9 +1,65 @@ -fluent-data-grid { - --col-gap: 1rem; +.fluent-data-grid { + table-layout: fixed; + /*border-collapse: separate;*/ + border-spacing: 0; + width: 100%; + /*--col-gap: 1.0rem;*/ + +} + +::deep thead { + + z-index: 1; + border-bottom: calc(var(--stroke-width) * 1px) solid var(--neutral-stroke-divider-rest); +} + +.col-header-content { + display: flex; + position: relative; + align-items: center; +} + + .col-header-content ::deep .keycapture { + padding-inline-end: calc(var(--design-unit) * 1px + 2px); + } + + .col-header-content ::deep .keycapture, + .col-header-content ::deep .col-sort-container, + .col-header-content ::deep .col-sort-button { + display: flex; + flex-grow: 1; + } + + + +::deep .col-title { + font-weight: 600 !important; + padding: 0.4rem 0.8rem !important; +} + +::deep tr { + border-bottom: calc(var(--stroke-width)* 1px) solid var(--neutral-stroke-divider-rest); + height: 34px; +} + + +.fluent-data-grid tbody > tr > td { + white-space: nowrap; + padding-left: 0.8rem; +} + +.fluent-data-grid thead > tr > th button { + border-radius: calc(var(--control-corner-radius)* 1px); + color: var(--neutral-foreground-rest); + padding: 0.4rem 0.8rem !important; +} + +.fluent-data-grid tbody tr:hover { + background: var(--neutral-fill-stealth-hover); } -::deep .empty-content-row, -::deep .loading-content-row { +.fluent-data-grid .empty-content-row, +.fluent-data-grid.loading-content-row { width: 100%; height: 100% !important; display: flex; @@ -11,8 +67,8 @@ fluent-data-grid { align-items: center; } -::deep .empty-content-cell, -::deep .loading-content-cell { +.fluent-data-grid .empty-content-cell, +.fluent-data-grid .loading-content-cell { font-weight: 600; } @@ -55,16 +111,136 @@ fluent-data-grid { } ::deep .col-width-draghandle { - height: auto; - width: calc(var(--design-unit) * 1px + 2px); - right: calc(var(--col-gap)/2 - 0.5rem); - border-top: none; - border-left: calc(var(--stroke-width) * 1px) solid var(--neutral-stroke-divider-rest); + height: 34px; cursor: col-resize; - position: sticky; - min-width: calc(var(--design-unit) * 1px + 2px); + } .col-width-draghandle:hover, .col-width-draghandle:active { background: var(--neutral-stroke-divider-rest); } + +.header { + padding: 0; + z-index: 3; +} + +.sticky-header { + z-index: 3; +} + +.hover:not([row-type='header'],[row-type='sticky-header'],.loading-content-row):hover { + cursor: pointer; + background-color: var(--datagrid-hover-color, var(--neutral-fill-stealth-hover)); +} + +fluent-data-grid-cell { + text-overflow: ellipsis; +} + +.auto-fit fluent-data-grid-cell { + text-overflow: unset; + overflow: visible; + visibility: hidden; +} + +.multiline-text { + white-space: inherit; + overflow: auto; + word-break: break-word; +} + +.column-header { + padding: calc((var(--design-unit) + var(--focus-stroke-width) - var(--stroke-width)) * 1px) 2px; +} + + .column-header.col-justify-end, .column-header.col-justify-right { + padding-right: 1px; + padding-left: 1px; + justify-content: end; + } + + +.column-header-content ::deep .keycapture .col-sort-container { + display: flex; + flex-grow: 1; +} + + .column-header-content ::deep .keycapture .col-sort-container ::deep .col-sort-button { + flex-grow: 1; + padding-inline-end: 5px; + } + + .column-header-content ::deep .keycapture .col-sort-container .col-sort-button::part(content) { + overflow: hidden; + text-overflow: ellipsis; + } + + .column-header-content.col-justify-end ::deep .col-title-text, .column-header-content.col-justify-right ::deep .col-title-text { + text-align: end; + padding-left: 4px; + } + + .column-header-content.col-justify-end ::deep .col-sort-button, .column-header.col-justify-right ::deep .col-sort-button { + justify-content: end; + } + + .column-header-content.col-justify-center ::deep .col-title-text { + text-align: center; + } + + .column-header-content.col-justify-end ::deep .col-sort-button, .column-header.col-justify-right ::deep .col-sort-button { + justify-content: end; + text-align: end; + } + +::deep .col-sort-button::part(control) { + align-items: center; + justify-content: start; + overflow: hidden; + text-overflow: ellipsis; +} + +::deep .col-sort-button.disabled::part(control) { + opacity: 1 !important; +} + +.col-justify-center ::deep .col-sort-button::part(control) { + justify-content: center; +} + +.col-justify-end ::deep .col-sort-button::part(control), .col-justify-right ::deep .col-sort-button::part(control) { + justify-content: end; +} + +.col-justify-end ::deep .col-sort-button::part(start), .col-justify-right ::deep .col-sort-button::part(start) { + margin-inline-end: 0 !important; +} + +.col-justify-center { + /*justify-self: center;*/ + text-align: center; +} + +.col-justify-end, .col-justify-right { + /*justify-self: end;*/ + text-align: end; + padding-inline-end: 20px; +} + + .col-justify-end .col-title, .col-justify-right .col-title { + justify-content: end; + } + +::deep .col-title { + padding: 0 calc((12 + (var(--design-unit) * 2 * var(--density))) * 1px); + display: flex; + align-items: center; +} + +::deep .col-title-text { + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + font-weight: 600; +} From 9cd10acf94b5dc1173e42b2e79c772193398ce33 Mon Sep 17 00:00:00 2001 From: Vincent Baaij Date: Mon, 2 Sep 2024 14:37:17 +0200 Subject: [PATCH 02/39] Adjust styling --- ...crosoft.FluentUI.AspNetCore.Components.xml | 5 - .../Examples/DataGridTemplateColumns2.razor | 4 +- .../DataGrid/Examples/DataGridTypical.razor | 89 ++++----- .../Examples/DataGridTypical.razor.css | 2 +- .../Examples/DataGridVirtualize.razor | 4 +- .../Pages/Tabs/Examples/TabsDynamic.razor | 26 +++ examples/Demo/Shared/SampleData/DataSource.cs | 2 +- src/Core.Assets/src/index.ts | 34 ++-- .../DataGrid/Columns/ColumnBase.razor | 114 +---------- .../DataGrid/Columns/ColumnBase.razor.cs | 10 +- .../DataGrid/Columns/ColumnBase.razor.css | 23 --- .../DataGrid/Columns/SelectColumn.cs | 4 +- .../Components/DataGrid/FluentDataGrid.razor | 138 +++++++------ .../DataGrid/FluentDataGrid.razor.cs | 47 +++-- .../DataGrid/FluentDataGrid.razor.css | 188 ++---------------- .../DataGrid/FluentDataGridCell.razor | 33 ++- .../DataGrid/FluentDataGridCell.razor.cs | 8 +- .../DataGrid/FluentDataGridCell.razor.css | 141 ++++++------- .../DataGrid/FluentDataGridRow.razor | 20 +- .../DataGrid/FluentDataGridRow.razor.cs | 2 +- .../DataGrid/FluentDataGridRow.razor.css | 10 +- src/Core/Events/EventHandlers.cs | 4 +- 22 files changed, 339 insertions(+), 569 deletions(-) diff --git a/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml b/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml index 7153a96a1..c6afc6c2d 100644 --- a/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml +++ b/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml @@ -1882,11 +1882,6 @@ Labels used in the column options UI. - - - If true, enables the new style of header cell that includes a button to display all column options through a menu. - - Optionally defines a value for @key on each rendered row. Typically this should be used to specify a diff --git a/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTemplateColumns2.razor b/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTemplateColumns2.razor index f9b8bcce8..b5477b6e1 100644 --- a/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTemplateColumns2.razor +++ b/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTemplateColumns2.razor @@ -1,5 +1,5 @@  - + @@ -14,7 +14,7 @@ { public string Name { get; set; } public int Age { get; set; } - + public SampleGridData(string name, int age) { Name = name; diff --git a/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTypical.razor b/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTypical.razor index c3a7fd6db..db302ed49 100644 --- a/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTypical.razor +++ b/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTypical.razor @@ -1,53 +1,50 @@ - -@inject DataSource Data +@inject DataSource Data

To test set ResizeType on the DataGrid to either DataGridResizeType.Discrete or DataGridResizeType.Exact

Remove the parameter completely to get the original behavior

- - - Flag of @(context.Code) - - - - - - - - - - - -
- - 0 - 50 - 100 - 150 - -

- - 0 - 50 - 100 - 150 - -
-
-
-
- +
+ + + Flag of @(context.Code) + + + + + + + + + + + +
+ + 0 + 50 + 100 + 150 + +

+ + 0 + 50 + 100 + 150 + +
+
+
+
+
diff --git a/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTypical.razor.css b/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTypical.razor.css index 2aa0928d6..49724e23d 100644 --- a/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTypical.razor.css +++ b/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTypical.razor.css @@ -1,7 +1,7 @@ /* Ensure all the flags are the same size, and centered */ .flag { height: 1rem; - margin: auto; + margin-top: 7px; border: 1px solid var(--neutral-layer-3); } .search-box { diff --git a/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridVirtualize.razor b/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridVirtualize.razor index 6277b5307..8ddbeb7cd 100644 --- a/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridVirtualize.razor +++ b/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridVirtualize.razor @@ -1,5 +1,5 @@ 
- + @@ -70,7 +70,7 @@ items = null; grid?.SetLoadingState(true); - await Task.Delay(2500); + await Task.Delay(1500); items = GenerateSampleGridData(5000); } diff --git a/examples/Demo/Shared/Pages/Tabs/Examples/TabsDynamic.razor b/examples/Demo/Shared/Pages/Tabs/Examples/TabsDynamic.razor index db13cc8ac..9b3ba52d2 100644 --- a/examples/Demo/Shared/Pages/Tabs/Examples/TabsDynamic.razor +++ b/examples/Demo/Shared/Pages/Tabs/Examples/TabsDynamic.razor @@ -12,6 +12,31 @@ @bind-Label="@item.Name" Data="@item"> Content #@item.Index - @item.Name + + + + Tab one content. This is for testing. + + + Tab two content. This is for testing. + + +

Tab three content. This is for testing.

+

Tab three content. This is for testing.

+

Tab three content. This is for testing.

+

Tab three content. This is for testing.

+

Tab three content. This is for testing.

+

Tab three content. This is for testing.

+

Tab three content. This is for testing.

+

Tab three content. This is for testing.

+

Tab three content. This is for testing.

+

Tab three content. This is for testing.

+

Tab three content. This is for testing.

+

Tab three content. This is for testing.

+

Tab three content. This is for testing.

+
+
+ } @@ -22,6 +47,7 @@ OptionValue="@(i => $"tab-{i.Index}")" @bind-Value="@SelectedTabId" /> Add and select + @code { List Items = new List(DataSource.AllMonths); diff --git a/examples/Demo/Shared/SampleData/DataSource.cs b/examples/Demo/Shared/SampleData/DataSource.cs index 078c6a973..741c3850e 100644 --- a/examples/Demo/Shared/SampleData/DataSource.cs +++ b/examples/Demo/Shared/SampleData/DataSource.cs @@ -295,7 +295,7 @@ private static string GetMonthName(int index) new Country("tr", "Turkey", new Medals { Gold = 0, Silver = 3, Bronze = 5}), new Country("ug", "Uganda", new Medals { Gold = 1, Silver = 1, Bronze = 0}), new Country("ua", "Ukraine", new Medals { Gold = 3, Silver = 5, Bronze = 4}), - new Country("us", "United States", new Medals { Gold = 40, Silver = 44, Bronze = 42}), + new Country("us", "United States of America", new Medals { Gold = 40, Silver = 44, Bronze = 42}), new Country("uz", "Uzbekistan", new Medals { Gold = 8, Silver = 2, Bronze = 3}), new Country("zm", "Zambia", new Medals { Gold = 0, Silver = 0, Bronze = 1}) diff --git a/src/Core.Assets/src/index.ts b/src/Core.Assets/src/index.ts index 38f60bfde..62839edff 100644 --- a/src/Core.Assets/src/index.ts +++ b/src/Core.Assets/src/index.ts @@ -267,23 +267,23 @@ export function afterStarted(blazor: Blazor, mode: string) { } }); - blazor.registerCustomEventType('cellfocus', { - browserEventName: 'cell-focused', - createEventArgs: event => { - return { - cellId: event.detail.attributes['cell-id'].value - }; - } - }); - - blazor.registerCustomEventType('rowfocus', { - browserEventName: 'row-focused', - createEventArgs: event => { - return { - rowId: event.detail.attributes['row-id'].value - }; - } - }); + //blazor.registerCustomEventType('cellfocus', { + // browserEventName: 'cell-focused', + // createEventArgs: event => { + // return { + // cellId: event.detail.attributes['cell-id'].value + // }; + // } + //}); + + //blazor.registerCustomEventType('rowfocus', { + // browserEventName: 'row-focused', + // createEventArgs: event => { + // return { + // rowId: event.detail.attributes['row-id'].value + // }; + // } + //}); blazor.registerCustomEventType('splitterresized', { browserEventName: 'splitterresized', diff --git a/src/Core/Components/DataGrid/Columns/ColumnBase.razor b/src/Core/Components/DataGrid/Columns/ColumnBase.razor index 7e450895f..f5448cddc 100644 --- a/src/Core/Components/DataGrid/Columns/ColumnBase.razor +++ b/src/Core/Components/DataGrid/Columns/ColumnBase.razor @@ -13,12 +13,14 @@ { @HeaderCellItemTemplate(this) } - else if (Grid.HeaderCellAsButtonWithMenu) + else { string? tooltip = Tooltip ? Title : null; + @if (AnyColumnActionEnabled) + {
@Title
@@ -40,7 +42,14 @@ } } -
+ + } + else + { +
+
@Title
+
+ } @if (Sortable.HasValue ? Sortable.Value : IsSortableByDefault()) { @@ -60,107 +69,6 @@
} - else - { - string? tooltip = Tooltip ? Title : null; - - @if (Align == Align.Start || Align == Align.Center) - { - @if (Grid.ResizeType is not null) - { - - - - } - else - { - @if (ColumnOptions is not null) - { - - @if (Filtered.GetValueOrDefault()) - { - - } - else - { - - } - - - } - } - } - - if (Sortable.HasValue ? Sortable.Value : IsSortableByDefault()) - { - - - -
@Title
- - @if (Grid.SortByAscending.HasValue && ShowSortIcon) - { - if (Grid.SortByAscending == true) - { - - } - else - { - - } - } - @if (Grid.ResizeType is not null && ColumnOptions is not null) - { - @if (Filtered.GetValueOrDefault()) - { - - } - } -
-
-
- } - else - { -
-
@Title
- @if (Grid.ResizeType is not null && ColumnOptions is not null) - { - @if (Filtered.GetValueOrDefault()) - { - - } - } -
- } - - @if (Align == Align.End) - { - @if (Grid.ResizeType is not null) - { - - - - } - else - { - @if (ColumnOptions is not null) - { - - @if (Filtered.GetValueOrDefault()) - { - - } - else - { - - } - - - } - } - } - } } internal void RenderPlaceholderContent(RenderTreeBuilder __builder, PlaceholderContext placeholderContext) diff --git a/src/Core/Components/DataGrid/Columns/ColumnBase.razor.cs b/src/Core/Components/DataGrid/Columns/ColumnBase.razor.cs index f186b6ac4..26f687888 100644 --- a/src/Core/Components/DataGrid/Columns/ColumnBase.razor.cs +++ b/src/Core/Components/DataGrid/Columns/ColumnBase.razor.cs @@ -134,6 +134,14 @@ public abstract partial class ColumnBase protected bool AnyColumnActionEnabled => Sortable is true || IsDefaultSortColumn || ColumnOptions != null || Grid.ResizableColumns; + protected override void OnInitialized() + { + if (GetType() == typeof(SelectColumn)) + { + Align = Align.Center; + } + } + /// /// Event callback for when the row is clicked. /// @@ -246,7 +254,7 @@ private async Task HandleSortMenuKeyDownAsync(KeyboardEventArgs args) if (KEYBOARD_MENU_SELECT_KEYS.Contains(args.Key)) { await Grid.SortByColumnAsync(this); - StateHasChanged(); + StateHasChanged(); _isMenuOpen = false; } } diff --git a/src/Core/Components/DataGrid/Columns/ColumnBase.razor.css b/src/Core/Components/DataGrid/Columns/ColumnBase.razor.css index 632ba1fbd..438e982fe 100644 --- a/src/Core/Components/DataGrid/Columns/ColumnBase.razor.css +++ b/src/Core/Components/DataGrid/Columns/ColumnBase.razor.css @@ -1,26 +1,3 @@ -/* Contains the title text and sort indicator, and expands to fill as much of the col width as it can */ -.col-title { - display: flex; /* So that we can make col-title-text expand as much as possible, and still hide overflow with ellipsis */ - min-width: 0px; - flex-grow: 1; - padding: 0; -} - -/* If the column is sortable, its title is rendered as a button element for accessibility and to support navigation by tab */ -button.col-title { - border: none; - background: none; - position: relative; - cursor: pointer; -} - -.col-justify-center .col-title { - justify-content: center; -} - -.col-justify-end .col-title, .col-justify-right .col-title { - flex-direction: row-reverse; /* For end-justified cols, the sort indicator should appear before the title text */ -} /* We put the column title text in its own element primarily so that it can use text-overflow: ellipsis */ .col-title-text { diff --git a/src/Core/Components/DataGrid/Columns/SelectColumn.cs b/src/Core/Components/DataGrid/Columns/SelectColumn.cs index 2535a7c73..97d6cde06 100644 --- a/src/Core/Components/DataGrid/Columns/SelectColumn.cs +++ b/src/Core/Components/DataGrid/Columns/SelectColumn.cs @@ -413,8 +413,8 @@ private RenderFragment GetHeaderContent() builder.AddAttribute(3, "OnClick", EventCallback.Factory.Create(this, OnClickAllAsync)); builder.AddAttribute(4, "onkeydown", EventCallback.Factory.Create(this, OnKeyAllAsync)); } - builder.AddAttribute(5, "Style", "margin-left: 12px;"); - builder.AddAttribute(6, "Title", iconAllChecked == IconIndeterminate + //builder.AddAttribute(5, "Style", "margin-left: 12px;"); + builder.AddAttribute(5, "Title", iconAllChecked == IconIndeterminate ? TitleAllIndeterminate : (iconAllChecked == GetIcon(true) ? TitleAllChecked : TitleAllUnchecked)); builder.CloseComponent(); diff --git a/src/Core/Components/DataGrid/FluentDataGrid.razor b/src/Core/Components/DataGrid/FluentDataGrid.razor index 6a3f4d8d1..f9dc885cb 100644 --- a/src/Core/Components/DataGrid/FluentDataGrid.razor +++ b/src/Core/Components/DataGrid/FluentDataGrid.razor @@ -18,64 +18,60 @@ + id="@Id" + class="@GridClass()" + style="@Style" + aria-rowcount="@(_internalGridContext.TotalItemCount + 1)" + @onclosecolumnoptions="CloseColumnOptions" + @onclosecolumnresize="CloseColumnResize" + @attributes="AdditionalAttributes"> @if (GenerateHeader != GenerateHeaderOption.None) { DataGridRowType headerType = DataGridRowType.Header; if (GenerateHeader == GenerateHeaderOption.Sticky) headerType = DataGridRowType.StickyHeader; - - + + @_renderColumnHeaders - + - @* - @_renderColumnHeaders - *@ + @* + @_renderColumnHeaders + *@ } - @if (Loading) - { - @_renderLoadingContent - } - else - { - @if (Virtualize) + @if (Loading) + { + @_renderLoadingContent + } + else { - if (_internalGridContext.TotalItemCount == 0) + @if (Virtualize) { - @_renderEmptyContent + if (_internalGridContext.TotalItemCount == 0) + { + @_renderEmptyContent + } + else + { + + } } else { - + @_renderNonVirtualizedRows } } - else + @if (_manualGrid) { - @_renderNonVirtualizedRows + @ChildContent } - } - @if (_manualGrid) - { - @ChildContent - }
@@ -102,38 +98,46 @@ private void RenderRow(RenderTreeBuilder __builder, int rowIndex, TGridItem item) { - var rowClass = RowClass?.Invoke(item) ?? null; + var rowClass = (ShowHover ? "hover " : RowClass?.Invoke(item) ?? null)?.TrimEnd(); var rowStyle = RowStyle?.Invoke(item) ?? null; Loading = false; - + // + @for (var colIndex = 0; colIndex < _columns.Count; colIndex++) { var col = _columns[colIndex]; string? tooltip = col.Tooltip ? @col.RawCellContent(item) : null; - + // + @((RenderFragment)(__builder => col.CellContent(__builder, item))) - + + // } - + + // } private void RenderPlaceholderRow(RenderTreeBuilder __builder, PlaceholderContext placeholderContext) { string? _rowsDataSize = $"height: {ItemSize}px"; - + // + @for (var colIndex = 0; colIndex < _columns.Count; colIndex++) { var col = _columns[colIndex]; - + // + @((RenderFragment)(__builder => col.RenderPlaceholderContent(__builder, placeholderContext))) - + + // } - + + // } private void RenderColumnHeaders(RenderTreeBuilder __builder) @@ -148,17 +152,19 @@ else col.ShowSortIcon = false; - +
@col.HeaderContent @if (col == _displayOptionsForColumn) {
- @col.ColumnOptions + @col.ColumnOptions
} @if (ResizableColumns && col == _displayResizeForColumn) @@ -178,7 +184,7 @@ }
- +
} } @@ -188,9 +194,9 @@ { return; } - // If we use the Blazor components here the renderer gets upset/lost, so we use the web components directly - - + + + @if (EmptyContent is null) { @("No data to show!") @@ -199,18 +205,18 @@ { @EmptyContent } - - + + } private void RenderLoadingContent(RenderTreeBuilder __builder) { - - + + @if (LoadingContent is null) { - +
Loading...
} @@ -218,7 +224,7 @@ { @LoadingContent } - - +
+
} } diff --git a/src/Core/Components/DataGrid/FluentDataGrid.razor.cs b/src/Core/Components/DataGrid/FluentDataGrid.razor.cs index 97fcf3403..21c79369d 100644 --- a/src/Core/Components/DataGrid/FluentDataGrid.razor.cs +++ b/src/Core/Components/DataGrid/FluentDataGrid.razor.cs @@ -7,6 +7,7 @@ using Microsoft.FluentUI.AspNetCore.Components.DataGrid.Infrastructure; using Microsoft.FluentUI.AspNetCore.Components.Extensions; using Microsoft.FluentUI.AspNetCore.Components.Infrastructure; +using Microsoft.FluentUI.AspNetCore.Components.Utilities; using Microsoft.JSInterop; using System.Diagnostics.CodeAnalysis; @@ -126,12 +127,6 @@ public partial class FluentDataGrid : FluentComponentBase, IHandleEve [Parameter] public ColumnOptionsLabels ColumnOptionsLabels { get; set; } = ColumnOptionsLabels.Default; - /// - /// If true, enables the new style of header cell that includes a button to display all column options through a menu. - /// - [Parameter] - public bool HeaderCellAsButtonWithMenu { get; set; } - /// /// Optionally defines a value for @key on each rendered row. Typically this should be used to specify a /// unique identifier, such as a primary key value, for each data item. @@ -680,29 +675,39 @@ private string AriaSortValue(ColumnBase column) : "none"; private string? ColumnHeaderClass(ColumnBase column) - => _sortByColumn == column - ? $"{ColumnClass(column)} {(_sortByAscending ? "col-sort-asc" : "col-sort-desc")}" - : ColumnClass(column); + { + return new CssBuilder(Class) + .AddClass(ColumnJustifyClass(column)) + .AddClass("col-sort-asc", _sortByAscending) + .AddClass("col-sort-desc", !_sortByAscending) + .Build(); + } private string? GridClass() { - var value = $"{Class} fluent-data-grid {(_pendingDataLoadCancellationTokenSource is null ? null : "loading")}".Trim(); - if (AutoFit) - { - value += " auto-fit"; - } + return new CssBuilder("fluent-data-grid") + .AddClass(Class) + .AddClass("loading", _pendingDataLoadCancellationTokenSource is not null) + .AddClass("auto-fit", AutoFit) + .Build(); + } - return string.IsNullOrEmpty(value) ? null : value; + private static string? ColumnJustifyClass(ColumnBase column) + { + return new CssBuilder(column.Class) + .AddClass("col-justify-start", column.Align == Align.Start) + .AddClass("col-justify-center", column.Align == Align.Center) + .AddClass("col-justify-end", column.Align == Align.End) + .Build(); } - private static string? ColumnClass(ColumnBase column) => column.Align switch + private static string? ColumnStyle(ColumnBase column) { - Align.Start => $"col-justify-start {column.Class}", - Align.Center => $"col-justify-center {column.Class}", - Align.End => $"col-justify-end {column.Class}", - _ => column.Class, - }; + return new StyleBuilder(column.Style) + .AddStyle("width", column.Width, column.Width is not null ) + .Build(); + } /// public async ValueTask DisposeAsync() diff --git a/src/Core/Components/DataGrid/FluentDataGrid.razor.css b/src/Core/Components/DataGrid/FluentDataGrid.razor.css index 355ff3f10..26ae78f05 100644 --- a/src/Core/Components/DataGrid/FluentDataGrid.razor.css +++ b/src/Core/Components/DataGrid/FluentDataGrid.razor.css @@ -1,37 +1,9 @@ .fluent-data-grid { table-layout: fixed; - /*border-collapse: separate;*/ border-spacing: 0; width: 100%; - /*--col-gap: 1.0rem;*/ - -} - -::deep thead { - - z-index: 1; - border-bottom: calc(var(--stroke-width) * 1px) solid var(--neutral-stroke-divider-rest); } -.col-header-content { - display: flex; - position: relative; - align-items: center; -} - - .col-header-content ::deep .keycapture { - padding-inline-end: calc(var(--design-unit) * 1px + 2px); - } - - .col-header-content ::deep .keycapture, - .col-header-content ::deep .col-sort-container, - .col-header-content ::deep .col-sort-button { - display: flex; - flex-grow: 1; - } - - - ::deep .col-title { font-weight: 600 !important; padding: 0.4rem 0.8rem !important; @@ -42,35 +14,16 @@ height: 34px; } - -.fluent-data-grid tbody > tr > td { +tbody > tr > td { white-space: nowrap; padding-left: 0.8rem; + text-overflow: ellipsis; } -.fluent-data-grid thead > tr > th button { - border-radius: calc(var(--control-corner-radius)* 1px); - color: var(--neutral-foreground-rest); - padding: 0.4rem 0.8rem !important; -} - -.fluent-data-grid tbody tr:hover { +.fluent-data-grid tbody tr .hover { background: var(--neutral-fill-stealth-hover); } -.fluent-data-grid .empty-content-row, -.fluent-data-grid.loading-content-row { - width: 100%; - height: 100% !important; - display: flex; - justify-content: center; - align-items: center; -} - -.fluent-data-grid .empty-content-cell, -.fluent-data-grid .loading-content-cell { - font-weight: 600; -} .col-options, .col-resize { position: absolute; @@ -88,20 +41,19 @@ left: unset; } -.col-justify-end .col-options, .col-justify-right .col-options { +.col-justify-end .col-options, +.col-justify-right .col-options { left: unset; margin-right: 0.6rem; } -[dir=rtl] .col-justify-end .col-options, [dir=rtl] .col-justify-right .col-options { +[dir=rtl] .col-justify-end .col-options, +[dir=rtl] .col-justify-right .col-options { right: unset; margin-left: 0.6rem; } -::deep > fluent-data-grid-row > fluent-data-grid-cell.grid-cell-placeholder:after { - content: '\2026'; /*horizontal ellipsis*/ - opacity: 0.75; -} + .resize-options { display: flex; @@ -113,11 +65,8 @@ ::deep .col-width-draghandle { height: 34px; cursor: col-resize; - -} - -.col-width-draghandle:hover, .col-width-draghandle:active { - background: var(--neutral-stroke-divider-rest); + margin-left: calc(var(--design-unit) * 2px); + width: calc(var(--design-unit) * 1px + 2px); } .header { @@ -125,8 +74,11 @@ z-index: 3; } -.sticky-header { - z-index: 3; +thead[row-type='sticky-header'] { + position: sticky; + top: 0; + background-color: var(--neutral-fill-stealth-rest); + z-index: 2; } .hover:not([row-type='header'],[row-type='sticky-header'],.loading-content-row):hover { @@ -134,113 +86,3 @@ background-color: var(--datagrid-hover-color, var(--neutral-fill-stealth-hover)); } -fluent-data-grid-cell { - text-overflow: ellipsis; -} - -.auto-fit fluent-data-grid-cell { - text-overflow: unset; - overflow: visible; - visibility: hidden; -} - -.multiline-text { - white-space: inherit; - overflow: auto; - word-break: break-word; -} - -.column-header { - padding: calc((var(--design-unit) + var(--focus-stroke-width) - var(--stroke-width)) * 1px) 2px; -} - - .column-header.col-justify-end, .column-header.col-justify-right { - padding-right: 1px; - padding-left: 1px; - justify-content: end; - } - - -.column-header-content ::deep .keycapture .col-sort-container { - display: flex; - flex-grow: 1; -} - - .column-header-content ::deep .keycapture .col-sort-container ::deep .col-sort-button { - flex-grow: 1; - padding-inline-end: 5px; - } - - .column-header-content ::deep .keycapture .col-sort-container .col-sort-button::part(content) { - overflow: hidden; - text-overflow: ellipsis; - } - - .column-header-content.col-justify-end ::deep .col-title-text, .column-header-content.col-justify-right ::deep .col-title-text { - text-align: end; - padding-left: 4px; - } - - .column-header-content.col-justify-end ::deep .col-sort-button, .column-header.col-justify-right ::deep .col-sort-button { - justify-content: end; - } - - .column-header-content.col-justify-center ::deep .col-title-text { - text-align: center; - } - - .column-header-content.col-justify-end ::deep .col-sort-button, .column-header.col-justify-right ::deep .col-sort-button { - justify-content: end; - text-align: end; - } - -::deep .col-sort-button::part(control) { - align-items: center; - justify-content: start; - overflow: hidden; - text-overflow: ellipsis; -} - -::deep .col-sort-button.disabled::part(control) { - opacity: 1 !important; -} - -.col-justify-center ::deep .col-sort-button::part(control) { - justify-content: center; -} - -.col-justify-end ::deep .col-sort-button::part(control), .col-justify-right ::deep .col-sort-button::part(control) { - justify-content: end; -} - -.col-justify-end ::deep .col-sort-button::part(start), .col-justify-right ::deep .col-sort-button::part(start) { - margin-inline-end: 0 !important; -} - -.col-justify-center { - /*justify-self: center;*/ - text-align: center; -} - -.col-justify-end, .col-justify-right { - /*justify-self: end;*/ - text-align: end; - padding-inline-end: 20px; -} - - .col-justify-end .col-title, .col-justify-right .col-title { - justify-content: end; - } - -::deep .col-title { - padding: 0 calc((12 + (var(--design-unit) * 2 * var(--density))) * 1px); - display: flex; - align-items: center; -} - -::deep .col-title-text { - text-overflow: ellipsis; - overflow: hidden; - white-space: nowrap; - font-weight: 600; -} diff --git a/src/Core/Components/DataGrid/FluentDataGridCell.razor b/src/Core/Components/DataGrid/FluentDataGridCell.razor index a05de6cc3..e91cfa01d 100644 --- a/src/Core/Components/DataGrid/FluentDataGridCell.razor +++ b/src/Core/Components/DataGrid/FluentDataGridCell.razor @@ -1,13 +1,26 @@ @namespace Microsoft.FluentUI.AspNetCore.Components @inherits FluentComponentBase @typeparam TGridItem - - @ChildContent - + +@if (CellType == DataGridCellType.Default || CellType == DataGridCellType.RowHeader) +{ + + @ChildContent + +} +else +{ + + @ChildContent + +} diff --git a/src/Core/Components/DataGrid/FluentDataGridCell.razor.cs b/src/Core/Components/DataGrid/FluentDataGridCell.razor.cs index c81423a88..862b6a1e6 100644 --- a/src/Core/Components/DataGrid/FluentDataGridCell.razor.cs +++ b/src/Core/Components/DataGrid/FluentDataGridCell.razor.cs @@ -23,7 +23,7 @@ public partial class FluentDataGridCell : FluentComponentBase /// Gets or sets the cell type. See . /// [Parameter] - public DataGridCellType? CellType { get; set; } = DataGridCellType.Default; + public DataGridCellType CellType { get; set; } /// /// Gets or sets the column index of the cell. @@ -55,9 +55,13 @@ public partial class FluentDataGridCell : FluentComponentBase /// private ColumnBase? Column => Owner.Owner.Grid._columns.ElementAtOrDefault(GridColumn - 1); + protected string? ClassValue => new CssBuilder(Class) + .AddClass("col-header", when: CellType == DataGridCellType.ColumnHeader) + .Build(); + protected string? StyleValue => new StyleBuilder(Style) .AddStyle("height", $"{GridContext.Grid.ItemSize:0}px", () => !GridContext.Grid.Loading && GridContext.Grid.Virtualize && Owner.RowType == DataGridRowType.Default) - .AddStyle("align-content", "center", () => !GridContext.Grid.Loading && GridContext.Grid.Virtualize && Owner.RowType == DataGridRowType.Default && string.IsNullOrEmpty(Style)) + //.AddStyle("text-align-content", "center", () => !GridContext.Grid.Loading && GridContext.Grid.Virtualize && Owner.RowType == DataGridRowType.Default && string.IsNullOrEmpty(Style)) .Build(); protected override void OnInitialized() diff --git a/src/Core/Components/DataGrid/FluentDataGridCell.razor.css b/src/Core/Components/DataGrid/FluentDataGridCell.razor.css index e866d970d..cf9625a55 100644 --- a/src/Core/Components/DataGrid/FluentDataGridCell.razor.css +++ b/src/Core/Components/DataGrid/FluentDataGridCell.razor.css @@ -2,6 +2,36 @@ fluent-data-grid-cell { text-overflow: ellipsis; } +tbody > tr > td { + padding-left: 0.8rem; + overflow:hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +td.col-justify-center { + text-align: center; + padding-inline-start: 0; +} + +td.col-justify-end, +td.col-justify-right { + text-align: end; + padding-inline-end: calc(var(--design-unit) * 7px); +} + +td.grid-cell-placeholder:after { + content: '\2026'; /*horizontal ellipsis*/ + opacity: 0.75; +} + +.empty-content-cell, +.loading-content-cell { + font-weight: 600; + text-align: center; +} + + .auto-fit fluent-data-grid-cell { text-overflow: unset; overflow: visible; @@ -14,110 +44,65 @@ fluent-data-grid-cell { word-break: break-word; } -.column-header { +::deep .col-header-content { display: flex; - width: 100%; - align-self: center; - padding-inline: 0; - padding-right: 1px; - padding-left: 1px; } - .column-header.col-justify-end, .column-header.col-justify-right { - padding-right: 1px; - padding-left: 1px; - justify-content: end; - } - - .column-header.col-justify-center { - padding-left: 1px; - padding-right: 1px; - justify-content: center; - } +.col-header { + position:relative; + width: 100%; + padding: calc((var(--design-unit) + var(--focus-stroke-width) - var(--stroke-width)) * 1px) 1px calc((var(--design-unit) + var(--focus-stroke-width) - var(--stroke-width)) * 1px); +} - .column-header > ::deep .keycapture { + .col-header ::deep .keycapture { display: flex; flex-grow: 1; + padding-inline-end: calc(var(--design-unit) * 1px); } - .column-header > ::deep .keycapture .col-sort-container { + + .col-header ::deep .col-sort-container, + .col-header ::deep .col-sort-button { display: flex; flex-grow: 1; } - .column-header > ::deep .keycapture .col-sort-container .col-sort-button { - flex-grow: 1; - padding-inline-end: 5px; + .col-header ::deep .col-sort-button::part(content) { + overflow: hidden; + text-overflow: ellipsis; } - .column-header > ::deep .keycapture .col-sort-container .col-sort-button::part(content) { - overflow: hidden; - text-overflow: ellipsis; - } - - .column-header.col-justify-end ::deep .col-title-text, .column-header.col-justify-right ::deep .col-title-text { - text-align: end; - padding-left: 4px; - } - - .column-header.col-justify-end ::deep .col-sort-button, .column-header.col-justify-right ::deep .col-sort-button { - justify-content: end; - } - - .column-header.col-justify-center ::deep .col-title-text { - text-align: center; - } +::deep .col-title { + padding: 0 calc((12 + (var(--design-unit) * 2 * var(--density))) * 1px); + display: flex; + align-items: center; + flex-grow: 1; + user-select: none; +} - .column-header.col-justify-end ::deep .col-sort-button, .column-header.col-justify-right ::deep .col-sort-button { - justify-content: end; - text-align: end; - } +::deep .col-title-text { + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + font-weight: 600; +} -::deep .col-sort-button::part(control) { +.col-justify-start ::deep .col-sort-button::part(control) { align-items: center; justify-content: start; overflow: hidden; text-overflow: ellipsis; } -::deep .col-sort-button.disabled::part(control) { - opacity: 1 !important; -} - -.col-justify-center ::deep .col-sort-button::part(control) { - justify-content: center; -} - -.col-justify-end ::deep .col-sort-button::part(control), .col-justify-right ::deep .col-sort-button::part(control) { +.col-justify-end ::deep .col-sort-button::part(control) { justify-content: end; } -.col-justify-end ::deep .col-sort-button::part(start), .col-justify-right ::deep .col-sort-button::part(start) { +.col-justify-end ::deep .col-sort-button::part(start) { margin-inline-end: 0 !important; } -.col-justify-center { - justify-self: center; -} - -.col-justify-end, .col-justify-right { - justify-self: end; - padding-inline-end: 20px; -} - - .col-justify-end .col-title, .col-justify-right .col-title { - justify-content: end; - } - -::deep .col-title { - padding: 0 calc((12 + (var(--design-unit) * 2 * var(--density))) * 1px); - display: flex; - align-items: center; -} - -::deep .col-title-text { - text-overflow: ellipsis; - overflow: hidden; - white-space: nowrap; - font-weight: 600; +.col-justify-start ::deep .col-sort-button::part(end), +.col-justify-center ::deep .col-sort-button::part(end) { + margin-inline-start: 0 !important; } diff --git a/src/Core/Components/DataGrid/FluentDataGridRow.razor b/src/Core/Components/DataGrid/FluentDataGridRow.razor index 809c81781..50bbbf793 100644 --- a/src/Core/Components/DataGrid/FluentDataGridRow.razor +++ b/src/Core/Components/DataGrid/FluentDataGridRow.razor @@ -3,17 +3,13 @@ @typeparam TGridItem @attribute [CascadingTypeParameter(nameof(TGridItem))] - + @ChildContent - + diff --git a/src/Core/Components/DataGrid/FluentDataGridRow.razor.cs b/src/Core/Components/DataGrid/FluentDataGridRow.razor.cs index c17580ed5..4e4461327 100644 --- a/src/Core/Components/DataGrid/FluentDataGridRow.razor.cs +++ b/src/Core/Components/DataGrid/FluentDataGridRow.razor.cs @@ -65,7 +65,7 @@ public partial class FluentDataGridRow : FluentComponentBase, IHandle protected string? StyleValue => new StyleBuilder(Style) .AddStyle("height", $"{Owner.Grid.ItemSize:0}px", () => Owner.Grid.Virtualize && RowType == DataGridRowType.Default) .AddStyle("height", "100%", () => (!Owner.Grid.Virtualize || Owner.Rows.Count == 0) && Owner.Grid.Loading && RowType == DataGridRowType.Default) - .AddStyle("align-items", "center", () => Owner.Grid.Virtualize && RowType == DataGridRowType.Default && string.IsNullOrEmpty(Style)) + //.AddStyle("text-align", "center", () => Owner.Grid.Virtualize && RowType == DataGridRowType.Default && string.IsNullOrEmpty(Style)) .Build(); protected override void OnInitialized() diff --git a/src/Core/Components/DataGrid/FluentDataGridRow.razor.css b/src/Core/Components/DataGrid/FluentDataGridRow.razor.css index e206f8b60..e2108c3da 100644 --- a/src/Core/Components/DataGrid/FluentDataGridRow.razor.css +++ b/src/Core/Components/DataGrid/FluentDataGridRow.razor.css @@ -7,7 +7,15 @@ z-index: 3; } -.hover:not([row-type='header'],[row-type='sticky-header'],.loading-content-row):hover { +.hover:not([row-type='header'],[row-type='sticky-header'] +,.loading-content-row):hover { cursor: pointer; background-color: var(--datagrid-hover-color, var(--neutral-fill-stealth-hover)); } + +.empty-content-row, +.loading-content-row { + width: 100%; + height: 100% !important; +} + diff --git a/src/Core/Events/EventHandlers.cs b/src/Core/Events/EventHandlers.cs index 07a5936d8..43ce21a03 100644 --- a/src/Core/Events/EventHandlers.cs +++ b/src/Core/Events/EventHandlers.cs @@ -14,8 +14,8 @@ namespace Microsoft.FluentUI.AspNetCore.Components; [EventHandler("onmenuchange", typeof(MenuChangeEventArgs), enableStopPropagation: true, enablePreventDefault: true)] [EventHandler("onscrollstart", typeof(HorizontalScrollEventArgs), enableStopPropagation: true, enablePreventDefault: true)] [EventHandler("onscrollend", typeof(HorizontalScrollEventArgs), enableStopPropagation: true, enablePreventDefault: true)] -[EventHandler("oncellfocus", typeof(DataGridCellFocusEventArgs), enableStopPropagation: true, enablePreventDefault: true)] -[EventHandler("onrowfocus", typeof(DataGridRowFocusEventArgs), enableStopPropagation: true, enablePreventDefault: true)] +//[EventHandler("oncellfocus", typeof(DataGridCellFocusEventArgs), enableStopPropagation: true, enablePreventDefault: true)] +//[EventHandler("onrowfocus", typeof(DataGridRowFocusEventArgs), enableStopPropagation: true, enablePreventDefault: true)] [EventHandler("onclosecolumnoptions", typeof(EventArgs), enableStopPropagation: true, enablePreventDefault: true)] [EventHandler("onclosecolumnresize", typeof(EventArgs), enableStopPropagation: true, enablePreventDefault: true)] [EventHandler("ontooltipdismiss", typeof(EventArgs), enableStopPropagation: true, enablePreventDefault: true)] From 5212a8b6dddf04b30875d3a59e1fb5fcaa9e3f58 Mon Sep 17 00:00:00 2001 From: Vincent Baaij Date: Tue, 3 Sep 2024 23:20:13 +0200 Subject: [PATCH 03/39] Resize rework --- .../DataGrid/FluentDataGrid.razor.js | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/Core/Components/DataGrid/FluentDataGrid.razor.js b/src/Core/Components/DataGrid/FluentDataGrid.razor.js index d6c3c6ead..6d01fc21a 100644 --- a/src/Core/Components/DataGrid/FluentDataGrid.razor.js +++ b/src/Core/Components/DataGrid/FluentDataGrid.razor.js @@ -6,7 +6,7 @@ export function init(gridElement) { return; }; - if (gridElement.querySelectorAll('.column-header.resizable').length > 0) { + if (gridElement.querySelectorAll('.col-header.resizable').length > 0) { initialColumnsWidths[gridElement.id] = gridElement.gridTemplateColumns ; enableColumnResizing(gridElement); } @@ -167,7 +167,7 @@ export function enableColumnResizing(gridElement) { let headerBeingResized; let resizeHandle; - gridElement.querySelectorAll('.column-header.resizable').forEach(header => { + gridElement.querySelectorAll('.col-header.resizable').forEach(header => { columns.push({ header }); const onPointerMove = (e) => requestAnimationFrame(() => { if (!headerBeingResized) { @@ -181,9 +181,10 @@ export function enableColumnResizing(gridElement) { const width = pointerLocalLeft - headerLocalLeft; const column = columns.find(({ header }) => header === headerBeingResized); - min = header.querySelector('.col-options-button') ? 100 : 75; + //min = header.querySelector('.col-options-button') ? 100 : 75; column.size = Math.max(min, width) + 'px'; + headerBeingResized.style.width = column.size; // Set initial sizes columns.forEach((column) => { @@ -208,7 +209,7 @@ export function enableColumnResizing(gridElement) { const initResize = ({ target, pointerId }) => { resizeHandle = target; - headerBeingResized = target.parentNode; + headerBeingResized = target.parentNode.parentNode; resizeHandle.setPointerCapture(pointerId); }; @@ -231,7 +232,7 @@ export function resetColumnWidths(gridElement) { export function resizeColumnDiscrete(gridElement, column, change) { - let headers = gridElement.querySelectorAll('.column-header.resizable'); + let headers = gridElement.querySelectorAll('.col-header.resizable'); if (headers.length <= 0) { return } @@ -239,13 +240,13 @@ export function resizeColumnDiscrete(gridElement, column, change) { let headerBeingResized; if (!column) { - if (!(document.activeElement.classList.contains("column-header") && document.activeElement.classList.contains("resizable"))) { + if (!(document.activeElement.classList.contains("col-header") && document.activeElement.classList.contains("resizable"))) { return; } headerBeingResized = document.activeElement; } else { - headerBeingResized = gridElement.querySelector('.column-header[grid-column="' + column + '"]'); + headerBeingResized = gridElement.querySelector('.col-header[grid-column="' + column + '"]'); } const columns = []; @@ -303,12 +304,12 @@ export function autoFitGridColumns(gridElement, columnCount) { export function resizeColumnExact(gridElement, column, width) { - let headers = gridElement.querySelectorAll('.column-header.resizable'); + let headers = gridElement.querySelectorAll('.col-header.resizable'); if (headers.length <= 0) { return } - let headerBeingResized = gridElement.querySelector('.column-header[grid-column="' + column + '"]'); + let headerBeingResized = gridElement.querySelector('.col-header[grid-column="' + column + '"]'); if (!headerBeingResized) { return; } From f0904e5ae8999118e5e1a9f84f599b4b40f48e26 Mon Sep 17 00:00:00 2001 From: Vincent Baaij Date: Wed, 4 Sep 2024 13:04:59 +0200 Subject: [PATCH 04/39] - Rename example EventHandlers - Adapt more samples to table rendering - Undo Tabs example changes - Remove grid custom events from script etc --- .../Examples/DataGridTemplateColumns2.razor | 6 ++--- .../Examples/DataGridVirtualize.razor | 12 ++++----- .../Pages/Tabs/Examples/TabsDynamic.razor | 25 ------------------- src/Core.Assets/src/index.ts | 18 ------------- .../DataGrid/FluentDataGridCell.razor.css | 17 +++++++++++-- src/Core/Events/EventHandlers.cs | 2 -- 6 files changed, 24 insertions(+), 56 deletions(-) diff --git a/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTemplateColumns2.razor b/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTemplateColumns2.razor index b5477b6e1..74c21150e 100644 --- a/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTemplateColumns2.razor +++ b/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTemplateColumns2.razor @@ -1,5 +1,5 @@  - + @@ -30,12 +30,12 @@ new SampleGridData("Bob", 20 ) }; - private void HandleRowFocus(FluentDataGridRow row) + private void HandleRowClick(FluentDataGridRow row) { DemoLogger.WriteLine($"Row focused: {row.RowIndex}"); } - private void HandleCellFocus(FluentDataGridCell cell) + private void HandleCellClick(FluentDataGridCell cell) { DemoLogger.WriteLine($"Cell focused: {cell.GridColumn}"); } diff --git a/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridVirtualize.razor b/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridVirtualize.razor index 8ddbeb7cd..2b0e6bdb2 100644 --- a/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridVirtualize.razor +++ b/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridVirtualize.razor @@ -1,10 +1,10 @@ -
- +
+ - - - - + + + +   Nothing to see here. Carry on! diff --git a/examples/Demo/Shared/Pages/Tabs/Examples/TabsDynamic.razor b/examples/Demo/Shared/Pages/Tabs/Examples/TabsDynamic.razor index 9b3ba52d2..fa25b58cb 100644 --- a/examples/Demo/Shared/Pages/Tabs/Examples/TabsDynamic.razor +++ b/examples/Demo/Shared/Pages/Tabs/Examples/TabsDynamic.razor @@ -12,31 +12,6 @@ @bind-Label="@item.Name" Data="@item"> Content #@item.Index - @item.Name - - - - Tab one content. This is for testing. - - - Tab two content. This is for testing. - - -

Tab three content. This is for testing.

-

Tab three content. This is for testing.

-

Tab three content. This is for testing.

-

Tab three content. This is for testing.

-

Tab three content. This is for testing.

-

Tab three content. This is for testing.

-

Tab three content. This is for testing.

-

Tab three content. This is for testing.

-

Tab three content. This is for testing.

-

Tab three content. This is for testing.

-

Tab three content. This is for testing.

-

Tab three content. This is for testing.

-

Tab three content. This is for testing.

-
-
- } diff --git a/src/Core.Assets/src/index.ts b/src/Core.Assets/src/index.ts index 62839edff..a75e3662c 100644 --- a/src/Core.Assets/src/index.ts +++ b/src/Core.Assets/src/index.ts @@ -267,24 +267,6 @@ export function afterStarted(blazor: Blazor, mode: string) { } }); - //blazor.registerCustomEventType('cellfocus', { - // browserEventName: 'cell-focused', - // createEventArgs: event => { - // return { - // cellId: event.detail.attributes['cell-id'].value - // }; - // } - //}); - - //blazor.registerCustomEventType('rowfocus', { - // browserEventName: 'row-focused', - // createEventArgs: event => { - // return { - // rowId: event.detail.attributes['row-id'].value - // }; - // } - //}); - blazor.registerCustomEventType('splitterresized', { browserEventName: 'splitterresized', createEventArgs: event => { diff --git a/src/Core/Components/DataGrid/FluentDataGridCell.razor.css b/src/Core/Components/DataGrid/FluentDataGridCell.razor.css index cf9625a55..46f2c311b 100644 --- a/src/Core/Components/DataGrid/FluentDataGridCell.razor.css +++ b/src/Core/Components/DataGrid/FluentDataGridCell.razor.css @@ -17,7 +17,7 @@ td.col-justify-center { td.col-justify-end, td.col-justify-right { text-align: end; - padding-inline-end: calc(var(--design-unit) * 7px); + padding-inline-end: calc(var(--design-unit) * 4px); } td.grid-cell-placeholder:after { @@ -94,10 +94,21 @@ td.grid-cell-placeholder:after { text-overflow: ellipsis; } -.col-justify-end ::deep .col-sort-button::part(control) { +.col-justify-center ::deep .col-sort-button::part(control), +.col-justify-center ::deep .col-title { + justify-content: center; +} + +.col-justify-end ::deep .col-sort-button::part(control), +.col-justify-end ::deep .col-title { justify-content: end; } +.col-justify-end ::deep .col-title { + padding-inline-end: 0 !important; +} + + .col-justify-end ::deep .col-sort-button::part(start) { margin-inline-end: 0 !important; } @@ -106,3 +117,5 @@ td.grid-cell-placeholder:after { .col-justify-center ::deep .col-sort-button::part(end) { margin-inline-start: 0 !important; } + + diff --git a/src/Core/Events/EventHandlers.cs b/src/Core/Events/EventHandlers.cs index 43ce21a03..b27aee787 100644 --- a/src/Core/Events/EventHandlers.cs +++ b/src/Core/Events/EventHandlers.cs @@ -14,8 +14,6 @@ namespace Microsoft.FluentUI.AspNetCore.Components; [EventHandler("onmenuchange", typeof(MenuChangeEventArgs), enableStopPropagation: true, enablePreventDefault: true)] [EventHandler("onscrollstart", typeof(HorizontalScrollEventArgs), enableStopPropagation: true, enablePreventDefault: true)] [EventHandler("onscrollend", typeof(HorizontalScrollEventArgs), enableStopPropagation: true, enablePreventDefault: true)] -//[EventHandler("oncellfocus", typeof(DataGridCellFocusEventArgs), enableStopPropagation: true, enablePreventDefault: true)] -//[EventHandler("onrowfocus", typeof(DataGridRowFocusEventArgs), enableStopPropagation: true, enablePreventDefault: true)] [EventHandler("onclosecolumnoptions", typeof(EventArgs), enableStopPropagation: true, enablePreventDefault: true)] [EventHandler("onclosecolumnresize", typeof(EventArgs), enableStopPropagation: true, enablePreventDefault: true)] [EventHandler("ontooltipdismiss", typeof(EventArgs), enableStopPropagation: true, enablePreventDefault: true)] From dd494cef7731f50c9777a40122c77a850df5e79c Mon Sep 17 00:00:00 2001 From: Vincent Baaij Date: Wed, 4 Sep 2024 17:21:47 +0200 Subject: [PATCH 05/39] - Redo AutoFit based on table-layout - Clean up CSS, commented code/apply code styles - revert `.col-header` rename (back to `.column-header) to have less breaking changes - Fix some samples --- .../DataGrid/Examples/DataGridAutoFit.razor | 2 +- .../Examples/DataGridTableScrollbars.razor | 2 +- .../DataGrid/Examples/DataGridTypical.razor | 4 +- examples/Demo/Shared/wwwroot/css/site.css | 2 +- .../DataGrid/Columns/SelectColumn.cs | 1 - .../Components/DataGrid/FluentDataGrid.razor | 15 +++++--- .../DataGrid/FluentDataGrid.razor.cs | 24 ++++-------- .../DataGrid/FluentDataGrid.razor.css | 1 - .../DataGrid/FluentDataGrid.razor.js | 37 ++++++------------- .../DataGrid/FluentDataGridCell.razor.cs | 2 +- .../DataGrid/FluentDataGridCell.razor.css | 23 +++--------- .../DataGrid/FluentDataGridRow.razor.css | 4 +- 12 files changed, 42 insertions(+), 75 deletions(-) diff --git a/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridAutoFit.razor b/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridAutoFit.razor index c3bf9a049..2ff7d08f3 100644 --- a/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridAutoFit.razor +++ b/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridAutoFit.razor @@ -3,7 +3,7 @@

With auto-fit

- + diff --git a/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTableScrollbars.razor b/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTableScrollbars.razor index 13fe3ab17..0958218f1 100644 --- a/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTableScrollbars.razor +++ b/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTableScrollbars.razor @@ -3,7 +3,7 @@ - +
diff --git a/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTypical.razor b/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTypical.razor index db302ed49..d00956f22 100644 --- a/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTypical.razor +++ b/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTypical.razor @@ -3,10 +3,10 @@

To test set ResizeType on the DataGrid to either DataGridResizeType.Discrete or DataGridResizeType.Exact

Remove the parameter completely to get the original behavior

-
+
fluent-data-grid-cell { + .highlighted-row > td { color: var(--neutral-fill-inverse-rest); } diff --git a/src/Core/Components/DataGrid/Columns/SelectColumn.cs b/src/Core/Components/DataGrid/Columns/SelectColumn.cs index 97d6cde06..6a6292fd5 100644 --- a/src/Core/Components/DataGrid/Columns/SelectColumn.cs +++ b/src/Core/Components/DataGrid/Columns/SelectColumn.cs @@ -413,7 +413,6 @@ private RenderFragment GetHeaderContent() builder.AddAttribute(3, "OnClick", EventCallback.Factory.Create(this, OnClickAllAsync)); builder.AddAttribute(4, "onkeydown", EventCallback.Factory.Create(this, OnKeyAllAsync)); } - //builder.AddAttribute(5, "Style", "margin-left: 12px;"); builder.AddAttribute(5, "Title", iconAllChecked == IconIndeterminate ? TitleAllIndeterminate : (iconAllChecked == GetIcon(true) ? TitleAllChecked : TitleAllUnchecked)); diff --git a/src/Core/Components/DataGrid/FluentDataGrid.razor b/src/Core/Components/DataGrid/FluentDataGrid.razor index f9dc885cb..1c88c2a45 100644 --- a/src/Core/Components/DataGrid/FluentDataGrid.razor +++ b/src/Core/Components/DataGrid/FluentDataGrid.razor @@ -20,7 +20,7 @@ @_renderColumnHeaders @@ -152,13 +154,14 @@ else col.ShowSortIcon = false; - + @key="@col" + scope="col" + TGridItem="TGridItem" + aria-sort="@AriaSortValue(col)">
@col.HeaderContent @if (col == _displayOptionsForColumn) @@ -195,7 +198,7 @@ return; } - + @if (EmptyContent is null) { diff --git a/src/Core/Components/DataGrid/FluentDataGrid.razor.cs b/src/Core/Components/DataGrid/FluentDataGrid.razor.cs index 21c79369d..383e6de19 100644 --- a/src/Core/Components/DataGrid/FluentDataGrid.razor.cs +++ b/src/Core/Components/DataGrid/FluentDataGrid.razor.cs @@ -332,14 +332,6 @@ protected override void OnInitialized() /// protected override Task OnParametersSetAsync() { - if (AutoFit) - { - _internalGridTemplateColumns = "auto-fit"; - } - else - { - _internalGridTemplateColumns = GridTemplateColumns; - } // The associated pagination state may have been added/removed/replaced _currentPageItemsChanged.SubscribeOrMove(Pagination?.CurrentPageItemsChanged); @@ -383,11 +375,6 @@ protected override async Task OnAfterRenderAsync(bool firstRender) { Console.WriteLine("[FluentDataGrid] " + ex.Message); } - - if (AutoFit && _gridReference is not null) - { - _ = Module?.InvokeVoidAsync("autoFitGridColumns", _gridReference, _columns.Count).AsTask(); - } } if (_checkColumnOptionsPosition && _displayOptionsForColumn is not null) @@ -674,6 +661,12 @@ private string AriaSortValue(ColumnBase column) ? (_sortByAscending ? "ascending" : "descending") : "none"; + private string? StyleValue => new StyleBuilder(Style) + .AddStyle("table-layout", AutoFit ? "auto" : "fixed") + .AddStyle("width", "fit-content", when: AutoFit ) + .Build(); + + private string? ColumnHeaderClass(ColumnBase column) { return new CssBuilder(Class) @@ -689,7 +682,6 @@ private string AriaSortValue(ColumnBase column) return new CssBuilder("fluent-data-grid") .AddClass(Class) .AddClass("loading", _pendingDataLoadCancellationTokenSource is not null) - .AddClass("auto-fit", AutoFit) .Build(); } @@ -719,12 +711,12 @@ public async ValueTask DisposeAsync() if (_jsEventDisposable is not null) { await _jsEventDisposable.InvokeVoidAsync("stop"); - await _jsEventDisposable.DisposeAsync(); + await _jsEventDisposable.DisposeAsync().ConfigureAwait(false); } if (Module is not null) { - await Module.DisposeAsync(); + await Module.DisposeAsync().ConfigureAwait(false); } } catch (Exception ex) when (ex is JSDisconnectedException || diff --git a/src/Core/Components/DataGrid/FluentDataGrid.razor.css b/src/Core/Components/DataGrid/FluentDataGrid.razor.css index 26ae78f05..42a70b8e0 100644 --- a/src/Core/Components/DataGrid/FluentDataGrid.razor.css +++ b/src/Core/Components/DataGrid/FluentDataGrid.razor.css @@ -1,5 +1,4 @@ .fluent-data-grid { - table-layout: fixed; border-spacing: 0; width: 100%; } diff --git a/src/Core/Components/DataGrid/FluentDataGrid.razor.js b/src/Core/Components/DataGrid/FluentDataGrid.razor.js index 6d01fc21a..a151277cf 100644 --- a/src/Core/Components/DataGrid/FluentDataGrid.razor.js +++ b/src/Core/Components/DataGrid/FluentDataGrid.razor.js @@ -6,7 +6,7 @@ export function init(gridElement) { return; }; - if (gridElement.querySelectorAll('.col-header.resizable').length > 0) { + if (gridElement.querySelectorAll('.column-header.resizable').length > 0) { initialColumnsWidths[gridElement.id] = gridElement.gridTemplateColumns ; enableColumnResizing(gridElement); } @@ -167,7 +167,7 @@ export function enableColumnResizing(gridElement) { let headerBeingResized; let resizeHandle; - gridElement.querySelectorAll('.col-header.resizable').forEach(header => { + gridElement.querySelectorAll('.column-header.resizable').forEach(header => { columns.push({ header }); const onPointerMove = (e) => requestAnimationFrame(() => { if (!headerBeingResized) { @@ -232,7 +232,7 @@ export function resetColumnWidths(gridElement) { export function resizeColumnDiscrete(gridElement, column, change) { - let headers = gridElement.querySelectorAll('.col-header.resizable'); + let headers = gridElement.querySelectorAll('.column-header.resizable'); if (headers.length <= 0) { return } @@ -240,13 +240,13 @@ export function resizeColumnDiscrete(gridElement, column, change) { let headerBeingResized; if (!column) { - if (!(document.activeElement.classList.contains("col-header") && document.activeElement.classList.contains("resizable"))) { + if (!(document.activeElement.classList.contains("column-header") && document.activeElement.classList.contains("resizable"))) { return; } headerBeingResized = document.activeElement; } else { - headerBeingResized = gridElement.querySelector('.col-header[grid-column="' + column + '"]'); + headerBeingResized = gridElement.querySelector('.column-header[data-col-index="' + column + '"]'); } const columns = []; @@ -264,6 +264,7 @@ export function resizeColumnDiscrete(gridElement, column, change) { else { header.size = width + 'px'; } + headerBeingResized.style.width = header.size; } else { if (header.size === undefined) { @@ -272,6 +273,7 @@ export function resizeColumnDiscrete(gridElement, column, change) { } else { header.size = header.clientWidth + 'px'; } + header.style.width = header.size; } } @@ -283,33 +285,14 @@ export function resizeColumnDiscrete(gridElement, column, change) { .join(' '); } -export function autoFitGridColumns(gridElement, columnCount) { - let gridTemplateColumns = ''; - - for (var i = 0; i < columnCount; i++) { - const columnWidths = Array - .from(gridElement.querySelectorAll(`[grid-column="${i + 1}"]`)) - .flatMap((x) => x.offsetWidth); - - const maxColumnWidth = Math.max(...columnWidths); - - gridTemplateColumns += ` ${maxColumnWidth}fr`; - } - - gridElement.setAttribute("grid-template-columns", gridTemplateColumns); - gridElement.classList.remove("auto-fit"); - - initialColumnsWidths[gridElement.id] = gridTemplateColumns; -} - export function resizeColumnExact(gridElement, column, width) { - let headers = gridElement.querySelectorAll('.col-header.resizable'); + let headers = gridElement.querySelectorAll('.column-header.resizable'); if (headers.length <= 0) { return } - let headerBeingResized = gridElement.querySelector('.col-header[grid-column="' + column + '"]'); + let headerBeingResized = gridElement.querySelector('.column-header[data-col-index="' + column + '"]'); if (!headerBeingResized) { return; } @@ -324,6 +307,8 @@ export function resizeColumnExact(gridElement, column, width) { const newWidth = width; header.size = Math.max(min, newWidth) + 'px'; + + headerBeingResized.style.width = header.size } else { if (header.size === undefined) { diff --git a/src/Core/Components/DataGrid/FluentDataGridCell.razor.cs b/src/Core/Components/DataGrid/FluentDataGridCell.razor.cs index 862b6a1e6..2f0879fc8 100644 --- a/src/Core/Components/DataGrid/FluentDataGridCell.razor.cs +++ b/src/Core/Components/DataGrid/FluentDataGridCell.razor.cs @@ -56,7 +56,7 @@ public partial class FluentDataGridCell : FluentComponentBase private ColumnBase? Column => Owner.Owner.Grid._columns.ElementAtOrDefault(GridColumn - 1); protected string? ClassValue => new CssBuilder(Class) - .AddClass("col-header", when: CellType == DataGridCellType.ColumnHeader) + .AddClass("column-header", when: CellType == DataGridCellType.ColumnHeader) .Build(); protected string? StyleValue => new StyleBuilder(Style) diff --git a/src/Core/Components/DataGrid/FluentDataGridCell.razor.css b/src/Core/Components/DataGrid/FluentDataGridCell.razor.css index 46f2c311b..79be7634b 100644 --- a/src/Core/Components/DataGrid/FluentDataGridCell.razor.css +++ b/src/Core/Components/DataGrid/FluentDataGridCell.razor.css @@ -1,7 +1,3 @@ -fluent-data-grid-cell { - text-overflow: ellipsis; -} - tbody > tr > td { padding-left: 0.8rem; overflow:hidden; @@ -17,7 +13,7 @@ td.col-justify-center { td.col-justify-end, td.col-justify-right { text-align: end; - padding-inline-end: calc(var(--design-unit) * 4px); + padding-inline-end: calc(var(--design-unit) * 7px); } td.grid-cell-placeholder:after { @@ -31,13 +27,6 @@ td.grid-cell-placeholder:after { text-align: center; } - -.auto-fit fluent-data-grid-cell { - text-overflow: unset; - overflow: visible; - visibility: hidden; -} - .multiline-text { white-space: inherit; overflow: auto; @@ -48,26 +37,26 @@ td.grid-cell-placeholder:after { display: flex; } -.col-header { +.column-header { position:relative; width: 100%; padding: calc((var(--design-unit) + var(--focus-stroke-width) - var(--stroke-width)) * 1px) 1px calc((var(--design-unit) + var(--focus-stroke-width) - var(--stroke-width)) * 1px); } - .col-header ::deep .keycapture { + .column-header ::deep .keycapture { display: flex; flex-grow: 1; padding-inline-end: calc(var(--design-unit) * 1px); } - .col-header ::deep .col-sort-container, - .col-header ::deep .col-sort-button { + .column-header ::deep .col-sort-container, + .column-header ::deep .col-sort-button { display: flex; flex-grow: 1; } - .col-header ::deep .col-sort-button::part(content) { + .column-header ::deep .col-sort-button::part(content) { overflow: hidden; text-overflow: ellipsis; } diff --git a/src/Core/Components/DataGrid/FluentDataGridRow.razor.css b/src/Core/Components/DataGrid/FluentDataGridRow.razor.css index e2108c3da..0dc9bf4f1 100644 --- a/src/Core/Components/DataGrid/FluentDataGridRow.razor.css +++ b/src/Core/Components/DataGrid/FluentDataGridRow.razor.css @@ -7,8 +7,8 @@ z-index: 3; } -.hover:not([row-type='header'],[row-type='sticky-header'] -,.loading-content-row):hover { +.hover:not([row-type='header'],[row-type='sticky-header'], +.loading-content-row):hover { cursor: pointer; background-color: var(--datagrid-hover-color, var(--neutral-fill-stealth-hover)); } From c371bddc647985dd19fd254ef4d4a4be324f83fb Mon Sep 17 00:00:00 2001 From: Vincent Baaij Date: Wed, 4 Sep 2024 22:35:04 +0200 Subject: [PATCH 06/39] - CSS cleanup --- .../DataGrid/Columns/ColumnBase.razor.css | 11 +++++++++++ .../DataGrid/FluentDataGrid.razor.css | 5 ----- .../DataGrid/FluentDataGridCell.razor.css | 18 ------------------ 3 files changed, 11 insertions(+), 23 deletions(-) diff --git a/src/Core/Components/DataGrid/Columns/ColumnBase.razor.css b/src/Core/Components/DataGrid/Columns/ColumnBase.razor.css index 438e982fe..ee42fe5d5 100644 --- a/src/Core/Components/DataGrid/Columns/ColumnBase.razor.css +++ b/src/Core/Components/DataGrid/Columns/ColumnBase.razor.css @@ -1,7 +1,18 @@ +/* Contains the title text and sort indicator, and expands to fill as much of the col width as it can */ +.col-title { + padding: 0.4rem 0.8rem !important; + min-width: 0; + display: flex; + flex-grow: 1; + align-items: center; + font-weight: 600 !important; + user-select: none; +} /* We put the column title text in its own element primarily so that it can use text-overflow: ellipsis */ .col-title-text { text-overflow: ellipsis; overflow: hidden; white-space: nowrap; + font-weight: 600; } diff --git a/src/Core/Components/DataGrid/FluentDataGrid.razor.css b/src/Core/Components/DataGrid/FluentDataGrid.razor.css index 42a70b8e0..4e83c1d7d 100644 --- a/src/Core/Components/DataGrid/FluentDataGrid.razor.css +++ b/src/Core/Components/DataGrid/FluentDataGrid.razor.css @@ -3,11 +3,6 @@ width: 100%; } -::deep .col-title { - font-weight: 600 !important; - padding: 0.4rem 0.8rem !important; -} - ::deep tr { border-bottom: calc(var(--stroke-width)* 1px) solid var(--neutral-stroke-divider-rest); height: 34px; diff --git a/src/Core/Components/DataGrid/FluentDataGridCell.razor.css b/src/Core/Components/DataGrid/FluentDataGridCell.razor.css index 79be7634b..cff8d4888 100644 --- a/src/Core/Components/DataGrid/FluentDataGridCell.razor.css +++ b/src/Core/Components/DataGrid/FluentDataGridCell.razor.css @@ -61,21 +61,6 @@ td.grid-cell-placeholder:after { text-overflow: ellipsis; } -::deep .col-title { - padding: 0 calc((12 + (var(--design-unit) * 2 * var(--density))) * 1px); - display: flex; - align-items: center; - flex-grow: 1; - user-select: none; -} - -::deep .col-title-text { - text-overflow: ellipsis; - overflow: hidden; - white-space: nowrap; - font-weight: 600; -} - .col-justify-start ::deep .col-sort-button::part(control) { align-items: center; justify-content: start; @@ -93,9 +78,6 @@ td.grid-cell-placeholder:after { justify-content: end; } -.col-justify-end ::deep .col-title { - padding-inline-end: 0 !important; -} .col-justify-end ::deep .col-sort-button::part(start) { From f8f4f0c740586d7a8643e4b0f77e4531368c1f0a Mon Sep 17 00:00:00 2001 From: Vincent Baaij Date: Thu, 5 Sep 2024 17:16:20 +0200 Subject: [PATCH 07/39] - Remove commented code - Fix resize reset - Make size related methods public - Make GridTemplateColumns work again --- .../DataGrid/Examples/DataGridTypical.razor | 11 ++++---- .../Components/DataGrid/FluentDataGrid.razor | 13 +-------- .../DataGrid/FluentDataGrid.razor.cs | 27 ++++++++++++------- .../DataGrid/FluentDataGrid.razor.js | 23 ++++++++++++---- .../DataGrid/FluentDataGridCell.razor.cs | 1 - .../DataGrid/FluentDataGridRow.razor.cs | 1 - 6 files changed, 43 insertions(+), 33 deletions(-) diff --git a/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTypical.razor b/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTypical.razor index d00956f22..22f5a7c0d 100644 --- a/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTypical.razor +++ b/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTypical.razor @@ -7,11 +7,12 @@ - + Flag of @(context.Code) @@ -21,10 +22,10 @@
- - - - + + + +
diff --git a/src/Core/Components/DataGrid/FluentDataGrid.razor b/src/Core/Components/DataGrid/FluentDataGrid.razor index 1c88c2a45..18375d158 100644 --- a/src/Core/Components/DataGrid/FluentDataGrid.razor +++ b/src/Core/Components/DataGrid/FluentDataGrid.razor @@ -37,9 +37,6 @@ @_renderColumnHeaders - @* - @_renderColumnHeaders - *@ }
@if (Loading) @@ -104,7 +101,6 @@ var rowStyle = RowStyle?.Invoke(item) ?? null; Loading = false; - // @for (var colIndex = 0; colIndex < _columns.Count; colIndex++) { @@ -112,34 +108,27 @@ string? tooltip = col.Tooltip ? @col.RawCellContent(item) : null; - // } - // } private void RenderPlaceholderRow(RenderTreeBuilder __builder, PlaceholderContext placeholderContext) { string? _rowsDataSize = $"height: {ItemSize}px"; - // @for (var colIndex = 0; colIndex < _columns.Count; colIndex++) { var col = _columns[colIndex]; - // } - // } private void RenderColumnHeaders(RenderTreeBuilder __builder) @@ -157,7 +146,7 @@ : FluentComponentBase, IHandleEve private readonly RenderFragment _renderEmptyContent; private readonly RenderFragment _renderLoadingContent; - private string? _internalGridTemplateColumns; + private string?[] _internalGridTemplateColumns =[]; // We try to minimize the number of times we query the items provider, since queries may be expensive // We only re-query when the developer calls RefreshDataAsync, or if we know something's changed, such @@ -332,6 +332,10 @@ protected override void OnInitialized() /// protected override Task OnParametersSetAsync() { + if (GridTemplateColumns is not null) + { + _internalGridTemplateColumns = GridTemplateColumns.Split(' '); + } // The associated pagination state may have been added/removed/replaced _currentPageItemsChanged.SubscribeOrMove(Pagination?.CurrentPageItemsChanged); @@ -422,9 +426,9 @@ private void FinishCollectingColumns() throw new Exception("You can use either the 'GridTemplateColumns' parameter on the grid or the 'Width' property at the column level, not both."); } - if (string.IsNullOrWhiteSpace(_internalGridTemplateColumns) && _columns.Any(x => !string.IsNullOrWhiteSpace(x.Width))) + if (_internalGridTemplateColumns.Any() && _columns.Any(x => !string.IsNullOrWhiteSpace(x.Width))) { - _internalGridTemplateColumns = string.Join(" ", _columns.Select(x => x.Width ?? "1fr")); + _internalGridTemplateColumns = _columns.Select(x => x.Width ?? "auto").ToArray(); } if (ResizableColumns) @@ -685,7 +689,7 @@ private string AriaSortValue(ColumnBase column) .Build(); } - private static string? ColumnJustifyClass(ColumnBase column) + private string? ColumnJustifyClass(ColumnBase column) { return new CssBuilder(column.Class) .AddClass("col-justify-start", column.Align == Align.Start) @@ -694,10 +698,15 @@ private string AriaSortValue(ColumnBase column) .Build(); } - private static string? ColumnStyle(ColumnBase column) + private string? ColumnStyle(ColumnBase column, int index) { + var w = "auto"; + if (_internalGridTemplateColumns.Count() > 0 && index < _internalGridTemplateColumns.Count()) + { + w = _internalGridTemplateColumns[index]; + } return new StyleBuilder(column.Style) - .AddStyle("width", column.Width, column.Width is not null ) + .AddStyle("width", column.Width ?? w) .Build(); } @@ -770,7 +779,7 @@ public async Task OnKeyDownAsync(FluentKeyCodeEventArgs args) //return Task.CompletedTask; } - internal async Task SetColumnWidthDiscreteAsync(int? columnIndex, float widthChange) + public async Task SetColumnWidthDiscreteAsync(int? columnIndex, float widthChange) { if (_gridReference is not null && Module is not null) { @@ -778,7 +787,7 @@ internal async Task SetColumnWidthDiscreteAsync(int? columnIndex, float widthCha } } - internal async Task SetColumnWidthExactAsync(int columnIndex, int width) + public async Task SetColumnWidthExactAsync(int columnIndex, int width) { if (_gridReference is not null && Module is not null) { @@ -786,7 +795,7 @@ internal async Task SetColumnWidthExactAsync(int columnIndex, int width) } } - internal async Task ResetColumnWidthsAsync() + public async Task ResetColumnWidthsAsync() { if (_gridReference is not null && Module is not null) { diff --git a/src/Core/Components/DataGrid/FluentDataGrid.razor.js b/src/Core/Components/DataGrid/FluentDataGrid.razor.js index a151277cf..fbb97279b 100644 --- a/src/Core/Components/DataGrid/FluentDataGrid.razor.js +++ b/src/Core/Components/DataGrid/FluentDataGrid.razor.js @@ -7,7 +7,14 @@ export function init(gridElement) { }; if (gridElement.querySelectorAll('.column-header.resizable').length > 0) { - initialColumnsWidths[gridElement.id] = gridElement.gridTemplateColumns ; + if (gridElement.gridTemplateColumns) { + initialColumnsWidths[gridElement.id] = gridElement.gridTemplateColumns; + } + else { + const columns = Array.from(gridElement.querySelectorAll('.column-header')); + initialColumnsWidths[gridElement.id] = columns.map(column => column.getBoundingClientRect().width + 'px'); + gridElement.gridTemplateColumns = initialColumnsWidths[gridElement.id]; + } enableColumnResizing(gridElement); } @@ -181,7 +188,6 @@ export function enableColumnResizing(gridElement) { const width = pointerLocalLeft - headerLocalLeft; const column = columns.find(({ header }) => header === headerBeingResized); - //min = header.querySelector('.col-options-button') ? 100 : 75; column.size = Math.max(min, width) + 'px'; headerBeingResized.style.width = column.size; @@ -226,8 +232,14 @@ export function enableColumnResizing(gridElement) { } export function resetColumnWidths(gridElement) { + const columnsWidths = initialColumnsWidths[gridElement.id]; - gridElement.gridTemplateColumns = initialColumnsWidths[gridElement.id]; + if (columnsWidths) { + const columns = Array.from(gridElement.querySelectorAll('.column-header')); + columns.forEach((column, index) => { + column.style.width = columnsWidths[index]; + }); + } } export function resizeColumnDiscrete(gridElement, column, change) { @@ -240,10 +252,11 @@ export function resizeColumnDiscrete(gridElement, column, change) { let headerBeingResized; if (!column) { - if (!(document.activeElement.classList.contains("column-header") && document.activeElement.classList.contains("resizable"))) { + const targetElement = document.activeElement.parentElement.parentElement.parentElement.parentElement; + if (!(targetElement.classList.contains("column-header") && targetElement.classList.contains("resizable"))) { return; } - headerBeingResized = document.activeElement; + headerBeingResized = targetElement; } else { headerBeingResized = gridElement.querySelector('.column-header[data-col-index="' + column + '"]'); diff --git a/src/Core/Components/DataGrid/FluentDataGridCell.razor.cs b/src/Core/Components/DataGrid/FluentDataGridCell.razor.cs index 2f0879fc8..ab3a00205 100644 --- a/src/Core/Components/DataGrid/FluentDataGridCell.razor.cs +++ b/src/Core/Components/DataGrid/FluentDataGridCell.razor.cs @@ -61,7 +61,6 @@ public partial class FluentDataGridCell : FluentComponentBase protected string? StyleValue => new StyleBuilder(Style) .AddStyle("height", $"{GridContext.Grid.ItemSize:0}px", () => !GridContext.Grid.Loading && GridContext.Grid.Virtualize && Owner.RowType == DataGridRowType.Default) - //.AddStyle("text-align-content", "center", () => !GridContext.Grid.Loading && GridContext.Grid.Virtualize && Owner.RowType == DataGridRowType.Default && string.IsNullOrEmpty(Style)) .Build(); protected override void OnInitialized() diff --git a/src/Core/Components/DataGrid/FluentDataGridRow.razor.cs b/src/Core/Components/DataGrid/FluentDataGridRow.razor.cs index 4e4461327..d469a9050 100644 --- a/src/Core/Components/DataGrid/FluentDataGridRow.razor.cs +++ b/src/Core/Components/DataGrid/FluentDataGridRow.razor.cs @@ -65,7 +65,6 @@ public partial class FluentDataGridRow : FluentComponentBase, IHandle protected string? StyleValue => new StyleBuilder(Style) .AddStyle("height", $"{Owner.Grid.ItemSize:0}px", () => Owner.Grid.Virtualize && RowType == DataGridRowType.Default) .AddStyle("height", "100%", () => (!Owner.Grid.Virtualize || Owner.Rows.Count == 0) && Owner.Grid.Loading && RowType == DataGridRowType.Default) - //.AddStyle("text-align", "center", () => Owner.Grid.Virtualize && RowType == DataGridRowType.Default && string.IsNullOrEmpty(Style)) .Build(); protected override void OnInitialized() From 2c7f5651a710a6e3a17b6b41b9b6e970e9cc6585 Mon Sep 17 00:00:00 2001 From: Vincent Baaij Date: Thu, 5 Sep 2024 17:18:08 +0200 Subject: [PATCH 08/39] Update version --- Directory.Build.props | 4 ++-- eng/pipelines/version.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index c5bb2ced4..b8d7c4b84 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -12,8 +12,8 @@ $(MSBuildThisFileDirectory) true - 4.10.0 - 4.10.0 + 4.11.0 + 4.11.0 $(VersionFile) $(VersionFile) diff --git a/eng/pipelines/version.yml b/eng/pipelines/version.yml index 5779153e2..f4c8a26d6 100644 --- a/eng/pipelines/version.yml +++ b/eng/pipelines/version.yml @@ -2,5 +2,5 @@ variables: # File and Package version # dev branch: 1.2.4-Preview-23282-1' (PackageSuffix is always ignored in Dev branch) # main branch: 1.2.4-RC.1' (PackageSuffix is ignored, if empty, in Main branch) - FileVersion: '4.10.0' # Set the next final version here. + FileVersion: '4.11.0' # Set the next final version here. PackageSuffix: '' From 6dbfb8503fb3296c8c725c46ec15628fc2c0538d Mon Sep 17 00:00:00 2001 From: Vincent Baaij Date: Thu, 5 Sep 2024 21:15:30 +0200 Subject: [PATCH 09/39] - Fix verified files for DataGrid tests --- .github/workflows/build-core-lib.yml | 2 +- .../DataGrid/FluentDataGrid.razor.cs | 3 +- ...yColumnIndex_Ascending.verified.razor.html | 76 ++++++++------ ...ColumnIndex_Descending.verified.razor.html | 76 ++++++++------ ...yColumnTitle_Ascending.verified.razor.html | 72 ++++++++------ ...ColumnTitle_Descending.verified.razor.html | 76 ++++++++------ ...t_Customized_Rendering.verified.razor.html | 62 +++++++----- ..._MultiSelect_Rendering.verified.razor.html | 98 +++++++++++-------- ...SingleSelect_Rendering.verified.razor.html | 86 +++++++++------- ...luentUI.AspNetCore.Components.Tests.csproj | 2 +- 10 files changed, 327 insertions(+), 226 deletions(-) diff --git a/.github/workflows/build-core-lib.yml b/.github/workflows/build-core-lib.yml index 6337448a3..ff4283633 100644 --- a/.github/workflows/build-core-lib.yml +++ b/.github/workflows/build-core-lib.yml @@ -126,7 +126,7 @@ jobs: - name: Report Generator uses: danielpalme/ReportGenerator-GitHub-Action@5.2.4 with: - reports: '**/coverage.net8.0.cobertura.xml;**/coverage.net9.0.cobertura.xml' + reports: '**/coverage.cobertura.xml;**/coverage.net8.0.cobertura.xml;**/coverage.net9.0.cobertura.xml' targetdir: 'CoverageReports' title: 'Unit Tests Code Coverage' classfilters: '-Microsoft.FluentUI.AspNetCore.Components.DesignTokens.*' diff --git a/src/Core/Components/DataGrid/FluentDataGrid.razor.cs b/src/Core/Components/DataGrid/FluentDataGrid.razor.cs index 796715e44..980f97eb1 100644 --- a/src/Core/Components/DataGrid/FluentDataGrid.razor.cs +++ b/src/Core/Components/DataGrid/FluentDataGrid.razor.cs @@ -249,7 +249,9 @@ public partial class FluentDataGrid : FluentComponentBase, IHandleEve /// /// Gets the first (optional) SelectColumn /// +#pragma warning disable CA2021 // Do not call Enumerable.Cast or Enumerable.OfType with incompatible types internal IEnumerable> SelectColumns => _columns.OfType>(); +#pragma warning restore CA2021 // Do not call Enumerable.Cast or Enumerable.OfType with incompatible types private ElementReference? _gridReference; private Virtualize<(int, TGridItem)>? _virtualizeComponent; @@ -670,7 +672,6 @@ private string AriaSortValue(ColumnBase column) .AddStyle("width", "fit-content", when: AutoFit ) .Build(); - private string? ColumnHeaderClass(ColumnBase column) { return new CssBuilder(Class) diff --git a/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnIndex_Ascending.verified.razor.html b/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnIndex_Ascending.verified.razor.html index 54e3b7df6..84c1fbf0a 100644 --- a/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnIndex_Ascending.verified.razor.html +++ b/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnIndex_Ascending.verified.razor.html @@ -1,31 +1,47 @@ - - - -
-
Item1
-
-
- -
-
Item2
-
-
-
- - A - D - - - B - C - - - C - B - - - D - A - -
\ No newline at end of file +
@((RenderFragment)(__builder => col.CellContent(__builder, item))) - //
@((RenderFragment)(__builder => col.RenderPlaceholderContent(__builder, placeholderContext))) - //
+ + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+
Item1
+
+
+
+
+
+
+ + +
+
Item2
+
+
+
+
+
AD
BC
CB
DA
\ No newline at end of file diff --git a/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnIndex_Descending.verified.razor.html b/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnIndex_Descending.verified.razor.html index 7c988e149..1394de78e 100644 --- a/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnIndex_Descending.verified.razor.html +++ b/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnIndex_Descending.verified.razor.html @@ -1,31 +1,47 @@ - - - -
-
Item1
-
-
- -
-
Item2
-
-
-
- - D - A - - - C - B - - - B - C - - - A - D - -
\ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+
Item1
+
+
+
+
+
+
+ + +
+
Item2
+
+
+
+
+
DA
CB
BC
AD
\ No newline at end of file diff --git a/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnTitle_Ascending.verified.razor.html b/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnTitle_Ascending.verified.razor.html index 07643b861..84c1fbf0a 100644 --- a/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnTitle_Ascending.verified.razor.html +++ b/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnTitle_Ascending.verified.razor.html @@ -1,31 +1,47 @@ - - - -
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
Item1
-
- - -
+
+
+
+
+
+
+ + +
Item2
-
- - - - A - D - - - B - C - - - C - B - - - D - A - - +
+ + + +
AD
BC
CB
DA
\ No newline at end of file diff --git a/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnTitle_Descending.verified.razor.html b/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnTitle_Descending.verified.razor.html index 7c988e149..1394de78e 100644 --- a/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnTitle_Descending.verified.razor.html +++ b/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnTitle_Descending.verified.razor.html @@ -1,31 +1,47 @@ - - - -
-
Item1
-
-
- -
-
Item2
-
-
-
- - D - A - - - C - B - - - B - C - - - A - D - -
\ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+
Item1
+
+
+
+
+
+
+ + +
+
Item2
+
+
+
+
+
DA
CB
BC
AD
\ No newline at end of file diff --git a/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_MultiSelect_Customized_Rendering.verified.razor.html b/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_MultiSelect_Customized_Rendering.verified.razor.html index 7179d1af2..a10f03691 100644 --- a/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_MultiSelect_Customized_Rendering.verified.razor.html +++ b/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_MultiSelect_Customized_Rendering.verified.razor.html @@ -1,26 +1,38 @@ - - - -
-
- -
-
Name
-
-
-
- - - - Jean Martin - - - - Kenji Sato - - - - Julie Smith - -
\ No newline at end of file + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+
+ + +
+
Name
+
+
+
+
+
+ Jean Martin
Kenji Sato
Julie Smith
\ No newline at end of file diff --git a/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_MultiSelect_Rendering.verified.razor.html b/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_MultiSelect_Rendering.verified.razor.html index 87edd83d2..b8c21b760 100644 --- a/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_MultiSelect_Rendering.verified.razor.html +++ b/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_MultiSelect_Rendering.verified.razor.html @@ -1,44 +1,56 @@ - - - - - - -
-
Name
-
-
-
- - - - - Jean Martin - - - - - - Kenji Sato - - - - - - Julie Smith - -
\ No newline at end of file + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+
+ + +
+
Name
+
+
+
+
+
+ + Jean Martin
+ + Kenji Sato
+ + Julie Smith
\ No newline at end of file diff --git a/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_SingleSelect_Rendering.verified.razor.html b/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_SingleSelect_Rendering.verified.razor.html index a2b8b67e5..340bcbbdd 100644 --- a/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_SingleSelect_Rendering.verified.razor.html +++ b/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_SingleSelect_Rendering.verified.razor.html @@ -1,38 +1,50 @@ - - - - -
-
Name
-
-
-
- - - - - Jean Martin - - - - - - Kenji Sato - - - - - - Julie Smith - -
+ + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ + +
+
Name
+
+
+
+
+
+ + Jean Martin
+ + Kenji Sato
+ + Julie Smith
\ No newline at end of file diff --git a/tests/Core/Microsoft.FluentUI.AspNetCore.Components.Tests.csproj b/tests/Core/Microsoft.FluentUI.AspNetCore.Components.Tests.csproj index f017eb8fc..d2828bf0f 100644 --- a/tests/Core/Microsoft.FluentUI.AspNetCore.Components.Tests.csproj +++ b/tests/Core/Microsoft.FluentUI.AspNetCore.Components.Tests.csproj @@ -1,7 +1,7 @@ - net8.0;net9.0 + net9.0 enable enable latest From 41e8026a6f9094f0e1ff6711591b20daebcfd1ab Mon Sep 17 00:00:00 2001 From: Vincent Baaij Date: Tue, 10 Sep 2024 13:08:27 +0200 Subject: [PATCH 10/39] - Script optimization - Take resize handler out of button --- .../DataGrid/Examples/DataGridTypical.razor | 6 +- .../Columns/ColumnResizeOptions.razor | 1 + .../Components/DataGrid/FluentDataGrid.razor | 8 +- .../DataGrid/FluentDataGrid.razor.cs | 4 +- .../DataGrid/FluentDataGrid.razor.css | 28 +- .../DataGrid/FluentDataGrid.razor.js | 265 +++++++----------- .../DataGrid/FluentDataGridCell.razor | 3 +- .../DataGrid/FluentDataGridCell.razor.cs | 1 + .../DataGrid/FluentDataGridCell.razor.css | 9 +- .../DataGrid/FluentDataGridRow.razor | 1 + 10 files changed, 141 insertions(+), 185 deletions(-) diff --git a/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTypical.razor b/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTypical.razor index 22f5a7c0d..1d5dace56 100644 --- a/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTypical.razor +++ b/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTypical.razor @@ -3,11 +3,11 @@

To test set ResizeType on the DataGrid to either DataGridResizeType.Discrete or DataGridResizeType.Exact

Remove the parameter completely to get the original behavior

-
+
diff --git a/src/Core/Components/DataGrid/FluentDataGrid.razor b/src/Core/Components/DataGrid/FluentDataGrid.razor index 18375d158..68a6a7834 100644 --- a/src/Core/Components/DataGrid/FluentDataGrid.razor +++ b/src/Core/Components/DataGrid/FluentDataGrid.razor @@ -171,11 +171,11 @@
} - @if (ResizableColumns) - { - - }
+ @if (ResizableColumns) + { + + } } } diff --git a/src/Core/Components/DataGrid/FluentDataGrid.razor.cs b/src/Core/Components/DataGrid/FluentDataGrid.razor.cs index 980f97eb1..9fe060b6f 100644 --- a/src/Core/Components/DataGrid/FluentDataGrid.razor.cs +++ b/src/Core/Components/DataGrid/FluentDataGrid.razor.cs @@ -668,8 +668,10 @@ private string AriaSortValue(ColumnBase column) : "none"; private string? StyleValue => new StyleBuilder(Style) - .AddStyle("table-layout", AutoFit ? "auto" : "fixed") + //.AddStyle("table-layout", AutoFit ? "auto" : "fixed") .AddStyle("width", "fit-content", when: AutoFit ) + .AddStyle("grid-template-columns", GridTemplateColumns) + .AddStyle("grid-auto-rows", "44px") //TODO: Implment Size parameter (44 (Default), 32 (Smaal), 23 (Extra Small)) .Build(); private string? ColumnHeaderClass(ColumnBase column) diff --git a/src/Core/Components/DataGrid/FluentDataGrid.razor.css b/src/Core/Components/DataGrid/FluentDataGrid.razor.css index 4e83c1d7d..01023ff4d 100644 --- a/src/Core/Components/DataGrid/FluentDataGrid.razor.css +++ b/src/Core/Components/DataGrid/FluentDataGrid.razor.css @@ -1,17 +1,20 @@ .fluent-data-grid { - border-spacing: 0; - width: 100%; + width: auto; + flex: 1; + display: grid; + border-collapse: collapse; + align-items: center; + height: max-content; } -::deep tr { - border-bottom: calc(var(--stroke-width)* 1px) solid var(--neutral-stroke-divider-rest); - height: 34px; +thead, +tbody +{ + display:contents; } -tbody > tr > td { - white-space: nowrap; - padding-left: 0.8rem; - text-overflow: ellipsis; +::deep tr { + display: contents; } .fluent-data-grid tbody tr .hover { @@ -28,6 +31,7 @@ tbody > tr > td { border-radius: 0.3rem; box-shadow: 0 3px 8px 1px var(--neutral-layer-4); padding: 1rem; + visibility: hidden; z-index: 1; } @@ -56,7 +60,11 @@ tbody > tr > td { align-items: center; } -::deep .col-width-draghandle { +::deep .resize-handle { + position: absolute; + top: 0; + right: 0; + bottom: 0; height: 34px; cursor: col-resize; margin-left: calc(var(--design-unit) * 2px); diff --git a/src/Core/Components/DataGrid/FluentDataGrid.razor.js b/src/Core/Components/DataGrid/FluentDataGrid.razor.js index fbb97279b..d2d109b82 100644 --- a/src/Core/Components/DataGrid/FluentDataGrid.razor.js +++ b/src/Core/Components/DataGrid/FluentDataGrid.razor.js @@ -1,22 +1,13 @@ -let initialColumnsWidths = {}; var latestGridElement = null; +let grids = []; +const minWidth = 100; export function init(gridElement) { if (gridElement === undefined || gridElement === null) { return; }; - if (gridElement.querySelectorAll('.column-header.resizable').length > 0) { - if (gridElement.gridTemplateColumns) { - initialColumnsWidths[gridElement.id] = gridElement.gridTemplateColumns; - } - else { - const columns = Array.from(gridElement.querySelectorAll('.column-header')); - initialColumnsWidths[gridElement.id] = columns.map(column => column.getBoundingClientRect().width + 'px'); - gridElement.gridTemplateColumns = initialColumnsWidths[gridElement.id]; - } - enableColumnResizing(gridElement); - } + enableColumnResizing(gridElement); const bodyClickHandler = event => { const columnOptionsElement = gridElement?.querySelector('.col-options'); @@ -89,74 +80,24 @@ export function init(gridElement) { document.body.removeEventListener('click', bodyClickHandler); document.body.removeEventListener('mousedown', bodyClickHandler); document.body.removeEventListener('keydown', keyDownHandler); - delete initialColumnsWidths[gridElement.id]; + delete grids[gridElement]; } }; } -export function checkColumnOptionsPosition(gridElement) { - const colOptions = gridElement?._rowElements[0] && gridElement?.querySelector('.col-options'); // Only match within *our* thead, not nested tables - if (colOptions) { - // We want the options popup to be positioned over the grid, not overflowing on either side, because it's possible that - // beyond either side is off-screen or outside the scroll range of an ancestor - const gridRect = gridElement.getBoundingClientRect(); - const optionsRect = colOptions.getBoundingClientRect(); - const leftOverhang = Math.max(0, gridRect.left - optionsRect.left); - const rightOverhang = Math.max(0, optionsRect.right - gridRect.right); - if (leftOverhang || rightOverhang) { - // In the unlikely event that it overhangs both sides, we'll center it - const applyOffset = leftOverhang && rightOverhang ? (leftOverhang - rightOverhang) / 2 : (leftOverhang - rightOverhang); - colOptions.style.transform = `translateX(${applyOffset}px)`; - } - - colOptions.scrollIntoViewIfNeeded(); - - const autoFocusElem = colOptions.querySelector('[autofocus]'); - if (autoFocusElem) { - autoFocusElem.focus(); - } - } -} - -export function checkColumnResizePosition(gridElement) { - const colOptions = gridElement?._rowElements[0] && gridElement?.querySelector('.col-resize'); // Only match within *our* thead, not nested tables - if (colResize) { - // We want the options popup to be positioned over the grid, not overflowing on either side, because it's possible that - // beyond either side is off-screen or outside the scroll range of an ancestor - const gridRect = gridElement.getBoundingClientRect(); - const resizeRect = colResize.getBoundingClientRect(); - const leftOverhang = Math.max(0, gridRect.left - resizeRect.left); - const rightOverhang = Math.max(0, resizeRect.right - gridRect.right); - if (leftOverhang || rightOverhang) { - // In the unlikely event that it overhangs both sides, we'll center it - const applyOffset = leftOverhang && rightOverhang ? (leftOverhang - rightOverhang) / 2 : (leftOverhang - rightOverhang); - colResize.style.transform = `translateX(${applyOffset}px)`; - } - - colResize.scrollIntoViewIfNeeded(); - - const autoFocusElem = colResize.querySelector('[autofocus]'); - if (autoFocusElem) { - autoFocusElem.focus(); - } - } -} - export function checkColumnPopupPosition(gridElement, selector) { - const colPopup = gridElement?._rowElements[0] && gridElement?.querySelector(selector); // Only match within *our* thead, not nested tables + const colPopup = gridElement.querySelector(selector); if (colPopup) { - // We want the options popup to be positioned over the grid, not overflowing on either side, because it's possible that - // beyond either side is off-screen or outside the scroll range of an ancestor const gridRect = gridElement.getBoundingClientRect(); const popupRect = colPopup.getBoundingClientRect(); const leftOverhang = Math.max(0, gridRect.left - popupRect.left); const rightOverhang = Math.max(0, popupRect.right - gridRect.right); if (leftOverhang || rightOverhang) { - // In the unlikely event that it overhangs both sides, we'll center it const applyOffset = leftOverhang && rightOverhang ? (leftOverhang - rightOverhang) / 2 : (leftOverhang - rightOverhang); colPopup.style.transform = `translateX(${applyOffset}px)`; } + colPopup.style.visibility = 'visible'; colPopup.scrollIntoViewIfNeeded(); const autoFocusElem = colPopup.querySelector('[autofocus]'); @@ -165,93 +106,123 @@ export function checkColumnPopupPosition(gridElement, selector) { } } } + export function enableColumnResizing(gridElement) { + const columns = []; + let headerBeingResized; + if (gridElement === latestGridElement) return; latestGridElement = gridElement; - const columns = []; - let min = 75; - let headerBeingResized; - let resizeHandle; - gridElement.querySelectorAll('.column-header.resizable').forEach(header => { - columns.push({ header }); + const headers = gridElement.querySelectorAll('.column-header.resizable'); + + if (headers.length === 0) { + return; + } + + headers.forEach(header => { + columns.push({ + header, + size: `minmax(${minWidth}px,1fr)`, + }); + const onPointerMove = (e) => requestAnimationFrame(() => { if (!headerBeingResized) { return; } - const gridLeft = gridElement.getBoundingClientRect().left; - const headerLocalLeft = headerBeingResized.getBoundingClientRect().left - gridLeft; - const pointerLocalLeft = e.clientX - gridLeft; - - const width = pointerLocalLeft - headerLocalLeft; + const horizontalScrollOffset = document.documentElement.scrollLeft; + const width = (horizontalScrollOffset + e.clientX) - headerBeingResized.offsetLeft; const column = columns.find(({ header }) => header === headerBeingResized); + column.size = Math.max(minWidth, width) + 'px'; - column.size = Math.max(min, width) + 'px'; - headerBeingResized.style.width = column.size; - - // Set initial sizes columns.forEach((column) => { - if (column.size === undefined) { - if (column.header.clientWidth === undefined || column.header.clientWidth === 0) { - column.size = '50px'; - } else { - column.size = column.header.clientWidth + 'px'; - } + if (column.size.startsWith('minmax')) { + column.size = parseInt(column.header.clientWidth, 10) + 'px'; } }); - gridElement.gridTemplateColumns = columns + gridElement.style.gridTemplateColumns = columns .map(({ size }) => size) .join(' '); }); - const onPointerUp = () => { - headerBeingResized = undefined; - resizeHandle = undefined; + const onPointerUp = (e) => { + window.removeEventListener('pointermove', onPointerMove); + window.removeEventListener('pointerup', onPointerUp); + window.removeEventListener('pointercancel', onPointerUp); + window.removeEventListener('pointerleave', onPointerUp); + + headerBeingResized.classList.remove('header--being-resized'); + headerBeingResized = null; + + if (e.target.hasPointerCapture(e.pointerId)) { + e.target.releasePointerCapture(e.pointerId); + } }; const initResize = ({ target, pointerId }) => { - resizeHandle = target; - headerBeingResized = target.parentNode.parentNode; + headerBeingResized = target.parentNode; + headerBeingResized.classList.add('header--being-resized'); - resizeHandle.setPointerCapture(pointerId); + window.addEventListener('pointermove', onPointerMove); + window.addEventListener('pointerup', onPointerUp); + window.addEventListener('pointercancel', onPointerUp); + window.addEventListener('pointerleave', onPointerUp); + + target.setPointerCapture(pointerId); }; - const dragHandle = header.querySelector('.col-width-draghandle'); - if (dragHandle) { - dragHandle.addEventListener('pointerdown', initResize); - dragHandle.addEventListener('pointermove', onPointerMove); - dragHandle.addEventListener('pointerup', onPointerUp); - dragHandle.addEventListener('pointercancel', onPointerUp); - dragHandle.addEventListener('pointerleave', onPointerUp); - } + header.querySelector('.resize-handle').addEventListener('pointerdown', initResize); + + }); + + let initialWidths; + if (gridElement.style.gridTemplateColumns) { + initialWidths = gridElement.style.gridTemplateColumns; + } + else { + initialWidths = columns + .map(({ header, size }) => size) + .join(' '); + + gridElement.style.gridTemplateColumns = initialWidths; + } + + let id = gridElement.id; + grids.push({ + id, + columns, + initialWidths }); } export function resetColumnWidths(gridElement) { - const columnsWidths = initialColumnsWidths[gridElement.id]; - if (columnsWidths) { - const columns = Array.from(gridElement.querySelectorAll('.column-header')); - columns.forEach((column, index) => { - column.style.width = columnsWidths[index]; - }); + const grid = grids.find(({ id }) => id === gridElement.id); + if (!grid) { + return; } + + const columnsWidths = grid.initialWidths.split(' '); + + grid.columns.forEach((column, index) => { + column.size = columnsWidths[index]; + }); + + gridElement.style.gridTemplateColumns = grid.initialWidths; + gridElement.dispatchEvent(new CustomEvent('closecolumnresize', { bubbles: true })); + gridElement.focus(); } export function resizeColumnDiscrete(gridElement, column, change) { - let headers = gridElement.querySelectorAll('.column-header.resizable'); - if (headers.length <= 0) { - return - } - + const columns = []; let headerBeingResized; - if (!column) { + if (!column) { const targetElement = document.activeElement.parentElement.parentElement.parentElement.parentElement; if (!(targetElement.classList.contains("column-header") && targetElement.classList.contains("resizable"))) { return; @@ -261,86 +232,52 @@ export function resizeColumnDiscrete(gridElement, column, change) { else { headerBeingResized = gridElement.querySelector('.column-header[data-col-index="' + column + '"]'); } - const columns = []; - let min = 50; - - headers.forEach(header => { - if (header === headerBeingResized) { - min = headerBeingResized.querySelector('.col-options-button') ? 75 : 50; + grids.find(({ id }) => id === gridElement.id).columns.forEach(column => { + if (column.header === headerBeingResized) { const width = headerBeingResized.getBoundingClientRect().width + change; if (change < 0) { - header.size = Math.max(min, width) + 'px'; + column.size = Math.max(minWidth, width) + 'px'; } else { - header.size = width + 'px'; + column.size = width + 'px'; } - headerBeingResized.style.width = header.size; } else { - if (header.size === undefined) { - if (header.clientWidth === undefined || header.clientWidth === 0) { - header.size = min + 'px'; - } else { - header.size = header.clientWidth + 'px'; - } - header.style.width = header.size; + if (column.size.startsWith('minmax')) { + column.size = parseInt(column.header.clientWidth, 10) + 'px'; } } - - columns.push({ header }); + columns.push(column.size); }); - gridElement.gridTemplateColumns = columns - .map(({ header }) => header.size) - .join(' '); + gridElement.style.gridTemplateColumns = columns.join(' '); } export function resizeColumnExact(gridElement, column, width) { - - let headers = gridElement.querySelectorAll('.column-header.resizable'); - if (headers.length <= 0) { - return - } - + const columns = []; let headerBeingResized = gridElement.querySelector('.column-header[data-col-index="' + column + '"]'); + if (!headerBeingResized) { return; } - const columns = []; - - let min = 50; - headers.forEach(header => { - if (header === headerBeingResized) { - min = headerBeingResized.querySelector('.col-options-button') ? 75 : 50; - - const newWidth = width; - - header.size = Math.max(min, newWidth) + 'px'; - - headerBeingResized.style.width = header.size + grids.find(({ id }) => id === gridElement.id).columns.forEach(column => { + if (column.header === headerBeingResized) { + column.size = Math.max(minWidth, width) + 'px'; } else { - if (header.size === undefined) { - if (header.clientWidth === undefined || header.clientWidth === 0) { - header.size = min + 'px'; - } else { - header.size = header.clientWidth + 'px'; - } + if (column.size.startsWith('minmax')) { + column.size = parseInt(column.header.clientWidth, 10) + 'px'; } } - - columns.push({ header }); + columns.push(column.size); }); - gridElement.gridTemplateColumns = columns - .map(({ header }) => header.size) - .join(' '); + gridElement.style.gridTemplateColumns = columns.join(' '); - gridElement.dispatchEvent(new CustomEvent('closecolumnoptions', { bubbles: true })); gridElement.dispatchEvent(new CustomEvent('closecolumnresize', { bubbles: true })); gridElement.focus(); } diff --git a/src/Core/Components/DataGrid/FluentDataGridCell.razor b/src/Core/Components/DataGrid/FluentDataGridCell.razor index e91cfa01d..20ca7a4d7 100644 --- a/src/Core/Components/DataGrid/FluentDataGridCell.razor +++ b/src/Core/Components/DataGrid/FluentDataGridCell.razor @@ -2,11 +2,12 @@ @inherits FluentComponentBase @typeparam TGridItem -@if (CellType == DataGridCellType.Default || CellType == DataGridCellType.RowHeader) +@if (CellType == DataGridCellType.Default) { diff --git a/src/Core/Components/DataGrid/FluentDataGridCell.razor.cs b/src/Core/Components/DataGrid/FluentDataGridCell.razor.cs index ab3a00205..9c96f4bcc 100644 --- a/src/Core/Components/DataGrid/FluentDataGridCell.razor.cs +++ b/src/Core/Components/DataGrid/FluentDataGridCell.razor.cs @@ -60,6 +60,7 @@ public partial class FluentDataGridCell : FluentComponentBase .Build(); protected string? StyleValue => new StyleBuilder(Style) + .AddStyle("grid-column", GridColumn.ToString()) .AddStyle("height", $"{GridContext.Grid.ItemSize:0}px", () => !GridContext.Grid.Loading && GridContext.Grid.Virtualize && Owner.RowType == DataGridRowType.Default) .Build(); diff --git a/src/Core/Components/DataGrid/FluentDataGridCell.razor.css b/src/Core/Components/DataGrid/FluentDataGridCell.razor.css index cff8d4888..b85225d88 100644 --- a/src/Core/Components/DataGrid/FluentDataGridCell.razor.css +++ b/src/Core/Components/DataGrid/FluentDataGridCell.razor.css @@ -1,8 +1,13 @@ -tbody > tr > td { +th, td { + border-bottom: calc(var(--stroke-width)* 1px) solid var(--neutral-stroke-divider-rest); +} + +td { padding-left: 0.8rem; - overflow:hidden; + overflow: hidden; text-overflow: ellipsis; white-space: nowrap; + min-height: 33px; } td.col-justify-center { diff --git a/src/Core/Components/DataGrid/FluentDataGridRow.razor b/src/Core/Components/DataGrid/FluentDataGridRow.razor index 50bbbf793..ab842f60d 100644 --- a/src/Core/Components/DataGrid/FluentDataGridRow.razor +++ b/src/Core/Components/DataGrid/FluentDataGridRow.razor @@ -6,6 +6,7 @@ Date: Thu, 12 Sep 2024 12:11:13 +0200 Subject: [PATCH 11/39] - Rename ShowSortIcon -> IsActiveSortColumn -Update RemoveSortByColumn logic --- .../Components/DataGrid/Columns/ColumnBase.razor | 2 +- .../DataGrid/Columns/ColumnBase.razor.cs | 6 +++--- src/Core/Components/DataGrid/FluentDataGrid.razor | 6 +++--- .../Components/DataGrid/FluentDataGrid.razor.cs | 14 +++++++------- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/Core/Components/DataGrid/Columns/ColumnBase.razor b/src/Core/Components/DataGrid/Columns/ColumnBase.razor index f5448cddc..c37c8fb54 100644 --- a/src/Core/Components/DataGrid/Columns/ColumnBase.razor +++ b/src/Core/Components/DataGrid/Columns/ColumnBase.razor @@ -24,7 +24,7 @@
@Title
- @if (Grid.SortByAscending.HasValue && ShowSortIcon) + @if (Grid.SortByAscending.HasValue && IsActiveSortColumn) { if (Grid.SortByAscending == true) { diff --git a/src/Core/Components/DataGrid/Columns/ColumnBase.razor.cs b/src/Core/Components/DataGrid/Columns/ColumnBase.razor.cs index 26f687888..1574e69e2 100644 --- a/src/Core/Components/DataGrid/Columns/ColumnBase.razor.cs +++ b/src/Core/Components/DataGrid/Columns/ColumnBase.razor.cs @@ -223,7 +223,7 @@ protected void HandleKeyDown(FluentKeyCodeEventArgs e) } } - public bool ShowSortIcon; + public bool IsActiveSortColumn; /// /// Constructs an instance of . @@ -279,12 +279,12 @@ private async Task HandleOptionsMenuKeyDownAsync(KeyboardEventArgs args) private string GetSortOptionText() { - if (Grid.SortByAscending.HasValue && ShowSortIcon) + if (Grid.SortByAscending.HasValue && IsActiveSortColumn) { if (Grid.SortByAscending is true) { return Grid.ColumnSortLabels.SortMenuAscendingLabel; - } + } else { return Grid.ColumnSortLabels.SortMenuDescendingLabel; diff --git a/src/Core/Components/DataGrid/FluentDataGrid.razor b/src/Core/Components/DataGrid/FluentDataGrid.razor index 68a6a7834..bbfb38193 100644 --- a/src/Core/Components/DataGrid/FluentDataGrid.razor +++ b/src/Core/Components/DataGrid/FluentDataGrid.razor @@ -137,11 +137,11 @@ { var col = _columns[colIndex]; var oneBasedIndex = colIndex + 1; - string CellId = Identifier.NewId(); + //string CellId = Identifier.NewId(); if (_sortByColumn == col) - col.ShowSortIcon = true; + col.IsActiveSortColumn = true; else - col.ShowSortIcon = false; + col.IsActiveSortColumn = false; @@ -286,7 +285,7 @@ public partial class FluentDataGrid : FluentComponentBase, IHandleEve private readonly RenderFragment _renderEmptyContent; private readonly RenderFragment _renderLoadingContent; - private string?[] _internalGridTemplateColumns =[]; + private string?[] _internalGridTemplateColumns = []; // We try to minimize the number of times we query the items provider, since queries may be expensive // We only re-query when the developer calls RefreshDataAsync, or if we know something's changed, such @@ -494,10 +493,11 @@ public Task RemoveSortByColumnAsync(ColumnBase column) { _sortByColumn = _internalGridContext.DefaultSortColumn.Column ?? null; _sortByAscending = _internalGridContext.DefaultSortColumn.Direction != SortDirection.Descending; - } - StateHasChanged(); // We want to see the updated sort order in the header, even before the data query is completed - return RefreshDataCoreAsync(); + StateHasChanged(); // We want to see the updated sort order in the header, even before the data query is completed + return RefreshDataCoreAsync(); + } + return Task.CompletedTask; } /// @@ -669,7 +669,7 @@ private string AriaSortValue(ColumnBase column) private string? StyleValue => new StyleBuilder(Style) //.AddStyle("table-layout", AutoFit ? "auto" : "fixed") - .AddStyle("width", "fit-content", when: AutoFit ) + .AddStyle("width", "fit-content", when: AutoFit) .AddStyle("grid-template-columns", GridTemplateColumns) .AddStyle("grid-auto-rows", "44px") //TODO: Implment Size parameter (44 (Default), 32 (Smaal), 23 (Extra Small)) .Build(); From 0e1caccd3c0137ee07e4be0af309b238d23de981 Mon Sep 17 00:00:00 2001 From: Vincent Baaij Date: Sun, 15 Sep 2024 11:15:13 +0200 Subject: [PATCH 12/39] More optimizations and fixes --- ...crosoft.FluentUI.AspNetCore.Components.xml | 45 ++++++++++- ...ataGridNotVirtualizedLoadingAndEmpty.razor | 2 +- .../DataGrid/Examples/DataGridTypical.razor | 2 +- .../Examples/DataGridVirtualize.razor | 2 +- examples/Demo/Shared/wwwroot/css/site.css | 4 +- .../DataGrid/Columns/ColumnBase.razor | 59 +++++++------- .../DataGrid/Columns/ColumnBase.razor.css | 12 ++- .../Components/DataGrid/FluentDataGrid.razor | 21 +++-- .../DataGrid/FluentDataGrid.razor.cs | 47 ++++++----- .../DataGrid/FluentDataGrid.razor.css | 7 +- .../DataGrid/FluentDataGridCell.razor | 1 + .../DataGrid/FluentDataGridCell.razor.cs | 25 ++++-- .../DataGrid/FluentDataGridCell.razor.css | 81 ++++++++++--------- .../DataGrid/FluentDataGridRow.razor.cs | 41 +++++----- .../DataGrid/FluentDataGridRow.razor.css | 13 +-- src/Core/Enums/DataGridRowSize.cs | 34 ++++++++ 16 files changed, 237 insertions(+), 159 deletions(-) create mode 100644 src/Core/Enums/DataGridRowSize.cs diff --git a/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml b/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml index 1feb84b58..838b35cec 100644 --- a/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml +++ b/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml @@ -2079,7 +2079,7 @@ Gets or sets the owning component. - + Gets or sets the owning component @@ -2089,6 +2089,11 @@ Gets a reference to the column that this cell belongs to. + + + Gets a reference to the enclosing . + + @@ -2118,11 +2123,16 @@ Gets or sets the content to be rendered inside the component. - + Gets or sets the owning component + + + Gets a reference to the enclosing . + + @@ -13229,6 +13239,37 @@ Resize datagrid columns by exact pixel values + + + The height of each in a . + Values are in pixels. + + + + + Medium row height (default) + + + + + Small row height + + + + + Smaller row height + + + + + Large row height + + + + + Dynamic row height + + The type of in a . diff --git a/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridNotVirtualizedLoadingAndEmpty.razor b/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridNotVirtualizedLoadingAndEmpty.razor index 6e507dc2b..ffe355d69 100644 --- a/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridNotVirtualizedLoadingAndEmpty.razor +++ b/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridNotVirtualizedLoadingAndEmpty.razor @@ -1,5 +1,5 @@ 
- + diff --git a/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTypical.razor b/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTypical.razor index 1d5dace56..0060d418e 100644 --- a/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTypical.razor +++ b/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTypical.razor @@ -70,7 +70,7 @@ .ThenDescending(x => x.Medals.Silver) .ThenDescending(x => x.Medals.Bronze); - Func rowClass = x => x.Name.StartsWith("A") ? "highlighted-row" : null; + Func rowClass = x => x.Name.StartsWith("A") ? "highlighted" : null; Func rowStyle = x => x.Name.StartsWith("Au") ? "background-color: var(--highlight-bg)" : null; //IQueryable? FilteredItems => items?.Where(x => x.Name.Contains(nameFilter, StringComparison.CurrentCultureIgnoreCase)); diff --git a/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridVirtualize.razor b/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridVirtualize.razor index 2b0e6bdb2..4e2b26ba8 100644 --- a/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridVirtualize.razor +++ b/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridVirtualize.razor @@ -1,5 +1,5 @@ 
- + diff --git a/examples/Demo/Shared/wwwroot/css/site.css b/examples/Demo/Shared/wwwroot/css/site.css index 95cc50c14..fd5e1f57a 100644 --- a/examples/Demo/Shared/wwwroot/css/site.css +++ b/examples/Demo/Shared/wwwroot/css/site.css @@ -203,11 +203,11 @@ code { padding: 5px; } -.highlighted-row { +.highlighted { background-color: var(--accent-stroke-control-active); } - .highlighted-row > td { + .highlighted > td { color: var(--neutral-fill-inverse-rest); } diff --git a/src/Core/Components/DataGrid/Columns/ColumnBase.razor b/src/Core/Components/DataGrid/Columns/ColumnBase.razor index c37c8fb54..66ed3cef7 100644 --- a/src/Core/Components/DataGrid/Columns/ColumnBase.razor +++ b/src/Core/Components/DataGrid/Columns/ColumnBase.razor @@ -17,10 +17,10 @@ { string? tooltip = Tooltip ? Title : null; - - - @if (AnyColumnActionEnabled) - { + + + @if (AnyColumnActionEnabled) + {
@Title
@@ -35,38 +35,35 @@ } } - @if (Grid.ResizeType is not null && ColumnOptions is not null) + @if (ColumnOptions is not null && Filtered.GetValueOrDefault()) { - @if (Filtered.GetValueOrDefault()) - { - - } + } -
+ + } + else + { +
+
@Title
+
+ } + + @if (Sortable.HasValue ? Sortable.Value : IsSortableByDefault()) + { + + @GetSortOptionText() + } - else + @if (Grid.ResizeType is not null && Grid.ResizableColumns) { -
-
@Title
-
+ @Grid.ColumnResizeLabels.ResizeMenu } - - @if (Sortable.HasValue ? Sortable.Value : IsSortableByDefault()) - { - - @GetSortOptionText() - - } - @if (Grid.ResizeType is not null && Grid.ResizableColumns) - { - @Grid.ColumnResizeLabels.ResizeMenu - } - @if (ColumnOptions is not null) - { - @Grid.ColumnOptionsLabels.OptionsMenu - } - -
+ @if (ColumnOptions is not null) + { + @Grid.ColumnOptionsLabels.OptionsMenu + } + +
} } diff --git a/src/Core/Components/DataGrid/Columns/ColumnBase.razor.css b/src/Core/Components/DataGrid/Columns/ColumnBase.razor.css index ee42fe5d5..2525d262a 100644 --- a/src/Core/Components/DataGrid/Columns/ColumnBase.razor.css +++ b/src/Core/Components/DataGrid/Columns/ColumnBase.razor.css @@ -1,18 +1,16 @@ -/* Contains the title text and sort indicator, and expands to fill as much of the col width as it can */ .col-title { padding: 0.4rem 0.8rem !important; - min-width: 0; - display: flex; - flex-grow: 1; - align-items: center; - font-weight: 600 !important; user-select: none; } -/* We put the column title text in its own element primarily so that it can use text-overflow: ellipsis */ .col-title-text { text-overflow: ellipsis; overflow: hidden; white-space: nowrap; font-weight: 600; } + +th.col-justify-center svg { + align-content: center; + text-align:center; +} diff --git a/src/Core/Components/DataGrid/FluentDataGrid.razor b/src/Core/Components/DataGrid/FluentDataGrid.razor index bbfb38193..e2e78f804 100644 --- a/src/Core/Components/DataGrid/FluentDataGrid.razor +++ b/src/Core/Components/DataGrid/FluentDataGrid.razor @@ -32,7 +32,7 @@ { headerType = DataGridRowType.StickyHeader; } - + @_renderColumnHeaders @@ -143,15 +143,14 @@ else col.IsActiveSortColumn = false; - -
+ @col.HeaderContent @if (col == _displayOptionsForColumn) { @@ -171,7 +170,7 @@
} -
+ @if (ResizableColumns) { @@ -187,8 +186,8 @@ return; } - - + + @if (EmptyContent is null) { @("No data to show!") @@ -204,8 +203,8 @@ private void RenderLoadingContent(RenderTreeBuilder __builder) { - - + + @if (LoadingContent is null) { diff --git a/src/Core/Components/DataGrid/FluentDataGrid.razor.cs b/src/Core/Components/DataGrid/FluentDataGrid.razor.cs index c8d1732fd..a0497a099 100644 --- a/src/Core/Components/DataGrid/FluentDataGrid.razor.cs +++ b/src/Core/Components/DataGrid/FluentDataGrid.razor.cs @@ -245,6 +245,9 @@ public partial class FluentDataGrid : FluentComponentBase, IHandleEve [Parameter] public bool AutoFit { get; set; } + [Parameter] + public DataGridRowSize RowSize { get; set; } = DataGridRowSize.Medium; + /// /// Gets the first (optional) SelectColumn /// @@ -670,8 +673,10 @@ private string AriaSortValue(ColumnBase column) private string? StyleValue => new StyleBuilder(Style) //.AddStyle("table-layout", AutoFit ? "auto" : "fixed") .AddStyle("width", "fit-content", when: AutoFit) - .AddStyle("grid-template-columns", GridTemplateColumns) - .AddStyle("grid-auto-rows", "44px") //TODO: Implment Size parameter (44 (Default), 32 (Smaal), 23 (Extra Small)) + .AddStyle("grid-template-columns", GridTemplateColumns, !string.IsNullOrWhiteSpace(GridTemplateColumns)) + .AddStyle("grid-template-rows", "auto 100%", _internalGridContext.Items.Count == 0) + .AddStyle("height", $"calc(100% - {(int)RowSize}px)", _internalGridContext.Items.Count == 0) + //.AddStyle("grid-auto-rows", $"{(int)RowSize}px", !Virtualize ) //TODO: Implment Size parameter (44 (Default), 32 (Smaal), 23 (Extra Small)) .Build(); private string? ColumnHeaderClass(ColumnBase column) @@ -692,7 +697,7 @@ private string AriaSortValue(ColumnBase column) .Build(); } - private string? ColumnJustifyClass(ColumnBase column) + private static string? ColumnJustifyClass(ColumnBase column) { return new CssBuilder(column.Class) .AddClass("col-justify-start", column.Align == Align.Start) @@ -701,25 +706,25 @@ private string AriaSortValue(ColumnBase column) .Build(); } - private string? ColumnStyle(ColumnBase column, int index) - { - var w = "auto"; - if (_internalGridTemplateColumns.Count() > 0 && index < _internalGridTemplateColumns.Count()) - { - w = _internalGridTemplateColumns[index]; - } - return new StyleBuilder(column.Style) - .AddStyle("width", column.Width ?? w) - .Build(); - } + //private string? ColumnStyle(ColumnBase column, int index) + //{ + // var w = "auto"; + // if (_internalGridTemplateColumns.Count() > 0 && index < _internalGridTemplateColumns.Count()) + // { + // w = _internalGridTemplateColumns[index]; + // } + // return new StyleBuilder(column.Style) + // //.AddStyle("width", column.Width ?? w) + // .Build(); + //} /// public async ValueTask DisposeAsync() { _currentPageItemsChanged.Dispose(); - try - { + //try + //{ if (_jsEventDisposable is not null) { await _jsEventDisposable.InvokeVoidAsync("stop"); @@ -730,13 +735,13 @@ public async ValueTask DisposeAsync() { await Module.DisposeAsync().ConfigureAwait(false); } - } - catch (Exception ex) when (ex is JSDisconnectedException || - ex is OperationCanceledException) - { + //} + //catch (Exception ex) when (ex is JSDisconnectedException || + // ex is OperationCanceledException) + //{ // The JSRuntime side may routinely be gone already if the reason we're disposing is that // the client disconnected. This is not an error. - } + //} } private void CloseColumnOptions() diff --git a/src/Core/Components/DataGrid/FluentDataGrid.razor.css b/src/Core/Components/DataGrid/FluentDataGrid.razor.css index 01023ff4d..37e560492 100644 --- a/src/Core/Components/DataGrid/FluentDataGrid.razor.css +++ b/src/Core/Components/DataGrid/FluentDataGrid.razor.css @@ -76,15 +76,12 @@ tbody z-index: 3; } -thead[row-type='sticky-header'] { +::deep tr[row-type='sticky-header'] > th { position: sticky; top: 0; background-color: var(--neutral-fill-stealth-rest); z-index: 2; } -.hover:not([row-type='header'],[row-type='sticky-header'],.loading-content-row):hover { - cursor: pointer; - background-color: var(--datagrid-hover-color, var(--neutral-fill-stealth-hover)); -} + diff --git a/src/Core/Components/DataGrid/FluentDataGridCell.razor b/src/Core/Components/DataGrid/FluentDataGridCell.razor index 20ca7a4d7..ef1e6055e 100644 --- a/src/Core/Components/DataGrid/FluentDataGridCell.razor +++ b/src/Core/Components/DataGrid/FluentDataGridCell.razor @@ -19,6 +19,7 @@ else diff --git a/src/Core/Components/DataGrid/FluentDataGridCell.razor.cs b/src/Core/Components/DataGrid/FluentDataGridCell.razor.cs index 9c96f4bcc..597c117ce 100644 --- a/src/Core/Components/DataGrid/FluentDataGridCell.razor.cs +++ b/src/Core/Components/DataGrid/FluentDataGridCell.razor.cs @@ -48,21 +48,32 @@ public partial class FluentDataGridCell : FluentComponentBase /// Gets or sets the owning component ///
[CascadingParameter] - private InternalGridContext GridContext { get; set; } = default!; + internal InternalGridContext InternalGridContext { get; set; } = default!; /// /// Gets a reference to the column that this cell belongs to. /// - private ColumnBase? Column => Owner.Owner.Grid._columns.ElementAtOrDefault(GridColumn - 1); + private ColumnBase? Column => Grid._columns.ElementAtOrDefault(GridColumn - 1); + + /// + /// Gets a reference to the enclosing . + /// + protected FluentDataGrid Grid => InternalGridContext.Grid; protected string? ClassValue => new CssBuilder(Class) .AddClass("column-header", when: CellType == DataGridCellType.ColumnHeader) + .AddClass(Owner.Class) .Build(); protected string? StyleValue => new StyleBuilder(Style) - .AddStyle("grid-column", GridColumn.ToString()) - .AddStyle("height", $"{GridContext.Grid.ItemSize:0}px", () => !GridContext.Grid.Loading && GridContext.Grid.Virtualize && Owner.RowType == DataGridRowType.Default) - .Build(); + .AddStyle("grid-column", GridColumn.ToString(), () => (!Grid.Loading && Grid.Items is not null) || Grid.Virtualize) + .AddStyle("text-align", "center", Column is SelectColumn) + .AddStyle("align-content", "center", Column is SelectColumn) + .AddStyle("padding-top", "calc(var(--design-unit) * 2.5px)", Column is SelectColumn) + .AddStyle("height", $"{Grid.ItemSize:0}px", () => !Grid.Loading && Grid.Virtualize && Owner.RowType == DataGridRowType.Default) + .AddStyle("height", $"{(int)Grid.RowSize}px", () => !Grid.Loading && !Grid.Virtualize && Grid.Items is not null) + .AddStyle(Owner.Style) + .Build(); protected override void OnInitialized() { @@ -72,9 +83,9 @@ protected override void OnInitialized() /// internal async Task HandleOnCellClickAsync() { - if (GridContext.Grid.OnCellClick.HasDelegate) + if (Grid.OnCellClick.HasDelegate) { - await GridContext.Grid.OnCellClick.InvokeAsync(this); + await Grid.OnCellClick.InvokeAsync(this); } if (Column != null) diff --git a/src/Core/Components/DataGrid/FluentDataGridCell.razor.css b/src/Core/Components/DataGrid/FluentDataGridCell.razor.css index b85225d88..2f44d6178 100644 --- a/src/Core/Components/DataGrid/FluentDataGridCell.razor.css +++ b/src/Core/Components/DataGrid/FluentDataGridCell.razor.css @@ -7,29 +7,32 @@ td { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; - min-height: 33px; + align-content: center; } -td.col-justify-center { - text-align: center; - padding-inline-start: 0; -} -td.col-justify-end, -td.col-justify-right { - text-align: end; - padding-inline-end: calc(var(--design-unit) * 7px); -} + td.col-justify-center { + text-align: center; + padding-inline-start: 0; + } + + td.col-justify-end, + td.col-justify-right { + text-align: end; + padding-inline-end: calc(var(--design-unit) * 7px); + } + + td.grid-cell-placeholder:after { + content: '\2026'; /*horizontal ellipsis*/ + opacity: 0.75; + } -td.grid-cell-placeholder:after { - content: '\2026'; /*horizontal ellipsis*/ - opacity: 0.75; -} .empty-content-cell, .loading-content-cell { font-weight: 600; text-align: center; + height: 100%; } .multiline-text { @@ -40,58 +43,56 @@ td.grid-cell-placeholder:after { ::deep .col-header-content { display: flex; + flex-grow: 1; } .column-header { - position:relative; - width: 100%; + font-weight: 600; + position: relative; padding: calc((var(--design-unit) + var(--focus-stroke-width) - var(--stroke-width)) * 1px) 1px calc((var(--design-unit) + var(--focus-stroke-width) - var(--stroke-width)) * 1px); } - .column-header ::deep .keycapture { - display: flex; - flex-grow: 1; - padding-inline-end: calc(var(--design-unit) * 1px); - } +::deep .col-sort-button { + width: calc(100% - 20px); + overflow: hidden; + text-overflow: ellipsis; +} - .column-header ::deep .col-sort-container, - .column-header ::deep .col-sort-button { - display: flex; - flex-grow: 1; - } - - .column-header ::deep .col-sort-button::part(content) { - overflow: hidden; - text-overflow: ellipsis; - } + ::deep .col-sort-button::part(content) { + overflow: hidden; + } .col-justify-start ::deep .col-sort-button::part(control) { - align-items: center; justify-content: start; overflow: hidden; - text-overflow: ellipsis; } -.col-justify-center ::deep .col-sort-button::part(control), -.col-justify-center ::deep .col-title { +.col-justify-center ::deep .col-sort-button::part(control) { justify-content: center; + overflow: hidden; } -.col-justify-end ::deep .col-sort-button::part(control), -.col-justify-end ::deep .col-title { +.col-justify-end ::deep .col-sort-button::part(control) { justify-content: end; + overflow: hidden; } - .col-justify-end ::deep .col-sort-button::part(start) { - margin-inline-end: 0 !important; + margin-inline-end: 2px; } .col-justify-start ::deep .col-sort-button::part(end), .col-justify-center ::deep .col-sort-button::part(end) { - margin-inline-start: 0 !important; + margin-inline-start: 2px; } +.col-justify-center ::deep .col-title { + text-align: center; +} +.col-justify-end ::deep .col-title { + text-align: end; + margin-inline-end: calc(var(--design-unit) * 4px); +} diff --git a/src/Core/Components/DataGrid/FluentDataGridRow.razor.cs b/src/Core/Components/DataGrid/FluentDataGridRow.razor.cs index d469a9050..736afc6c4 100644 --- a/src/Core/Components/DataGrid/FluentDataGridRow.razor.cs +++ b/src/Core/Components/DataGrid/FluentDataGridRow.razor.cs @@ -56,29 +56,34 @@ public partial class FluentDataGridRow : FluentComponentBase, IHandle /// Gets or sets the owning component /// [CascadingParameter] - internal InternalGridContext Owner { get; set; } = default!; + internal InternalGridContext InternalGridContext { get; set; } = default!; + + /// + /// Gets a reference to the enclosing . + /// + protected FluentDataGrid Grid => InternalGridContext.Grid; protected string? ClassValue => new CssBuilder(Class) - .AddClass("hover", when: Owner.Grid.ShowHover) + .AddClass("hover", when: Grid.ShowHover) .Build(); protected string? StyleValue => new StyleBuilder(Style) - .AddStyle("height", $"{Owner.Grid.ItemSize:0}px", () => Owner.Grid.Virtualize && RowType == DataGridRowType.Default) - .AddStyle("height", "100%", () => (!Owner.Grid.Virtualize || Owner.Rows.Count == 0) && Owner.Grid.Loading && RowType == DataGridRowType.Default) + .AddStyle("height", $"{Grid.ItemSize:0}px", () => Grid.Virtualize && RowType == DataGridRowType.Default) + //.AddStyle("height", "100%", () => (!Grid.Virtualize || InternalGridContext.Rows.Count == 0) && Grid.Loading && RowType == DataGridRowType.Default) .Build(); protected override void OnInitialized() { - RowId = $"r{Owner.GetNextRowId()}"; - Owner.Register(this); + RowId = $"r{InternalGridContext.GetNextRowId()}"; + InternalGridContext.Register(this); } - public void Dispose() => Owner.Unregister(this); + public void Dispose() => InternalGridContext.Unregister(this); internal void Register(FluentDataGridCell cell) { - cell.CellId = $"c{Owner.GetNextCellId()}"; + cell.CellId = $"c{InternalGridContext.GetNextCellId()}"; cells.Add(cell.CellId, cell); } @@ -94,7 +99,7 @@ private async Task HandleOnCellFocusAsync(DataGridCellFocusEventArgs args) { if (cell != null && cell.CellType == DataGridCellType.Default) { - await Owner.Grid.OnCellFocus.InvokeAsync(cell); + await Grid.OnCellFocus.InvokeAsync(cell); } } } @@ -104,14 +109,14 @@ internal async Task HandleOnRowClickAsync(string rowId) { var row = GetRow(rowId); - if (row != null && Owner.Grid.OnRowClick.HasDelegate) + if (row != null && Grid.OnRowClick.HasDelegate) { - await Owner.Grid.OnRowClick.InvokeAsync(row); + await Grid.OnRowClick.InvokeAsync(row); } if (row != null && row.RowType == DataGridRowType.Default) { - foreach (var column in Owner.Grid._columns) + foreach (var column in Grid._columns) { await column.OnRowClickAsync(row); } @@ -122,9 +127,9 @@ internal async Task HandleOnRowClickAsync(string rowId) internal async Task HandleOnRowDoubleClickAsync(string rowId) { var row = GetRow(rowId); - if (row != null && Owner.Grid.OnRowDoubleClick.HasDelegate) + if (row != null && Grid.OnRowDoubleClick.HasDelegate) { - await Owner.Grid.OnRowDoubleClick.InvokeAsync(row); + await Grid.OnRowDoubleClick.InvokeAsync(row); } } @@ -138,14 +143,14 @@ internal async Task HandleOnRowKeyDownAsync(string rowId, KeyboardEventArgs e) var row = GetRow(rowId); - if (row != null && Owner.Grid.OnRowClick.HasDelegate) + if (row != null && Grid.OnRowClick.HasDelegate) { - await Owner.Grid.OnRowClick.InvokeAsync(row); + await Grid.OnRowClick.InvokeAsync(row); } if (row != null && row.RowType == DataGridRowType.Default) { - foreach (var column in Owner.Grid._columns) + foreach (var column in Grid._columns) { await column.OnRowKeyDownAsync(row, e); } @@ -154,7 +159,7 @@ internal async Task HandleOnRowKeyDownAsync(string rowId, KeyboardEventArgs e) private FluentDataGridRow? GetRow(string rowId, Func, bool>? where = null) { - if (!string.IsNullOrEmpty(rowId) && Owner.Rows.TryGetValue(rowId, out var row)) + if (!string.IsNullOrEmpty(rowId) && InternalGridContext.Rows.TryGetValue(rowId, out var row)) { return where == null ? row diff --git a/src/Core/Components/DataGrid/FluentDataGridRow.razor.css b/src/Core/Components/DataGrid/FluentDataGridRow.razor.css index 0dc9bf4f1..071d1c6a0 100644 --- a/src/Core/Components/DataGrid/FluentDataGridRow.razor.css +++ b/src/Core/Components/DataGrid/FluentDataGridRow.razor.css @@ -1,21 +1,10 @@ -.header { - padding: 0; - z-index: 3; -} - .sticky-header { z-index: 3; } -.hover:not([row-type='header'],[row-type='sticky-header'], -.loading-content-row):hover { +.hover:not([row-type='header'],[row-type='sticky-header'],.loading-content-row):hover ::deep td { cursor: pointer; background-color: var(--datagrid-hover-color, var(--neutral-fill-stealth-hover)); } -.empty-content-row, -.loading-content-row { - width: 100%; - height: 100% !important; -} diff --git a/src/Core/Enums/DataGridRowSize.cs b/src/Core/Enums/DataGridRowSize.cs new file mode 100644 index 000000000..733ece387 --- /dev/null +++ b/src/Core/Enums/DataGridRowSize.cs @@ -0,0 +1,34 @@ +namespace Microsoft.FluentUI.AspNetCore.Components; + +/// +/// The height of each in a . +/// Values are in pixels. +/// +public enum DataGridRowSize +{ + + /// + /// Medium row height (default) + /// + Medium = 44, + + /// + /// Small row height + /// + Small = 32, + + /// + /// Smaller row height + /// + Smaller = 24, + + /// + /// Large row height + /// + Large = 58, + + /// + /// Dynamic row height + /// + Dynamic +} From bf7c20d64033df2ee36ecac5dd31cfb09324d9bb Mon Sep 17 00:00:00 2001 From: Vincent Baaij Date: Mon, 16 Sep 2024 23:55:19 +0200 Subject: [PATCH 13/39] - More fine-tunning. - Add `MultiLine` parameter to grid + styling - Make `AutoSize` work again --- .../Shared/Components/ApiDocumentation.razor | 6 +-- .../Shared/Pages/DataGrid/DataGridPage.razor | 2 +- .../Examples/DataGridMultilineText.razor | 6 +-- .../Demo/Shared/Pages/Lab/IssueTester.razor | 2 +- .../DataGrid/Columns/ColumnBase.razor.cs | 2 +- .../DataGrid/FluentDataGrid.razor.cs | 47 +++++++++++++------ .../DataGrid/FluentDataGrid.razor.js | 23 ++++++++- .../DataGrid/FluentDataGridCell.razor | 4 +- .../DataGrid/FluentDataGridCell.razor.cs | 4 +- .../DataGrid/FluentDataGridCell.razor.css | 3 +- 10 files changed, 70 insertions(+), 29 deletions(-) diff --git a/examples/Demo/Shared/Components/ApiDocumentation.razor b/examples/Demo/Shared/Components/ApiDocumentation.razor index f27addbad..11c615da7 100644 --- a/examples/Demo/Shared/Components/ApiDocumentation.razor +++ b/examples/Demo/Shared/Components/ApiDocumentation.razor @@ -26,7 +26,7 @@ string header = Properties.Any(x => x.IsParameter) ? "Parameters" : "Properties";

@header

- + @context.Name @context.Type @@ -82,7 +82,7 @@ {

EventCallbacks

- + @context.Name @@ -98,7 +98,7 @@ {

Methods

- + @context.Name @foreach (var param in @context.Parameters) diff --git a/examples/Demo/Shared/Pages/DataGrid/DataGridPage.razor b/examples/Demo/Shared/Pages/DataGrid/DataGridPage.razor index a0c6b2f6c..f0c350d08 100644 --- a/examples/Demo/Shared/Pages/DataGrid/DataGridPage.razor +++ b/examples/Demo/Shared/Pages/DataGrid/DataGridPage.razor @@ -289,7 +289,7 @@ fluent-data-grid-row:has([row-selected]) { - Example of using the Class parameter to style parts of the grid. Note that the class used in the example (multiline-text) has been added to the FluentDataGridCell css. + Set the grid parameter MultiLine to true when you have cells in your data that will take up more than a single line. diff --git a/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridMultilineText.razor b/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridMultilineText.razor index 89dcc9285..bf68608e0 100644 --- a/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridMultilineText.razor +++ b/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridMultilineText.razor @@ -1,7 +1,7 @@ - + - + @code { @@ -13,4 +13,4 @@ new Person(10944, "António Langa", "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."), new Person(11203, "Julie Smith","Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."), }.AsQueryable(); -} \ No newline at end of file +} diff --git a/examples/Demo/Shared/Pages/Lab/IssueTester.razor b/examples/Demo/Shared/Pages/Lab/IssueTester.razor index 08bef4c23..a43f08b2a 100644 --- a/examples/Demo/Shared/Pages/Lab/IssueTester.razor +++ b/examples/Demo/Shared/Pages/Lab/IssueTester.razor @@ -1,4 +1,4 @@ @page "/issue-tester" @using FluentUI.Demo.Shared.Pages.DataGrid.Examples - + diff --git a/src/Core/Components/DataGrid/Columns/ColumnBase.razor.cs b/src/Core/Components/DataGrid/Columns/ColumnBase.razor.cs index 1574e69e2..5993e4d42 100644 --- a/src/Core/Components/DataGrid/Columns/ColumnBase.razor.cs +++ b/src/Core/Components/DataGrid/Columns/ColumnBase.razor.cs @@ -14,7 +14,7 @@ public abstract partial class ColumnBase { private bool _isMenuOpen; private static readonly string[] KEYBOARD_MENU_SELECT_KEYS = ["Enter", "NumpadEnter"]; - private readonly string _columnId = $"column-header{Identifier.NewId()}"; + private readonly string _columnId = Identifier.NewId(); [CascadingParameter] internal InternalGridContext InternalGridContext { get; set; } = default!; diff --git a/src/Core/Components/DataGrid/FluentDataGrid.razor.cs b/src/Core/Components/DataGrid/FluentDataGrid.razor.cs index a0497a099..3917bef80 100644 --- a/src/Core/Components/DataGrid/FluentDataGrid.razor.cs +++ b/src/Core/Components/DataGrid/FluentDataGrid.razor.cs @@ -248,6 +248,9 @@ public partial class FluentDataGrid : FluentComponentBase, IHandleEve [Parameter] public DataGridRowSize RowSize { get; set; } = DataGridRowSize.Medium; + [Parameter] + public bool MultiLine { get; set; } = false; + /// /// Gets the first (optional) SelectColumn /// @@ -288,7 +291,7 @@ public partial class FluentDataGrid : FluentComponentBase, IHandleEve private readonly RenderFragment _renderEmptyContent; private readonly RenderFragment _renderLoadingContent; - private string?[] _internalGridTemplateColumns = []; + private string? _internalGridTemplateColumns; // We try to minimize the number of times we query the items provider, since queries may be expensive // We only re-query when the developer calls RefreshDataAsync, or if we know something's changed, such @@ -338,7 +341,7 @@ protected override Task OnParametersSetAsync() { if (GridTemplateColumns is not null) { - _internalGridTemplateColumns = GridTemplateColumns.Split(' '); + _internalGridTemplateColumns = GridTemplateColumns; } // The associated pagination state may have been added/removed/replaced @@ -396,6 +399,11 @@ protected override async Task OnAfterRenderAsync(bool firstRender) _checkColumnResizePosition = false; _ = Module?.InvokeVoidAsync("checkColumnPopupPosition", _gridReference, ".col-resize").AsTask(); } + + if (AutoFit && _gridReference is not null) + { + _ = Module?.InvokeVoidAsync("autoFitGridColumns", _gridReference, _columns.Count).AsTask(); + } } // Invoked by descendant columns at a special time during rendering @@ -430,11 +438,21 @@ private void FinishCollectingColumns() throw new Exception("You can use either the 'GridTemplateColumns' parameter on the grid or the 'Width' property at the column level, not both."); } - if (_internalGridTemplateColumns.Any() && _columns.Any(x => !string.IsNullOrWhiteSpace(x.Width))) + if (string.IsNullOrWhiteSpace(_internalGridTemplateColumns)) { - _internalGridTemplateColumns = _columns.Select(x => x.Width ?? "auto").ToArray(); + if (!AutoFit) + { + _internalGridTemplateColumns = string.Join(" ", Enumerable.Repeat("1fr", _columns.Count)); + } + + if (_columns.Any(x => !string.IsNullOrWhiteSpace(x.Width))) + { + _internalGridTemplateColumns = string.Join(" ", _columns.Select(x => x.Width ?? "auto")); + } + } + if (ResizableColumns) { _ = Module?.InvokeVoidAsync("enableColumnResizing", _gridReference).AsTask(); @@ -672,8 +690,9 @@ private string AriaSortValue(ColumnBase column) private string? StyleValue => new StyleBuilder(Style) //.AddStyle("table-layout", AutoFit ? "auto" : "fixed") - .AddStyle("width", "fit-content", when: AutoFit) - .AddStyle("grid-template-columns", GridTemplateColumns, !string.IsNullOrWhiteSpace(GridTemplateColumns)) + //.AddStyle("width", "fit-content", when: AutoFit) + //.AddStyle("grid-template-columns", GridTemplateColumns, !string.IsNullOrWhiteSpace(GridTemplateColumns)) + .AddStyle("grid-template-columns", _internalGridTemplateColumns, !string.IsNullOrWhiteSpace(_internalGridTemplateColumns)) .AddStyle("grid-template-rows", "auto 100%", _internalGridContext.Items.Count == 0) .AddStyle("height", $"calc(100% - {(int)RowSize}px)", _internalGridContext.Items.Count == 0) //.AddStyle("grid-auto-rows", $"{(int)RowSize}px", !Virtualize ) //TODO: Implment Size parameter (44 (Default), 32 (Smaal), 23 (Extra Small)) @@ -690,9 +709,9 @@ private string AriaSortValue(ColumnBase column) private string? GridClass() { - return new CssBuilder("fluent-data-grid") .AddClass(Class) + .AddClass("auto-fit", AutoFit) .AddClass("loading", _pendingDataLoadCancellationTokenSource is not null) .Build(); } @@ -723,8 +742,8 @@ public async ValueTask DisposeAsync() { _currentPageItemsChanged.Dispose(); - //try - //{ + try + { if (_jsEventDisposable is not null) { await _jsEventDisposable.InvokeVoidAsync("stop"); @@ -735,13 +754,13 @@ public async ValueTask DisposeAsync() { await Module.DisposeAsync().ConfigureAwait(false); } - //} - //catch (Exception ex) when (ex is JSDisconnectedException || - // ex is OperationCanceledException) - //{ + } + catch (Exception ex) when (ex is JSDisconnectedException || + ex is OperationCanceledException) + { // The JSRuntime side may routinely be gone already if the reason we're disposing is that // the client disconnected. This is not an error. - //} + } } private void CloseColumnOptions() diff --git a/src/Core/Components/DataGrid/FluentDataGrid.razor.js b/src/Core/Components/DataGrid/FluentDataGrid.razor.js index d2d109b82..133d64da8 100644 --- a/src/Core/Components/DataGrid/FluentDataGrid.razor.js +++ b/src/Core/Components/DataGrid/FluentDataGrid.razor.js @@ -230,7 +230,7 @@ export function resizeColumnDiscrete(gridElement, column, change) { headerBeingResized = targetElement; } else { - headerBeingResized = gridElement.querySelector('.column-header[data-col-index="' + column + '"]'); + headerBeingResized = gridElement.querySelector('.column-header[col-index="' + column + '"]'); } @@ -258,7 +258,7 @@ export function resizeColumnDiscrete(gridElement, column, change) { export function resizeColumnExact(gridElement, column, width) { const columns = []; - let headerBeingResized = gridElement.querySelector('.column-header[data-col-index="' + column + '"]'); + let headerBeingResized = gridElement.querySelector('.column-header[col-index="' + column + '"]'); if (!headerBeingResized) { return; @@ -281,3 +281,22 @@ export function resizeColumnExact(gridElement, column, width) { gridElement.dispatchEvent(new CustomEvent('closecolumnresize', { bubbles: true })); gridElement.focus(); } + +export function autoFitGridColumns(gridElement, columnCount) { + let gridTemplateColumns = ''; + + for (var i = 0; i < columnCount; i++) { + const columnWidths = Array + .from(gridElement.querySelectorAll(`[col-index="${i + 1}"]`)) + .flatMap((x) => x.offsetWidth); + + const maxColumnWidth = Math.max(...columnWidths); + + gridTemplateColumns += ` ${maxColumnWidth}fr`; + } + + gridElement.style.gridTemplateColumns = gridTemplateColumns; + gridElement.classList.remove("auto-fit"); + + grids[gridElement.id] = gridTemplateColumns; +} diff --git a/src/Core/Components/DataGrid/FluentDataGridCell.razor b/src/Core/Components/DataGrid/FluentDataGridCell.razor index ef1e6055e..66afe71e6 100644 --- a/src/Core/Components/DataGrid/FluentDataGridCell.razor +++ b/src/Core/Components/DataGrid/FluentDataGridCell.razor @@ -4,7 +4,7 @@ @if (CellType == DataGridCellType.Default) { - : FluentComponentBase protected string? ClassValue => new CssBuilder(Class) .AddClass("column-header", when: CellType == DataGridCellType.ColumnHeader) + .AddClass("multiline-text", when: Grid.MultiLine) .AddClass(Owner.Class) .Build(); @@ -71,7 +72,8 @@ public partial class FluentDataGridCell : FluentComponentBase .AddStyle("align-content", "center", Column is SelectColumn) .AddStyle("padding-top", "calc(var(--design-unit) * 2.5px)", Column is SelectColumn) .AddStyle("height", $"{Grid.ItemSize:0}px", () => !Grid.Loading && Grid.Virtualize && Owner.RowType == DataGridRowType.Default) - .AddStyle("height", $"{(int)Grid.RowSize}px", () => !Grid.Loading && !Grid.Virtualize && Grid.Items is not null) + .AddStyle("height", $"{(int)Grid.RowSize}px", () => !Grid.Loading && !Grid.Virtualize && Grid.Items is not null && !Grid.MultiLine) + .AddStyle("height", "100%", Grid.MultiLine) .AddStyle(Owner.Style) .Build(); diff --git a/src/Core/Components/DataGrid/FluentDataGridCell.razor.css b/src/Core/Components/DataGrid/FluentDataGridCell.razor.css index 2f44d6178..c670e7aea 100644 --- a/src/Core/Components/DataGrid/FluentDataGridCell.razor.css +++ b/src/Core/Components/DataGrid/FluentDataGridCell.razor.css @@ -3,7 +3,7 @@ th, td { } td { - padding-left: 0.8rem; + padding: calc((var(--design-unit) + var(--focus-stroke-width) - var(--stroke-width))* 1px) calc(((var(--design-unit)* 3) + var(--focus-stroke-width) - var(--stroke-width))* 1px); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; @@ -39,6 +39,7 @@ td { white-space: inherit; overflow: auto; word-break: break-word; + align-content: start; } ::deep .col-header-content { From 3551ef64d5b6612c5d7ba2bc6e45d3374953c06a Mon Sep 17 00:00:00 2001 From: Vincent Baaij Date: Tue, 17 Sep 2024 10:31:33 +0200 Subject: [PATCH 14/39] Fix tests --- ...crosoft.FluentUI.AspNetCore.Components.xml | 2 +- ...yColumnIndex_Ascending.verified.razor.html | 62 ++++++++----------- ...ColumnIndex_Descending.verified.razor.html | 62 ++++++++----------- ...yColumnTitle_Ascending.verified.razor.html | 62 ++++++++----------- ...ColumnTitle_Descending.verified.razor.html | 62 ++++++++----------- ...t_Customized_Rendering.verified.razor.html | 46 ++++++-------- ..._MultiSelect_Rendering.verified.razor.html | 54 +++++++--------- ...SingleSelect_Rendering.verified.razor.html | 44 ++++++------- 8 files changed, 172 insertions(+), 222 deletions(-) diff --git a/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml b/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml index adcc0fead..5a2163fe5 100644 --- a/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml +++ b/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml @@ -8246,7 +8246,7 @@ - + diff --git a/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnIndex_Ascending.verified.razor.html b/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnIndex_Ascending.verified.razor.html index 84c1fbf0a..6fb364d33 100644 --- a/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnIndex_Ascending.verified.razor.html +++ b/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnIndex_Ascending.verified.razor.html @@ -1,47 +1,39 @@ - - - - - - -
-
- - -
-
Item1
-
-
-
-
+ + + + - - - - + + + - - - + + + - - - + + + - - - + + +
+ +
+
Item1
+
+
-
- - -
-
Item2
-
-
-
-
+
+ +
+
Item2
+
+
AD
AD
BC
BC
CB
CB
DA
DA
\ No newline at end of file diff --git a/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnIndex_Descending.verified.razor.html b/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnIndex_Descending.verified.razor.html index 1394de78e..0ad3cf2d6 100644 --- a/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnIndex_Descending.verified.razor.html +++ b/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnIndex_Descending.verified.razor.html @@ -1,47 +1,39 @@ - - - - - - -
-
- - -
-
Item1
-
-
-
-
+ + + + - - - - + + + - - - + + + - - - + + + - - - + + +
+ +
+
Item1
+
+
-
- - -
-
Item2
-
-
-
-
+
+ +
+
Item2
+
+
DA
DA
CB
CB
BC
BC
AD
AD
\ No newline at end of file diff --git a/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnTitle_Ascending.verified.razor.html b/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnTitle_Ascending.verified.razor.html index 84c1fbf0a..6fb364d33 100644 --- a/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnTitle_Ascending.verified.razor.html +++ b/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnTitle_Ascending.verified.razor.html @@ -1,47 +1,39 @@ - - - - - - + - - + + - - + +
-
- - -
-
Item1
-
-
-
-
+ + + + - - - - + + + - - - + + + - - - + + + - - - + + +
+ +
+
Item1
+
+
-
- - -
-
Item2
-
-
-
-
+
+ +
+
Item2
+
+
AD
AD
BC
BC
CB
CB
DA
DA
\ No newline at end of file diff --git a/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnTitle_Descending.verified.razor.html b/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnTitle_Descending.verified.razor.html index 1394de78e..0ad3cf2d6 100644 --- a/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnTitle_Descending.verified.razor.html +++ b/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnTitle_Descending.verified.razor.html @@ -1,47 +1,39 @@ - - - - - - + + - - + + - - + + - - + +
-
- - -
-
Item1
-
-
-
-
+ + + + - - - - + + + - - - + + + - - - + + + - - - + + +
+ +
+
Item1
+
+
-
- - -
-
Item2
-
-
-
-
+
+ +
+
Item2
+
+
DA
DA
CB
CB
BC
BC
AD
AD
\ No newline at end of file diff --git a/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_MultiSelect_Customized_Rendering.verified.razor.html b/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_MultiSelect_Customized_Rendering.verified.razor.html index a10f03691..842eace6d 100644 --- a/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_MultiSelect_Customized_Rendering.verified.razor.html +++ b/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_MultiSelect_Customized_Rendering.verified.razor.html @@ -1,38 +1,32 @@ - - - - - - + + - - + + - - + + - - + +
-
-
-
+ + + + - - - + - + - - - + + + - - - + + +
+
-
- - -
-
Name
-
-
-
-
+
+ +
+
Name
+
+
+
Jean MartinJean Martin
Kenji Sato
Kenji Sato
Julie Smith
Julie Smith
\ No newline at end of file diff --git a/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_MultiSelect_Rendering.verified.razor.html b/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_MultiSelect_Rendering.verified.razor.html index b8c21b760..ad8a02c56 100644 --- a/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_MultiSelect_Rendering.verified.razor.html +++ b/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_MultiSelect_Rendering.verified.razor.html @@ -1,56 +1,50 @@ - - - - - - + + - - + + - - + + - - + +
-
- -
+ + + + - - - + - + - - + - + - - + - +
+ -
- - -
-
Name
-
-
-
-
+
+ +
+
Name
+
+
+
Jean MartinJean Martin
+
Kenji SatoKenji Sato
+
Julie SmithJulie Smith
\ No newline at end of file diff --git a/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_SingleSelect_Rendering.verified.razor.html b/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_SingleSelect_Rendering.verified.razor.html index 340bcbbdd..2852aef82 100644 --- a/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_SingleSelect_Rendering.verified.razor.html +++ b/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_SingleSelect_Rendering.verified.razor.html @@ -1,50 +1,44 @@ - - - - - diff --git a/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnIndex_Descending.verified.razor.html b/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnIndex_Descending.verified.razor.html index 6931328db..2039802ec 100644 --- a/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnIndex_Descending.verified.razor.html +++ b/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnIndex_Descending.verified.razor.html @@ -3,18 +3,14 @@ diff --git a/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnTitle_Ascending.verified.razor.html b/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnTitle_Ascending.verified.razor.html index 1cb800924..c9d018db4 100644 --- a/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnTitle_Ascending.verified.razor.html +++ b/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnTitle_Ascending.verified.razor.html @@ -3,18 +3,14 @@ diff --git a/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnTitle_Descending.verified.razor.html b/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnTitle_Descending.verified.razor.html index 6931328db..2039802ec 100644 --- a/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnTitle_Descending.verified.razor.html +++ b/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnTitle_Descending.verified.razor.html @@ -3,18 +3,14 @@ diff --git a/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_MultiSelect_Customized_Rendering.verified.razor.html b/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_MultiSelect_Customized_Rendering.verified.razor.html index 9f594885d..6b11a2494 100644 --- a/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_MultiSelect_Customized_Rendering.verified.razor.html +++ b/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_MultiSelect_Customized_Rendering.verified.razor.html @@ -6,11 +6,9 @@
diff --git a/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_MultiSelect_Rendering.verified.razor.html b/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_MultiSelect_Rendering.verified.razor.html index 3db2c0a65..ba273c9be 100644 --- a/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_MultiSelect_Rendering.verified.razor.html +++ b/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_MultiSelect_Rendering.verified.razor.html @@ -10,11 +10,9 @@ diff --git a/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_SingleSelect_Rendering.verified.razor.html b/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_SingleSelect_Rendering.verified.razor.html index 7daf17ba7..3bb857790 100644 --- a/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_SingleSelect_Rendering.verified.razor.html +++ b/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_SingleSelect_Rendering.verified.razor.html @@ -4,11 +4,9 @@ From 7060116fe2ac5157402dd9ddbc30dd9bb1c1df45 Mon Sep 17 00:00:00 2001 From: Vincent Baaij Date: Mon, 21 Oct 2024 18:02:18 +0200 Subject: [PATCH 23/39] Fix virtualized grid row height --- .../Pages/DataGrid/Examples/DataGridRemoteData.razor | 9 ++++++++- src/Core/Components/DataGrid/FluentDataGridCell.razor.cs | 4 ++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridRemoteData.razor b/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridRemoteData.razor index a5943a326..d4f478752 100644 --- a/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridRemoteData.razor +++ b/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridRemoteData.razor @@ -4,7 +4,14 @@ @inject NavigationManager NavManager
- + diff --git a/src/Core/Components/DataGrid/FluentDataGridCell.razor.cs b/src/Core/Components/DataGrid/FluentDataGridCell.razor.cs index d1e23d72f..fbbbbd16b 100644 --- a/src/Core/Components/DataGrid/FluentDataGridCell.razor.cs +++ b/src/Core/Components/DataGrid/FluentDataGridCell.razor.cs @@ -73,9 +73,9 @@ public partial class FluentDataGridCell : FluentComponentBase .AddStyle("padding-inline-start", "calc(((var(--design-unit)* 3) + var(--focus-stroke-width) - var(--stroke-width))* 1px)", Column is SelectColumn && Owner.RowType == DataGridRowType.Default) .AddStyle("padding-top", "calc(var(--design-unit) * 2.5px)", Column is SelectColumn && (Grid.RowSize == DataGridRowSize.Medium || Owner.RowType == DataGridRowType.Header)) .AddStyle("padding-top", "calc(var(--design-unit) * 1.5px)", Column is SelectColumn && Grid.RowSize == DataGridRowSize.Small && Owner.RowType == DataGridRowType.Default) - .AddStyle("height", $"{Grid.ItemSize:0}px", () => !Grid.Loading && Grid.Virtualize && Grid.Items is not null && Owner.RowType == DataGridRowType.Default) + .AddStyle("height", $"{Grid.ItemSize:0}px", () => !Grid.Loading && Grid.Virtualize && Owner.RowType == DataGridRowType.Default) .AddStyle("height", $"{(int)Grid.RowSize}px", () => !Grid.Loading && !Grid.Virtualize && Grid.Items is not null && !Grid.MultiLine) - .AddStyle("height", "100%", Grid.MultiLine) + .AddStyle("height", "100%", InternalGridContext.TotalItemCount == 0 || (Grid.Loading && (Grid.MultiLine || Grid.Items is null))) .AddStyle("min-height", "44px", Owner.RowType != DataGridRowType.Default) .AddStyle(Owner.Style) .Build(); From bca8540a71f46643fc839fe616e22d17b6d7a2f2 Mon Sep 17 00:00:00 2001 From: Vincent Baaij Date: Tue, 22 Oct 2024 10:29:20 +0200 Subject: [PATCH 24/39] Fix column resizing when in rtl mode --- examples/Demo/Shared/Pages/Lab/IssueTester.razor | 2 +- src/Core/Components/DataGrid/FluentDataGrid.razor.js | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/examples/Demo/Shared/Pages/Lab/IssueTester.razor b/examples/Demo/Shared/Pages/Lab/IssueTester.razor index 8b1378917..5f282702b 100644 --- a/examples/Demo/Shared/Pages/Lab/IssueTester.razor +++ b/examples/Demo/Shared/Pages/Lab/IssueTester.razor @@ -1 +1 @@ - + \ No newline at end of file diff --git a/src/Core/Components/DataGrid/FluentDataGrid.razor.js b/src/Core/Components/DataGrid/FluentDataGrid.razor.js index 133d64da8..2163cfe81 100644 --- a/src/Core/Components/DataGrid/FluentDataGrid.razor.js +++ b/src/Core/Components/DataGrid/FluentDataGrid.razor.js @@ -133,7 +133,14 @@ export function enableColumnResizing(gridElement) { } const horizontalScrollOffset = document.documentElement.scrollLeft; - const width = (horizontalScrollOffset + e.clientX) - headerBeingResized.offsetLeft; + let width; + + if (document.body.dir === '' || document.body.dir === 'ltr') { + width = (horizontalScrollOffset + e.clientX) - headerBeingResized.offsetLeft; + } + else { + width = headerBeingResized.offsetLeft + headerBeingResized.clientWidth - (horizontalScrollOffset + e.clientX); + } const column = columns.find(({ header }) => header === headerBeingResized); column.size = Math.max(minWidth, width) + 'px'; From 26a1fb0f23e68e367fba623b94c998b4209bfa0d Mon Sep 17 00:00:00 2001 From: Vincent Baaij Date: Tue, 29 Oct 2024 16:31:13 +0100 Subject: [PATCH 25/39] - Fix button width when no filter button - Add tabindex to cells - Fix resize handle pos when rtl -WIP: use cursor keys to go through cells --- .../DataGrid/Columns/ColumnBase.razor | 10 +++- .../DataGrid/FluentDataGrid.razor.css | 6 +++ .../DataGrid/FluentDataGrid.razor.js | 46 ++++++++++++++++++- .../DataGrid/FluentDataGridCell.razor | 1 + 4 files changed, 60 insertions(+), 3 deletions(-) diff --git a/src/Core/Components/DataGrid/Columns/ColumnBase.razor b/src/Core/Components/DataGrid/Columns/ColumnBase.razor index ba7748cee..f188c35e4 100644 --- a/src/Core/Components/DataGrid/Columns/ColumnBase.razor +++ b/src/Core/Components/DataGrid/Columns/ColumnBase.razor @@ -68,6 +68,12 @@ else { string? tooltip = Tooltip ? (HeaderTooltip ?? Title) : null; + string? wdelta = "20px"; + + if (Grid.ResizeType is not null || ColumnOptions is not null) + { + wdelta = "56px"; + } @if (Align == Align.Start || Align == Align.Center) { @@ -87,7 +93,7 @@ @if (Sortable.HasValue ? Sortable.Value : IsSortableByDefault()) { - +
@Title
@if (Grid.SortByAscending.HasValue && IsActiveSortColumn) @@ -110,7 +116,7 @@ } else { - +
@Title
@if (ColumnOptions is not null && Filtered.GetValueOrDefault()) diff --git a/src/Core/Components/DataGrid/FluentDataGrid.razor.css b/src/Core/Components/DataGrid/FluentDataGrid.razor.css index 71dce59ac..1122bec7e 100644 --- a/src/Core/Components/DataGrid/FluentDataGrid.razor.css +++ b/src/Core/Components/DataGrid/FluentDataGrid.razor.css @@ -64,6 +64,7 @@ tbody position: absolute; top: 5px; right: 0; + left: unset; bottom: 0; height: 32px; cursor: col-resize; @@ -71,6 +72,11 @@ tbody width: calc(var(--design-unit) * 1px + 2px); } +[dir=rtl] * ::deep .resize-handle { + left: 0; + right: unset; +} + .header { padding: 0; z-index: 3; diff --git a/src/Core/Components/DataGrid/FluentDataGrid.razor.js b/src/Core/Components/DataGrid/FluentDataGrid.razor.js index d3b654413..e8c698eb0 100644 --- a/src/Core/Components/DataGrid/FluentDataGrid.razor.js +++ b/src/Core/Components/DataGrid/FluentDataGrid.razor.js @@ -1,4 +1,3 @@ -var latestGridElement = null; let grids = []; const minWidth = 100; @@ -9,6 +8,11 @@ export function init(gridElement) { enableColumnResizing(gridElement); + let start = gridElement.querySelector('td:first-child'); + //start.focus(); + //start.style.backgroundColor = '#50b988'; + //start.style.color = 'white'; + const bodyClickHandler = event => { const columnOptionsElement = gridElement?.querySelector('.col-options'); if (columnOptionsElement && event.composedPath().indexOf(columnOptionsElement) < 0) { @@ -19,6 +23,17 @@ export function init(gridElement) { gridElement.dispatchEvent(new CustomEvent('closecolumnresize', { bubbles: true })); } }; + const changeStyle = (sibling) => { + if (sibling !== null) { + start.focus(); + start.style.backgroundColor = ''; + start.style.color = ''; + sibling.focus(); + //sibling.style.backgroundColor = '#50b988'; + //sibling.style.color = 'white'; + start = sibling; + } + } const keyDownHandler = event => { const columnOptionsElement = gridElement?.querySelector('.col-options'); if (columnOptionsElement) { @@ -50,6 +65,35 @@ export function init(gridElement) { } ); } + + if (start) { + const idx = start.cellIndex; + + if (event.key === "ArrowUp") { + // up arrow + const previousRow = start.parentElement.previousElementSibling; + if (previousRow !== null) { + const previousSibling = previousRow.cells[idx]; + changeStyle(previousSibling); + } + } else if (event.key === "ArrowDown") { + // down arrow + const nextRow = start.parentElement.nextElementSibling; + if (nextRow !== null) { + const nextSibling = nextRow.cells[idx]; + changeStyle(nextSibling); + } + } else if (event.key === "ArrowLeft") { + // left arrow + const previousSibling = start.previousElementSibling; + changeStyle(previousSibling); + } else if (event.key === "ArrowRight") { + // right arrow + const nextsibling = start.nextElementSibling; + changeStyle(nextsibling); + } + } + }; const cells = gridElement.querySelectorAll('[role="gridcell"]'); diff --git a/src/Core/Components/DataGrid/FluentDataGridCell.razor b/src/Core/Components/DataGrid/FluentDataGridCell.razor index 66afe71e6..c531716d0 100644 --- a/src/Core/Components/DataGrid/FluentDataGridCell.razor +++ b/src/Core/Components/DataGrid/FluentDataGridCell.razor @@ -8,6 +8,7 @@ class="@ClassValue" style="@StyleValue" role="gridcell" + tabindex="0" @onkeydown="@HandleOnCellKeyDownAsync" @onclick="@HandleOnCellClickAsync" @attributes="AdditionalAttributes"> From 4772f61d3be4ec12d4991f6f0f11e92f936931d6 Mon Sep 17 00:00:00 2001 From: Vincent Baaij Date: Mon, 25 Nov 2024 22:34:58 +0100 Subject: [PATCH 26/39] - Update example, - Update rendering for non button column headee - Fix multiline height issue --- .../Microsoft.FluentUI.AspNetCore.Components.xml | 5 ----- .../Examples/DataGridTemplateColumns2.razor | 8 +++++++- .../Components/DataGrid/Columns/ColumnBase.razor | 14 ++++++-------- .../DataGrid/FluentDataGridCell.razor.cs | 2 +- 4 files changed, 14 insertions(+), 15 deletions(-) diff --git a/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml b/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml index 947cbddc6..c10cfc199 100644 --- a/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml +++ b/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml @@ -2020,11 +2020,6 @@ Gets or sets a value indicating whether the grid should allow multiple lines of text in cells. - - - Gets the first (optional) SelectColumn - - Constructs an instance of . diff --git a/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTemplateColumns2.razor b/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTemplateColumns2.razor index 74c21150e..bdc517129 100644 --- a/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTemplateColumns2.razor +++ b/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTemplateColumns2.razor @@ -1,5 +1,11 @@  - + diff --git a/src/Core/Components/DataGrid/Columns/ColumnBase.razor b/src/Core/Components/DataGrid/Columns/ColumnBase.razor index f188c35e4..469d4f218 100644 --- a/src/Core/Components/DataGrid/Columns/ColumnBase.razor +++ b/src/Core/Components/DataGrid/Columns/ColumnBase.razor @@ -116,15 +116,13 @@ } else { - - +
@Title
- @if (ColumnOptions is not null && Filtered.GetValueOrDefault()) - { - - } - - +
+ @if (ColumnOptions is not null && Filtered.GetValueOrDefault()) + { + + } } @if (Align == Align.End) diff --git a/src/Core/Components/DataGrid/FluentDataGridCell.razor.cs b/src/Core/Components/DataGrid/FluentDataGridCell.razor.cs index fbbbbd16b..27da6e2ca 100644 --- a/src/Core/Components/DataGrid/FluentDataGridCell.razor.cs +++ b/src/Core/Components/DataGrid/FluentDataGridCell.razor.cs @@ -75,7 +75,7 @@ public partial class FluentDataGridCell : FluentComponentBase .AddStyle("padding-top", "calc(var(--design-unit) * 1.5px)", Column is SelectColumn && Grid.RowSize == DataGridRowSize.Small && Owner.RowType == DataGridRowType.Default) .AddStyle("height", $"{Grid.ItemSize:0}px", () => !Grid.Loading && Grid.Virtualize && Owner.RowType == DataGridRowType.Default) .AddStyle("height", $"{(int)Grid.RowSize}px", () => !Grid.Loading && !Grid.Virtualize && Grid.Items is not null && !Grid.MultiLine) - .AddStyle("height", "100%", InternalGridContext.TotalItemCount == 0 || (Grid.Loading && (Grid.MultiLine || Grid.Items is null))) + .AddStyle("height", "100%", InternalGridContext.TotalItemCount == 0 || (Grid.Loading && Grid.Items is null) || Grid.MultiLine) .AddStyle("min-height", "44px", Owner.RowType != DataGridRowType.Default) .AddStyle(Owner.Style) .Build(); From 3004965027b6f07dd42a7acfe87e664fa7083b9a Mon Sep 17 00:00:00 2001 From: Vincent Baaij Date: Mon, 25 Nov 2024 22:42:30 +0100 Subject: [PATCH 27/39] Fix tests --- ...yColumnIndex_Ascending.verified.razor.html | 24 +++++++++---------- ...ColumnIndex_Descending.verified.razor.html | 24 +++++++++---------- ...yColumnTitle_Ascending.verified.razor.html | 24 +++++++++---------- ...ColumnTitle_Descending.verified.razor.html | 24 +++++++++---------- ...t_Customized_Rendering.verified.razor.html | 16 ++++++------- ..._MultiSelect_Rendering.verified.razor.html | 22 ++++++++--------- ...SingleSelect_Rendering.verified.razor.html | 22 ++++++++--------- 7 files changed, 78 insertions(+), 78 deletions(-) diff --git a/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnIndex_Ascending.verified.razor.html b/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnIndex_Ascending.verified.razor.html index c9d018db4..668b64c43 100644 --- a/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnIndex_Ascending.verified.razor.html +++ b/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnIndex_Ascending.verified.razor.html @@ -3,33 +3,33 @@
- - + + - - + + - - + + - - + +
-
-
-
- - -
-
Name
-
-
-
-
+ + + + + - - + - + - - + - + - - + - +
+ +
+
Name
+
+
+
Jean MartinJean Martin
+
Kenji SatoKenji Sato
+
Julie SmithJulie Smith
\ No newline at end of file From c9513777a29cb4c87b64f8becb8d4698a171b405 Mon Sep 17 00:00:00 2001 From: Vincent Baaij Date: Tue, 17 Sep 2024 12:17:25 +0200 Subject: [PATCH 15/39] - Styling updates - Set `RowSize` to small to be equal to v4 default --- .../Microsoft.FluentUI.AspNetCore.Components.xml | 8 ++++---- src/Core/Components/DataGrid/Columns/SelectColumn.cs | 4 ++-- src/Core/Components/DataGrid/FluentDataGrid.razor | 2 +- src/Core/Components/DataGrid/FluentDataGrid.razor.cs | 3 +-- .../Components/DataGrid/FluentDataGridCell.razor.cs | 5 ++++- .../Components/DataGrid/FluentDataGridRow.razor.cs | 2 +- src/Core/Enums/DataGridRowSize.cs | 10 +++++----- 7 files changed, 18 insertions(+), 16 deletions(-) diff --git a/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml b/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml index 5a2163fe5..618dcd265 100644 --- a/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml +++ b/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml @@ -13251,14 +13251,14 @@ Values are in pixels. - + - Medium row height (default) + Small row height (default) - + - Small row height + Medium row height diff --git a/src/Core/Components/DataGrid/Columns/SelectColumn.cs b/src/Core/Components/DataGrid/Columns/SelectColumn.cs index 6a6292fd5..d8a946558 100644 --- a/src/Core/Components/DataGrid/Columns/SelectColumn.cs +++ b/src/Core/Components/DataGrid/Columns/SelectColumn.cs @@ -21,7 +21,7 @@ public class SelectColumn : ColumnBase private readonly Icon IconSelectedSingle = new CoreIcons.Filled.Size20.RadioButton(); private DataGridSelectMode _selectMode = DataGridSelectMode.Single; - private readonly List _selectedItems = new List(); + private readonly List _selectedItems = []; /// /// Initializes a new instance of . @@ -332,7 +332,7 @@ private Icon GetIcon(bool? selected) private async Task KeepOnlyFirstSelectedItemAsync() { - if (_selectedItems.Count() <= 1) + if (_selectedItems.Count <= 1) { return; } diff --git a/src/Core/Components/DataGrid/FluentDataGrid.razor b/src/Core/Components/DataGrid/FluentDataGrid.razor index e2e78f804..fb3a65053 100644 --- a/src/Core/Components/DataGrid/FluentDataGrid.razor +++ b/src/Core/Components/DataGrid/FluentDataGrid.razor @@ -97,7 +97,7 @@ private void RenderRow(RenderTreeBuilder __builder, int rowIndex, TGridItem item) { - var rowClass = (ShowHover ? "hover " : RowClass?.Invoke(item) ?? null)?.TrimEnd(); + var rowClass = RowClass?.Invoke(item) ?? null; var rowStyle = RowStyle?.Invoke(item) ?? null; Loading = false; diff --git a/src/Core/Components/DataGrid/FluentDataGrid.razor.cs b/src/Core/Components/DataGrid/FluentDataGrid.razor.cs index 3917bef80..3562bebce 100644 --- a/src/Core/Components/DataGrid/FluentDataGrid.razor.cs +++ b/src/Core/Components/DataGrid/FluentDataGrid.razor.cs @@ -246,7 +246,7 @@ public partial class FluentDataGrid : FluentComponentBase, IHandleEve public bool AutoFit { get; set; } [Parameter] - public DataGridRowSize RowSize { get; set; } = DataGridRowSize.Medium; + public DataGridRowSize RowSize { get; set; } = DataGridRowSize.Small; [Parameter] public bool MultiLine { get; set; } = false; @@ -452,7 +452,6 @@ private void FinishCollectingColumns() } - if (ResizableColumns) { _ = Module?.InvokeVoidAsync("enableColumnResizing", _gridReference).AsTask(); diff --git a/src/Core/Components/DataGrid/FluentDataGridCell.razor.cs b/src/Core/Components/DataGrid/FluentDataGridCell.razor.cs index 10cd616ec..eb086b35b 100644 --- a/src/Core/Components/DataGrid/FluentDataGridCell.razor.cs +++ b/src/Core/Components/DataGrid/FluentDataGridCell.razor.cs @@ -70,10 +70,13 @@ public partial class FluentDataGridCell : FluentComponentBase .AddStyle("grid-column", GridColumn.ToString(), () => (!Grid.Loading && Grid.Items is not null) || Grid.Virtualize) .AddStyle("text-align", "center", Column is SelectColumn) .AddStyle("align-content", "center", Column is SelectColumn) - .AddStyle("padding-top", "calc(var(--design-unit) * 2.5px)", Column is SelectColumn) + .AddStyle("padding-inline-start", "calc(((var(--design-unit)* 3) + var(--focus-stroke-width) - var(--stroke-width))* 1px)", Column is SelectColumn && Owner.RowType == DataGridRowType.Default) + .AddStyle("padding-top", "calc(var(--design-unit) * 2.5px)", Column is SelectColumn && (Grid.RowSize == DataGridRowSize.Medium || Owner.RowType == DataGridRowType.Header)) + .AddStyle("padding-top", "calc(var(--design-unit) * 1.5px)", Column is SelectColumn && Grid.RowSize == DataGridRowSize.Small && Owner.RowType == DataGridRowType.Default) .AddStyle("height", $"{Grid.ItemSize:0}px", () => !Grid.Loading && Grid.Virtualize && Owner.RowType == DataGridRowType.Default) .AddStyle("height", $"{(int)Grid.RowSize}px", () => !Grid.Loading && !Grid.Virtualize && Grid.Items is not null && !Grid.MultiLine) .AddStyle("height", "100%", Grid.MultiLine) + .AddStyle("min-height", "44px", Owner.RowType != DataGridRowType.Default) .AddStyle(Owner.Style) .Build(); diff --git a/src/Core/Components/DataGrid/FluentDataGridRow.razor.cs b/src/Core/Components/DataGrid/FluentDataGridRow.razor.cs index 736afc6c4..10fb0db41 100644 --- a/src/Core/Components/DataGrid/FluentDataGridRow.razor.cs +++ b/src/Core/Components/DataGrid/FluentDataGridRow.razor.cs @@ -68,7 +68,7 @@ public partial class FluentDataGridRow : FluentComponentBase, IHandle .Build(); protected string? StyleValue => new StyleBuilder(Style) - .AddStyle("height", $"{Grid.ItemSize:0}px", () => Grid.Virtualize && RowType == DataGridRowType.Default) + //.AddStyle("height", $"{Grid.ItemSize:0}px", () => Grid.Virtualize && RowType == DataGridRowType.Default) //.AddStyle("height", "100%", () => (!Grid.Virtualize || InternalGridContext.Rows.Count == 0) && Grid.Loading && RowType == DataGridRowType.Default) .Build(); diff --git a/src/Core/Enums/DataGridRowSize.cs b/src/Core/Enums/DataGridRowSize.cs index 733ece387..28219e7e2 100644 --- a/src/Core/Enums/DataGridRowSize.cs +++ b/src/Core/Enums/DataGridRowSize.cs @@ -6,16 +6,16 @@ namespace Microsoft.FluentUI.AspNetCore.Components; /// public enum DataGridRowSize { - /// - /// Medium row height (default) + /// Small row height (default) /// - Medium = 44, + Small = 32, /// - /// Small row height + /// Medium row height /// - Small = 32, + Medium = 44, + /// /// Smaller row height From 04c0a07191940b7b747ecbcbf2447eb3d8166334 Mon Sep 17 00:00:00 2001 From: Vincent Baaij Date: Tue, 17 Sep 2024 12:20:48 +0200 Subject: [PATCH 16/39] - Don't use dynamic row size for now. - Process review comments --- src/Core/Components/DataGrid/FluentDataGrid.razor.cs | 9 ++++++++- src/Core/Enums/DataGridRowSize.cs | 8 ++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/Core/Components/DataGrid/FluentDataGrid.razor.cs b/src/Core/Components/DataGrid/FluentDataGrid.razor.cs index 3562bebce..b3ed7fd6d 100644 --- a/src/Core/Components/DataGrid/FluentDataGrid.razor.cs +++ b/src/Core/Components/DataGrid/FluentDataGrid.razor.cs @@ -82,7 +82,8 @@ public partial class FluentDataGrid : FluentComponentBase, IHandleEve /// scroll smoothness by rendering more items off-screen, they can also increase initial load times. Finding a balance /// based on your data set size and user experience requirements is recommended. The default value is 3. /// - [Parameter] public int OverscanCount { get; set; } = 3; + [Parameter] + public int OverscanCount { get; set; } = 3; /// /// This is applicable only when using . It defines an expected height in pixels for @@ -245,9 +246,15 @@ public partial class FluentDataGrid : FluentComponentBase, IHandleEve [Parameter] public bool AutoFit { get; set; } + /// + /// Gets or sets the size of each row in the grid based on the enum. + /// [Parameter] public DataGridRowSize RowSize { get; set; } = DataGridRowSize.Small; + /// + /// Gets or sets a value indicating whether the grid should allow multiple lines of text in cells. + /// [Parameter] public bool MultiLine { get; set; } = false; diff --git a/src/Core/Enums/DataGridRowSize.cs b/src/Core/Enums/DataGridRowSize.cs index 28219e7e2..4e1cadce6 100644 --- a/src/Core/Enums/DataGridRowSize.cs +++ b/src/Core/Enums/DataGridRowSize.cs @@ -27,8 +27,8 @@ public enum DataGridRowSize /// Large = 58, - /// - /// Dynamic row height - /// - Dynamic + ///// + ///// Dynamic row height + ///// + //Dynamic } From 36148e92474ceac0579a9d3e710a222aa80b79ae Mon Sep 17 00:00:00 2001 From: Vincent Baaij Date: Tue, 17 Sep 2024 12:33:09 +0200 Subject: [PATCH 17/39] Fix tests --- ...crosoft.FluentUI.AspNetCore.Components.xml | 15 +++++++++----- ...yColumnIndex_Ascending.verified.razor.html | 20 +++++++++---------- ...ColumnIndex_Descending.verified.razor.html | 20 +++++++++---------- ...yColumnTitle_Ascending.verified.razor.html | 20 +++++++++---------- ...ColumnTitle_Descending.verified.razor.html | 20 +++++++++---------- ...t_Customized_Rendering.verified.razor.html | 16 +++++++-------- ..._MultiSelect_Rendering.verified.razor.html | 16 +++++++-------- ...SingleSelect_Rendering.verified.razor.html | 16 +++++++-------- 8 files changed, 74 insertions(+), 69 deletions(-) diff --git a/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml b/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml index 618dcd265..5b14048c4 100644 --- a/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml +++ b/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml @@ -1984,6 +1984,16 @@ Sets to automatically fit the columns to the available width as best it can. + + + Gets or sets the size of each row in the grid based on the enum. + + + + + Gets or sets a value indicating whether the grid should allow multiple lines of text in cells. + + Gets the first (optional) SelectColumn @@ -13271,11 +13281,6 @@ Large row height - - - Dynamic row height - - The type of in a . diff --git a/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnIndex_Ascending.verified.razor.html b/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnIndex_Ascending.verified.razor.html index 6fb364d33..1cb800924 100644 --- a/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnIndex_Ascending.verified.razor.html +++ b/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnIndex_Ascending.verified.razor.html @@ -2,14 +2,14 @@ - - - - + + - - + + - - + + - - + +
+
Item1
+
Item2
@@ -20,20 +20,20 @@
ADAD
BCBC
CBCB
DADA
\ No newline at end of file diff --git a/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnIndex_Descending.verified.razor.html b/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnIndex_Descending.verified.razor.html index 0ad3cf2d6..6931328db 100644 --- a/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnIndex_Descending.verified.razor.html +++ b/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnIndex_Descending.verified.razor.html @@ -2,14 +2,14 @@ - - - - + + - - + + - - + + - - + +
+
Item1
+
Item2
@@ -20,20 +20,20 @@
DADA
CBCB
BCBC
ADAD
\ No newline at end of file diff --git a/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnTitle_Ascending.verified.razor.html b/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnTitle_Ascending.verified.razor.html index 6fb364d33..1cb800924 100644 --- a/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnTitle_Ascending.verified.razor.html +++ b/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnTitle_Ascending.verified.razor.html @@ -2,14 +2,14 @@ - - - - + + - - + + - - + + - - + +
+
Item1
+
Item2
@@ -20,20 +20,20 @@
ADAD
BCBC
CBCB
DADA
\ No newline at end of file diff --git a/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnTitle_Descending.verified.razor.html b/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnTitle_Descending.verified.razor.html index 0ad3cf2d6..6931328db 100644 --- a/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnTitle_Descending.verified.razor.html +++ b/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnTitle_Descending.verified.razor.html @@ -2,14 +2,14 @@ - - - - + + - - + + - - + + - - + +
+
Item1
+
Item2
@@ -20,20 +20,20 @@
DADA
CBCB
BCBC
ADAD
\ No newline at end of file diff --git a/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_MultiSelect_Customized_Rendering.verified.razor.html b/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_MultiSelect_Customized_Rendering.verified.razor.html index 842eace6d..9f594885d 100644 --- a/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_MultiSelect_Customized_Rendering.verified.razor.html +++ b/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_MultiSelect_Customized_Rendering.verified.razor.html @@ -2,10 +2,10 @@ - - - - + - - + + - - + +
+
+
Name
@@ -16,17 +16,17 @@
+ Jean MartinJean Martin
Kenji SatoKenji Sato
Julie SmithJulie Smith
\ No newline at end of file diff --git a/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_MultiSelect_Rendering.verified.razor.html b/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_MultiSelect_Rendering.verified.razor.html index ad8a02c56..3db2c0a65 100644 --- a/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_MultiSelect_Rendering.verified.razor.html +++ b/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_MultiSelect_Rendering.verified.razor.html @@ -2,14 +2,14 @@ - - - - + - - + - - +
+ +
Name
@@ -20,31 +20,31 @@
+ Jean MartinJean Martin
+ Kenji SatoKenji Sato
+ Julie SmithJulie Smith
\ No newline at end of file diff --git a/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_SingleSelect_Rendering.verified.razor.html b/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_SingleSelect_Rendering.verified.razor.html index 2852aef82..7daf17ba7 100644 --- a/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_SingleSelect_Rendering.verified.razor.html +++ b/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_SingleSelect_Rendering.verified.razor.html @@ -2,8 +2,8 @@ - - + - - + - - + - - +
+
Name
@@ -14,31 +14,31 @@
+ Jean MartinJean Martin
+ Kenji SatoKenji Sato
+ Julie SmithJulie Smith
\ No newline at end of file From fb0a25d5ceee5d371ad4477a9c850494a2c74d49 Mon Sep 17 00:00:00 2001 From: Vincent Baaij Date: Tue, 17 Sep 2024 15:47:32 +0200 Subject: [PATCH 18/39] More style updates --- .../Shared/Pages/DataGrid/Examples/DataGridTypical.razor | 2 +- examples/Demo/Shared/Pages/Lab/IssueTester.razor | 2 -- src/Core/Components/DataGrid/FluentDataGrid.razor.cs | 8 ++------ src/Core/Components/DataGrid/FluentDataGridCell.razor.cs | 2 +- 4 files changed, 4 insertions(+), 10 deletions(-) diff --git a/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTypical.razor b/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTypical.razor index 0060d418e..e359a7ed7 100644 --- a/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTypical.razor +++ b/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTypical.razor @@ -3,7 +3,7 @@

To test set ResizeType on the DataGrid to either DataGridResizeType.Discrete or DataGridResizeType.Exact

Remove the parameter completely to get the original behavior

-
+
diff --git a/src/Core/Components/DataGrid/FluentDataGrid.razor.cs b/src/Core/Components/DataGrid/FluentDataGrid.razor.cs index b3ed7fd6d..a1443093e 100644 --- a/src/Core/Components/DataGrid/FluentDataGrid.razor.cs +++ b/src/Core/Components/DataGrid/FluentDataGrid.razor.cs @@ -695,13 +695,9 @@ private string AriaSortValue(ColumnBase column) : "none"; private string? StyleValue => new StyleBuilder(Style) - //.AddStyle("table-layout", AutoFit ? "auto" : "fixed") - //.AddStyle("width", "fit-content", when: AutoFit) - //.AddStyle("grid-template-columns", GridTemplateColumns, !string.IsNullOrWhiteSpace(GridTemplateColumns)) .AddStyle("grid-template-columns", _internalGridTemplateColumns, !string.IsNullOrWhiteSpace(_internalGridTemplateColumns)) - .AddStyle("grid-template-rows", "auto 100%", _internalGridContext.Items.Count == 0) - .AddStyle("height", $"calc(100% - {(int)RowSize}px)", _internalGridContext.Items.Count == 0) - //.AddStyle("grid-auto-rows", $"{(int)RowSize}px", !Virtualize ) //TODO: Implment Size parameter (44 (Default), 32 (Smaal), 23 (Extra Small)) + .AddStyle("grid-template-rows", "auto 1fr", _internalGridContext.Items.Count == 0 || Items is null) + .AddStyle("height", $"calc(100% - {(int)RowSize}px)", _internalGridContext.TotalItemCount == 0 || Loading) .Build(); private string? ColumnHeaderClass(ColumnBase column) diff --git a/src/Core/Components/DataGrid/FluentDataGridCell.razor.cs b/src/Core/Components/DataGrid/FluentDataGridCell.razor.cs index eb086b35b..d1e23d72f 100644 --- a/src/Core/Components/DataGrid/FluentDataGridCell.razor.cs +++ b/src/Core/Components/DataGrid/FluentDataGridCell.razor.cs @@ -73,7 +73,7 @@ public partial class FluentDataGridCell : FluentComponentBase .AddStyle("padding-inline-start", "calc(((var(--design-unit)* 3) + var(--focus-stroke-width) - var(--stroke-width))* 1px)", Column is SelectColumn && Owner.RowType == DataGridRowType.Default) .AddStyle("padding-top", "calc(var(--design-unit) * 2.5px)", Column is SelectColumn && (Grid.RowSize == DataGridRowSize.Medium || Owner.RowType == DataGridRowType.Header)) .AddStyle("padding-top", "calc(var(--design-unit) * 1.5px)", Column is SelectColumn && Grid.RowSize == DataGridRowSize.Small && Owner.RowType == DataGridRowType.Default) - .AddStyle("height", $"{Grid.ItemSize:0}px", () => !Grid.Loading && Grid.Virtualize && Owner.RowType == DataGridRowType.Default) + .AddStyle("height", $"{Grid.ItemSize:0}px", () => !Grid.Loading && Grid.Virtualize && Grid.Items is not null && Owner.RowType == DataGridRowType.Default) .AddStyle("height", $"{(int)Grid.RowSize}px", () => !Grid.Loading && !Grid.Virtualize && Grid.Items is not null && !Grid.MultiLine) .AddStyle("height", "100%", Grid.MultiLine) .AddStyle("min-height", "44px", Owner.RowType != DataGridRowType.Default) From dfb6b7ea5cb6c6ec2a757c3b00bbd07c92b247ca Mon Sep 17 00:00:00 2001 From: Vincent Baaij Date: Tue, 17 Sep 2024 20:41:35 +0200 Subject: [PATCH 19/39] - Re-add separate header buttons - Fix some samples - Position resize handle better - Always put sort/filter indicators behind header text - Add comments to public methods --- .../Examples/DataGridCustomComparer.razor | 63 +++++------ .../Examples/DataGridTemplateColumns.razor | 4 +- .../DataGrid/Examples/DataGridTypical.razor | 3 +- .../DataGrid/Columns/ColumnBase.razor | 100 +++++++++++++++++- .../Components/DataGrid/FluentDataGrid.razor | 26 ++++- .../DataGrid/FluentDataGrid.razor.cs | 20 ++++ .../DataGrid/FluentDataGrid.razor.css | 4 +- .../DataGrid/FluentDataGridCell.razor.css | 3 + 8 files changed, 183 insertions(+), 40 deletions(-) diff --git a/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridCustomComparer.razor b/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridCustomComparer.razor index 3f189f664..4bd5f023b 100644 --- a/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridCustomComparer.razor +++ b/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridCustomComparer.razor @@ -10,41 +10,42 @@ } - - - - Flag of @(context.Code) - - - - - - - @* +
+ + + Flag of @(context.Code) + + + + + + + @* - + - @(context.Name) + @(context.Name) - *@ - - - - - - + *@ + + + + + +
diff --git a/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTemplateColumns.razor b/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTemplateColumns.razor index 5496035fe..c1e5d93a7 100644 --- a/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTemplateColumns.razor +++ b/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTemplateColumns.razor @@ -1,6 +1,6 @@ @inject DataSource Data - +
Flag of @(context.CountryCode) @@ -28,4 +28,4 @@ void Bonus(Person p) => message = $"You want to give {p.FirstName} {p.LastName} a regular bonus"; void DoubleBonus(Person p) => message = $"You want to give {p.FirstName} {p.LastName} a double bonus"; -} \ No newline at end of file +} diff --git a/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTypical.razor b/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTypical.razor index e359a7ed7..3b05fc635 100644 --- a/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTypical.razor +++ b/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTypical.razor @@ -3,7 +3,7 @@

To test set ResizeType on the DataGrid to either DataGridResizeType.Discrete or DataGridResizeType.Exact

Remove the parameter completely to get the original behavior

-
+
Flag of @(context.Code) diff --git a/src/Core/Components/DataGrid/Columns/ColumnBase.razor b/src/Core/Components/DataGrid/Columns/ColumnBase.razor index 66ed3cef7..4f1eed1b8 100644 --- a/src/Core/Components/DataGrid/Columns/ColumnBase.razor +++ b/src/Core/Components/DataGrid/Columns/ColumnBase.razor @@ -13,7 +13,7 @@ { @HeaderCellItemTemplate(this) } - else + else if (Grid.HeaderCellAsButtonWithMenu) { string? tooltip = Tooltip ? Title : null; @@ -21,7 +21,7 @@ @if (AnyColumnActionEnabled) { - +
@Title
@if (Grid.SortByAscending.HasValue && IsActiveSortColumn) @@ -66,6 +66,78 @@ } + else + { + string? tooltip = Tooltip ? Title : null; + + @if (Align == Align.Start || Align == Align.Center) + { + @if (Grid.ResizeType is not null) + { + @OptionsButton() + } + else + { + @if (ColumnOptions is not null) + { + @FilterButton() + } + } + } + + @if (Sortable.HasValue ? Sortable.Value : IsSortableByDefault()) + { + + +
@Title
+ + @if (Grid.SortByAscending.HasValue && IsActiveSortColumn) + { + if (Grid.SortByAscending == true) + { + + } + else + { + + } + } + @if (ColumnOptions is not null && Filtered.GetValueOrDefault()) + { + + } +
+
+ } + else + { + + +
@Title
+ @if (ColumnOptions is not null && Filtered.GetValueOrDefault()) + { + + } + +
+ } + + @if (Align == Align.End) + { + @if (Grid.ResizeType is not null) + { + @OptionsButton() + } + else + { + @if (ColumnOptions is not null) + { + @FilterButton() + } + } + } + + } } internal void RenderPlaceholderContent(RenderTreeBuilder __builder, PlaceholderContext placeholderContext) @@ -76,4 +148,28 @@ @PlaceholderTemplate(placeholderContext) } } + + private RenderFragment OptionsButton() + { + return + @ + + ; + } + + private RenderFragment FilterButton() + { + return + @ + @if (Filtered.GetValueOrDefault()) + { + + } + else + { + + } + + ; + } } diff --git a/src/Core/Components/DataGrid/FluentDataGrid.razor b/src/Core/Components/DataGrid/FluentDataGrid.razor index fb3a65053..0c17d3990 100644 --- a/src/Core/Components/DataGrid/FluentDataGrid.razor +++ b/src/Core/Components/DataGrid/FluentDataGrid.razor @@ -151,7 +151,9 @@ scope="col" aria-sort="@AriaSortValue(col)"> - @col.HeaderContent + @col.HeaderContent + @if (HeaderCellAsButtonWithMenu) + { @if (col == _displayOptionsForColumn) {
@@ -169,6 +171,26 @@
} + } + else + { + @if (col == _displayOptionsForColumn) + { +
+ + @if (ResizeType is not null) + { + + @if (@col.ColumnOptions is not null) + { + + } + } + @col.ColumnOptions + +
+ } + } @if (ResizableColumns) @@ -203,7 +225,7 @@ private void RenderLoadingContent(RenderTreeBuilder __builder) { - + @if (LoadingContent is null) { diff --git a/src/Core/Components/DataGrid/FluentDataGrid.razor.cs b/src/Core/Components/DataGrid/FluentDataGrid.razor.cs index a1443093e..876627bf6 100644 --- a/src/Core/Components/DataGrid/FluentDataGrid.razor.cs +++ b/src/Core/Components/DataGrid/FluentDataGrid.razor.cs @@ -258,6 +258,9 @@ public partial class FluentDataGrid : FluentComponentBase, IHandleEve [Parameter] public bool MultiLine { get; set; } = false; + [Parameter] + public bool HeaderCellAsButtonWithMenu { get; set; } = true; + /// /// Gets the first (optional) SelectColumn /// @@ -808,6 +811,12 @@ public async Task OnKeyDownAsync(FluentKeyCodeEventArgs args) //return Task.CompletedTask; } + /// + /// Resizes the column width by a discrete amount. + /// + /// The column to be resized + /// The amount of pixels to change width with + /// public async Task SetColumnWidthDiscreteAsync(int? columnIndex, float widthChange) { if (_gridReference is not null && Module is not null) @@ -816,6 +825,12 @@ public async Task SetColumnWidthDiscreteAsync(int? columnIndex, float widthChang } } + /// + /// Resizes the column width to the exact width specified (in pixels). + /// + /// The column to be resized + /// The new width in pixels + /// public async Task SetColumnWidthExactAsync(int columnIndex, int width) { if (_gridReference is not null && Module is not null) @@ -824,6 +839,11 @@ public async Task SetColumnWidthExactAsync(int columnIndex, int width) } } + /// + /// Resets the column widths to their initial values as specified with the parameter. + /// If no value is specified, the default value is "1fr" for each column. + /// + /// public async Task ResetColumnWidthsAsync() { if (_gridReference is not null && Module is not null) diff --git a/src/Core/Components/DataGrid/FluentDataGrid.razor.css b/src/Core/Components/DataGrid/FluentDataGrid.razor.css index 37e560492..71dce59ac 100644 --- a/src/Core/Components/DataGrid/FluentDataGrid.razor.css +++ b/src/Core/Components/DataGrid/FluentDataGrid.razor.css @@ -62,10 +62,10 @@ tbody ::deep .resize-handle { position: absolute; - top: 0; + top: 5px; right: 0; bottom: 0; - height: 34px; + height: 32px; cursor: col-resize; margin-left: calc(var(--design-unit) * 2px); width: calc(var(--design-unit) * 1px + 2px); diff --git a/src/Core/Components/DataGrid/FluentDataGridCell.razor.css b/src/Core/Components/DataGrid/FluentDataGridCell.razor.css index c670e7aea..e078551ab 100644 --- a/src/Core/Components/DataGrid/FluentDataGridCell.razor.css +++ b/src/Core/Components/DataGrid/FluentDataGridCell.razor.css @@ -67,16 +67,19 @@ td { .col-justify-start ::deep .col-sort-button::part(control) { justify-content: start; overflow: hidden; + opacity: 1 } .col-justify-center ::deep .col-sort-button::part(control) { justify-content: center; overflow: hidden; + opacity: 1 } .col-justify-end ::deep .col-sort-button::part(control) { justify-content: end; overflow: hidden; + opacity: 1 } From b16868a4948800f85389430765c1366c48ea3f77 Mon Sep 17 00:00:00 2001 From: Vincent Baaij Date: Wed, 18 Sep 2024 13:39:44 +0200 Subject: [PATCH 20/39] Fix merge issues --- ...crosoft.FluentUI.AspNetCore.Components.xml | 23 ++++++++++++++ .../DataGrid/Examples/DataGridTypical.razor | 2 +- .../DataGrid/Columns/ColumnBase.razor | 31 ------------------- .../Components/DataGrid/FluentDataGrid.razor | 1 - 4 files changed, 24 insertions(+), 33 deletions(-) diff --git a/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml b/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml index 1afa07dca..d536f2c8f 100644 --- a/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml +++ b/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml @@ -2063,6 +2063,29 @@ + + + Resizes the column width by a discrete amount. + + The column to be resized + The amount of pixels to change width with + + + + + Resizes the column width to the exact width specified (in pixels). + + The column to be resized + The new width in pixels + + + + + Resets the column widths to their initial values as specified with the parameter. + If no value is specified, the default value is "1fr" for each column. + + + Gets or sets the reference to the item that holds this cell's values. diff --git a/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTypical.razor b/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTypical.razor index 3b05fc635..7dc7e9f6e 100644 --- a/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTypical.razor +++ b/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTypical.razor @@ -11,7 +11,7 @@ Pagination="@pagination" RowClass="@rowClass" RowStyle="@rowStyle" - HeaderCellAsButtonWithMenu="false" + HeaderCellAsButtonWithMenu="true" ColumnResizeLabels="@customLabels"> Flag of @(context.Code) diff --git a/src/Core/Components/DataGrid/Columns/ColumnBase.razor b/src/Core/Components/DataGrid/Columns/ColumnBase.razor index a061b0840..39f020399 100644 --- a/src/Core/Components/DataGrid/Columns/ColumnBase.razor +++ b/src/Core/Components/DataGrid/Columns/ColumnBase.razor @@ -40,36 +40,6 @@ } - - @if (Sortable.HasValue ? Sortable.Value : IsSortableByDefault()) - { - - @GetSortOptionText() - - } - @if (Grid.ResizeType is not null && Grid.ResizableColumns) - { - @Grid.ColumnResizeLabels.ResizeMenu - } - @if (ColumnOptions is not null) - { - @Grid.ColumnOptionsLabels.OptionsMenu - } - - - - } - else - { - string? tooltip = Tooltip ? Title : null; - - @if (Align == Align.Start || Align == Align.Center) - { - @if (Grid.ResizeType is not null) - { - - - } else { @@ -93,7 +63,6 @@ @Grid.ColumnOptionsLabels.OptionsMenu } - } else diff --git a/src/Core/Components/DataGrid/FluentDataGrid.razor b/src/Core/Components/DataGrid/FluentDataGrid.razor index 0c17d3990..b85cd9e83 100644 --- a/src/Core/Components/DataGrid/FluentDataGrid.razor +++ b/src/Core/Components/DataGrid/FluentDataGrid.razor @@ -150,7 +150,6 @@ Class="@(@ColumnHeaderClass(col) + (ResizableColumns ? " resizable" : ""))" scope="col" aria-sort="@AriaSortValue(col)"> - @col.HeaderContent @if (HeaderCellAsButtonWithMenu) { From 4e1d24a60a4de9500a55ee3e464dfea96ff320a7 Mon Sep 17 00:00:00 2001 From: Vincent Baaij Date: Fri, 27 Sep 2024 19:53:45 +0200 Subject: [PATCH 21/39] Change icons in grid to size 20 (nice in the middel of Aspire (16) and our default (24) --- ...crosoft.FluentUI.AspNetCore.Components.xml | 5 ++ .../Examples/DataGridCustomComparer.razor | 71 +++++++++---------- .../DataGrid/Columns/ColumnBase.razor | 20 +++--- src/Core/Components/Icons/CoreIcons.cs | 13 +++- 4 files changed, 62 insertions(+), 47 deletions(-) diff --git a/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml b/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml index f6a893895..7e170ab63 100644 --- a/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml +++ b/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml @@ -1888,6 +1888,11 @@ Labels used in the column options UI. + + + If true, enables the new style of header cell that includes a button to display all column options through a menu. + + Optionally defines a value for @key on each rendered row. Typically this should be used to specify a diff --git a/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridCustomComparer.razor b/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridCustomComparer.razor index f929f559a..e0df24e86 100644 --- a/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridCustomComparer.razor +++ b/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridCustomComparer.razor @@ -12,44 +12,43 @@ - - None - Discrete - Exact - - - + + None + Discrete + Exact + + +
- - - Flag of @(context.Code) - - - - - - - @* - - - - - @(context.Name) - + + + Flag of @(context.Code) + + + + + + + @* + + + + + @(context.Name) + *@ diff --git a/src/Core/Components/DataGrid/Columns/ColumnBase.razor b/src/Core/Components/DataGrid/Columns/ColumnBase.razor index 39f020399..e2f132c24 100644 --- a/src/Core/Components/DataGrid/Columns/ColumnBase.razor +++ b/src/Core/Components/DataGrid/Columns/ColumnBase.razor @@ -28,16 +28,16 @@ { if (Grid.SortByAscending == true) { - + } else { - + } } @if (ColumnOptions is not null && Filtered.GetValueOrDefault()) { - + } } @@ -94,16 +94,16 @@ { if (Grid.SortByAscending == true) { - + } else { - + } } @if (ColumnOptions is not null && Filtered.GetValueOrDefault()) { - + } @@ -115,7 +115,7 @@
@Title
@if (ColumnOptions is not null && Filtered.GetValueOrDefault()) { - + } @@ -152,7 +152,7 @@ { return @ - + ; } @@ -162,11 +162,11 @@ @ @if (Filtered.GetValueOrDefault()) { - + } else { - + } ; diff --git a/src/Core/Components/Icons/CoreIcons.cs b/src/Core/Components/Icons/CoreIcons.cs index 1c577f3f3..96c19ec91 100644 --- a/src/Core/Components/Icons/CoreIcons.cs +++ b/src/Core/Components/Icons/CoreIcons.cs @@ -80,10 +80,14 @@ internal static partial class Regular [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] internal static partial class Size16 { + public class ArrowSortDown : Icon { public ArrowSortDown() : base("ArrowSortDown", IconVariant.Regular, IconSize.Size16, "") { } } + public class ArrowSortUp : Icon { public ArrowSortUp() : base("ArrowSortUp", IconVariant.Regular, IconSize.Size16, "") { } } public class CheckmarkCircle : Icon { public CheckmarkCircle() : base("CheckmarkCircle", IconVariant.Regular, IconSize.Size16, "") { } } public class Dismiss : Icon { public Dismiss() : base("Dismiss", IconVariant.Regular, IconSize.Size16, "") { } } public class DismissCircle : Icon { public DismissCircle() : base("DismissCircle", IconVariant.Regular, IconSize.Size16, "") { } } + public class Filter : Icon { public Filter() : base("Filter", IconVariant.Regular, IconSize.Size16, "") { } } public class Info : Icon { public Info() : base("Info", IconVariant.Regular, IconSize.Size16, "") { } } + public class MoreVertical : Icon { public MoreVertical() : base("MoreVertical", IconVariant.Regular, IconSize.Size16, "") { } } public class Warning : Icon { public Warning() : base("Warning", IconVariant.Regular, IconSize.Size16, "") { } } public class Search : Icon { public Search() : base("Search", IconVariant.Regular, IconSize.Size16, "") { } } } @@ -96,12 +100,19 @@ internal static partial class Size20 { public class Add : Icon { public Add() : base("Add", IconVariant.Regular, IconSize.Size20, "") { } } public class ArrowReset : Icon { public ArrowReset() : base("ArrowReset", IconVariant.Regular, IconSize.Size20, "") { } } + public class ArrowSortDown : Icon { public ArrowSortDown() : base("ArrowSortDown", IconVariant.Regular, IconSize.Size20, "") { } } + public class ArrowSortUp : Icon { public ArrowSortUp() : base("ArrowSortUp", IconVariant.Regular, IconSize.Size20, "") { } } + public class CheckboxUnchecked : Icon { public CheckboxUnchecked() : base("CheckboxUnchecked", IconVariant.Regular, IconSize.Size20, "") { } } public class Checkmark : Icon { public Checkmark() : base("Checkmark", IconVariant.Regular, IconSize.Size24, "") { } } public class ChevronDoubleLeft : Icon { public ChevronDoubleLeft() : base("ChevronDoubleLeft", IconVariant.Regular, IconSize.Size20, "") { } } public class ChevronDoubleRight : Icon { public ChevronDoubleRight() : base("ChevronDoubleRight", IconVariant.Regular, IconSize.Size20, "") { } } + public class ChevronDown : Icon { public ChevronDown() : base("ChevronDown", IconVariant.Regular, IconSize.Size20, "") { } } public class Dismiss : Icon { public Dismiss() : base("Dismiss", IconVariant.Regular, IconSize.Size20, "") { } } public class DismissCircle : Icon { public DismissCircle() : base("DismissCircle", IconVariant.Regular, IconSize.Size20, "") { } } - public class CheckboxUnchecked : Icon { public CheckboxUnchecked() : base("CheckboxUnchecked", IconVariant.Regular, IconSize.Size20, "") { } } + public class Filter : Icon { public Filter() : base("Filter", IconVariant.Regular, IconSize.Size20, "") { } } + public class FilterDismiss : Icon { public FilterDismiss() : base("FilterDismiss", IconVariant.Regular, IconSize.Size20, "") { } } + public class MoreVertical : Icon { public MoreVertical() : base("MoreVertical", IconVariant.Regular, IconSize.Size20, "") { } } + public class RadioButton : Icon { public RadioButton() : base("RadioButton", IconVariant.Regular, IconSize.Size20, "") { } }; public class Star : Icon { public Star() : base("Star", IconVariant.Regular, IconSize.Size20, "") { } }; public class Subtract : Icon { public Subtract() : base("Subtract", IconVariant.Regular, IconSize.Size20, "") { } } From d6af5445f9314bbb647286462a10caf34b74f22c Mon Sep 17 00:00:00 2001 From: Vincent Baaij Date: Wed, 2 Oct 2024 15:45:41 +0200 Subject: [PATCH 22/39] Fix tests/verified files --- .../Microsoft.FluentUI.AspNetCore.Components.xml | 6 ++++++ ...rtByColumnIndex_Ascending.verified.razor.html | 16 ++++++---------- ...tByColumnIndex_Descending.verified.razor.html | 16 ++++++---------- ...rtByColumnTitle_Ascending.verified.razor.html | 16 ++++++---------- ...tByColumnTitle_Descending.verified.razor.html | 16 ++++++---------- ...lect_Customized_Rendering.verified.razor.html | 8 +++----- ...ect_MultiSelect_Rendering.verified.razor.html | 8 +++----- ...ct_SingleSelect_Rendering.verified.razor.html | 8 +++----- 8 files changed, 39 insertions(+), 55 deletions(-) diff --git a/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml b/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml index fbb1ef8fc..8694c6bb8 100644 --- a/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml +++ b/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml @@ -14013,6 +14013,12 @@ Light variant of FluentUI System Icons
+ + + Color variant of FluentUI System Icons + > Note: FOR TESTING ONLY. This variant is not supported yet in the FluentUI System Icons. + + How to handle the input file(s). diff --git a/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnIndex_Ascending.verified.razor.html b/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnIndex_Ascending.verified.razor.html index 1cb800924..c9d018db4 100644 --- a/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnIndex_Ascending.verified.razor.html +++ b/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnIndex_Ascending.verified.razor.html @@ -3,18 +3,14 @@
- -
-
Item1
-
-
+ +
Item1
+
- -
-
Item2
-
-
+ +
Item2
+
- -
-
Item1
-
-
+ +
Item1
+
- -
-
Item2
-
-
+ +
Item2
+
- -
-
Item1
-
-
+ +
Item1
+
- -
-
Item2
-
-
+ +
Item2
+
- -
-
Item1
-
-
+ +
Item1
+
- -
-
Item2
-
-
+ +
Item2
+
- -
-
Name
-
-
+ +
Name
+
- -
-
Name
-
-
+ +
Name
+
- -
-
Name
-
-
+ +
Name
+
- +
Item1
- +
- +
Item2
- +
ADAD
BCBC
CBCB
DADA
\ No newline at end of file diff --git a/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnIndex_Descending.verified.razor.html b/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnIndex_Descending.verified.razor.html index 2039802ec..59121cb25 100644 --- a/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnIndex_Descending.verified.razor.html +++ b/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnIndex_Descending.verified.razor.html @@ -3,33 +3,33 @@
- +
Item1
- +
- +
Item2
- +
DADA
CBCB
BCBC
ADAD
\ No newline at end of file diff --git a/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnTitle_Ascending.verified.razor.html b/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnTitle_Ascending.verified.razor.html index c9d018db4..668b64c43 100644 --- a/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnTitle_Ascending.verified.razor.html +++ b/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnTitle_Ascending.verified.razor.html @@ -3,33 +3,33 @@
- +
Item1
- +
- +
Item2
- +
ADAD
BCBC
CBCB
DADA
\ No newline at end of file diff --git a/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnTitle_Descending.verified.razor.html b/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnTitle_Descending.verified.razor.html index 2039802ec..59121cb25 100644 --- a/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnTitle_Descending.verified.razor.html +++ b/tests/Core/DataGrid/DataGridSortByTests.DataGridSortByTests_SortByColumnTitle_Descending.verified.razor.html @@ -3,33 +3,33 @@
- +
Item1
- +
- +
Item2
- +
DADA
CBCB
BCBC
ADAD
\ No newline at end of file diff --git a/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_MultiSelect_Customized_Rendering.verified.razor.html b/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_MultiSelect_Customized_Rendering.verified.razor.html index 6b11a2494..666165676 100644 --- a/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_MultiSelect_Customized_Rendering.verified.razor.html +++ b/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_MultiSelect_Customized_Rendering.verified.razor.html @@ -6,25 +6,25 @@
- +
Name
- +
+ Jean MartinJean Martin
Kenji SatoKenji Sato
Julie SmithJulie Smith
\ No newline at end of file diff --git a/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_MultiSelect_Rendering.verified.razor.html b/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_MultiSelect_Rendering.verified.razor.html index ba273c9be..11b0bc5b3 100644 --- a/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_MultiSelect_Rendering.verified.razor.html +++ b/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_MultiSelect_Rendering.verified.razor.html @@ -10,39 +10,39 @@
- +
Name
- +
-
-
-
\ No newline at end of file diff --git a/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_SingleSelect_Rendering.verified.razor.html b/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_SingleSelect_Rendering.verified.razor.html index 3bb857790..e52d79405 100644 --- a/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_SingleSelect_Rendering.verified.razor.html +++ b/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_SingleSelect_Rendering.verified.razor.html @@ -4,39 +4,39 @@
- +
Name
- +
-
-
-
\ No newline at end of file From acadf418049a9f2e048372f69e352267c6c48d61 Mon Sep 17 00:00:00 2001 From: Vincent Baaij Date: Tue, 26 Nov 2024 13:18:05 +0100 Subject: [PATCH 28/39] - Process review comments --- examples/Demo/Shared/Pages/Lab/IssueTester.razor | 3 ++- src/Core/Components/DataGrid/Columns/ColumnBase.razor.css | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/examples/Demo/Shared/Pages/Lab/IssueTester.razor b/examples/Demo/Shared/Pages/Lab/IssueTester.razor index 5f282702b..9eb9d9cea 100644 --- a/examples/Demo/Shared/Pages/Lab/IssueTester.razor +++ b/examples/Demo/Shared/Pages/Lab/IssueTester.razor @@ -1 +1,2 @@ - \ No newline at end of file +@using FluentUI.Demo.Shared.Pages.DataGrid.Examples + diff --git a/src/Core/Components/DataGrid/Columns/ColumnBase.razor.css b/src/Core/Components/DataGrid/Columns/ColumnBase.razor.css index 2525d262a..cbf496e9c 100644 --- a/src/Core/Components/DataGrid/Columns/ColumnBase.razor.css +++ b/src/Core/Components/DataGrid/Columns/ColumnBase.razor.css @@ -1,5 +1,5 @@ .col-title { - padding: 0.4rem 0.8rem !important; + padding: 0.4rem 0.8rem; user-select: none; } From fe3da39d443358be3fe0bca7b1aacbc46ceed426 Mon Sep 17 00:00:00 2001 From: Vincent Baaij Date: Tue, 26 Nov 2024 14:40:38 +0100 Subject: [PATCH 29/39] - Fix keyboard navigation in DataGrid --- ...crosoft.FluentUI.AspNetCore.Components.xml | 5 +++ .../DataGrid/Examples/DataGridTypical.razor | 3 +- .../DataGrid/FluentDataGrid.razor.cs | 8 ++++- .../DataGrid/FluentDataGrid.razor.js | 32 +++++++++---------- 4 files changed, 30 insertions(+), 18 deletions(-) diff --git a/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml b/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml index eab056ec0..68d1524a9 100644 --- a/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml +++ b/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml @@ -2020,6 +2020,11 @@ Gets or sets a value indicating whether the grid should allow multiple lines of text in cells.
+ + + Gets or sets a value indicating whether the grids' first cell should be focused. + + Constructs an instance of . diff --git a/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTypical.razor b/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTypical.razor index 7dc7e9f6e..bd0073c50 100644 --- a/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTypical.razor +++ b/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTypical.razor @@ -12,7 +12,8 @@ RowClass="@rowClass" RowStyle="@rowStyle" HeaderCellAsButtonWithMenu="true" - ColumnResizeLabels="@customLabels"> + ColumnResizeLabels="@customLabels" + InitialFocus="true"> Flag of @(context.Code) diff --git a/src/Core/Components/DataGrid/FluentDataGrid.razor.cs b/src/Core/Components/DataGrid/FluentDataGrid.razor.cs index 0a38e9e26..2e2eb5b35 100644 --- a/src/Core/Components/DataGrid/FluentDataGrid.razor.cs +++ b/src/Core/Components/DataGrid/FluentDataGrid.razor.cs @@ -266,6 +266,12 @@ public partial class FluentDataGrid : FluentComponentBase, IHandleEve [Parameter] public bool MultiLine { get; set; } = false; + /// + /// Gets or sets a value indicating whether the grids' first cell should be focused. + /// + [Parameter] + public bool AutoFocus{ get; set; } = false; + private ElementReference? _gridReference; private Virtualize<(int, TGridItem)>? _virtualizeComponent; @@ -391,7 +397,7 @@ protected override async Task OnAfterRenderAsync(bool firstRender) Module ??= await JSRuntime.InvokeAsync("import", JAVASCRIPT_FILE.FormatCollocatedUrl(LibraryConfiguration)); try { - _jsEventDisposable = await Module.InvokeAsync("init", _gridReference); + _jsEventDisposable = await Module.InvokeAsync("init", _gridReference, AutoFocus); } catch (JSException ex) { diff --git a/src/Core/Components/DataGrid/FluentDataGrid.razor.js b/src/Core/Components/DataGrid/FluentDataGrid.razor.js index e8c698eb0..c767f4ec7 100644 --- a/src/Core/Components/DataGrid/FluentDataGrid.razor.js +++ b/src/Core/Components/DataGrid/FluentDataGrid.razor.js @@ -1,7 +1,7 @@ let grids = []; const minWidth = 100; -export function init(gridElement) { +export function init(gridElement, autoFocus) { if (gridElement === undefined || gridElement === null) { return; }; @@ -9,9 +9,10 @@ export function init(gridElement) { enableColumnResizing(gridElement); let start = gridElement.querySelector('td:first-child'); - //start.focus(); - //start.style.backgroundColor = '#50b988'; - //start.style.color = 'white'; + + if (autoFocus) { + start.focus(); + } const bodyClickHandler = event => { const columnOptionsElement = gridElement?.querySelector('.col-options'); @@ -23,14 +24,10 @@ export function init(gridElement) { gridElement.dispatchEvent(new CustomEvent('closecolumnresize', { bubbles: true })); } }; - const changeStyle = (sibling) => { + const keyboardNavigation = (sibling) => { if (sibling !== null) { start.focus(); - start.style.backgroundColor = ''; - start.style.color = ''; sibling.focus(); - //sibling.style.backgroundColor = '#50b988'; - //sibling.style.color = 'white'; start = sibling; } } @@ -66,7 +63,7 @@ export function init(gridElement) { ); } - if (start) { + if (start === document.activeElement) { const idx = start.cellIndex; if (event.key === "ArrowUp") { @@ -74,25 +71,28 @@ export function init(gridElement) { const previousRow = start.parentElement.previousElementSibling; if (previousRow !== null) { const previousSibling = previousRow.cells[idx]; - changeStyle(previousSibling); + keyboardNavigation(previousSibling); } } else if (event.key === "ArrowDown") { // down arrow const nextRow = start.parentElement.nextElementSibling; if (nextRow !== null) { const nextSibling = nextRow.cells[idx]; - changeStyle(nextSibling); + keyboardNavigation(nextSibling); } } else if (event.key === "ArrowLeft") { // left arrow - const previousSibling = start.previousElementSibling; - changeStyle(previousSibling); + const previousSibling = (document.body.dir === '' || document.body.dir === 'ltr') ? start.previousElementSibling : start.nextElementSibling; + keyboardNavigation(previousSibling); } else if (event.key === "ArrowRight") { // right arrow - const nextsibling = start.nextElementSibling; - changeStyle(nextsibling); + const nextsibling = (document.body.dir === '' || document.body.dir === 'ltr') ? start.nextElementSibling : start.previousElementSibling; + keyboardNavigation(nextsibling); } } + else { + start = document.activeElement; + } }; From d0df3e3aec3dafa1c1330381d2aaa4d0cba183ba Mon Sep 17 00:00:00 2001 From: Vincent Baaij Date: Wed, 27 Nov 2024 12:50:27 +0100 Subject: [PATCH 30/39] Menu work --- .../Shared/Pages/DataGrid/Examples/DataGridTypical.razor | 6 +++--- examples/Demo/Shared/Pages/Lab/IssueTester.razor | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTypical.razor b/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTypical.razor index bd0073c50..411969a3b 100644 --- a/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTypical.razor +++ b/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTypical.razor @@ -3,7 +3,7 @@

To test set ResizeType on the DataGrid to either DataGridResizeType.Discrete or DataGridResizeType.Exact

Remove the parameter completely to get the original behavior

-
+
+ AutoFocus="true"> Flag of @(context.Code) - +
+ + + Gets or sets the (1-based) index of the column + + Gets or sets the an optional CSS class name. diff --git a/src/Core/Components/DataGrid/Columns/ColumnBase.razor.cs b/src/Core/Components/DataGrid/Columns/ColumnBase.razor.cs index e1a15e3d6..d0a3a3299 100644 --- a/src/Core/Components/DataGrid/Columns/ColumnBase.razor.cs +++ b/src/Core/Components/DataGrid/Columns/ColumnBase.razor.cs @@ -26,6 +26,13 @@ public abstract partial class ColumnBase [Parameter] public string? Title { get; set; } + + /// + /// Gets or sets the index (1-based) of the column + /// + [Parameter] + public int Index { get; set; } + /// /// Gets or sets the an optional CSS class name. /// If specified, this is included in the class attribute of header and grid cells diff --git a/src/Core/Components/DataGrid/FluentDataGrid.razor b/src/Core/Components/DataGrid/FluentDataGrid.razor index c191a9bf5..84f90548f 100644 --- a/src/Core/Components/DataGrid/FluentDataGrid.razor +++ b/src/Core/Components/DataGrid/FluentDataGrid.razor @@ -118,11 +118,11 @@ string? _rowsDataSize = $"height: {ItemSize}px"; - @for (var colIndex = 0; colIndex < _columns.Count; colIndex++) + @for (var i = 0; i < _columns.Count; i++) { - var col = _columns[colIndex]; + var col = _columns[i]; - + @((RenderFragment)(__builder => col.RenderPlaceholderContent(__builder, placeholderContext))) } @@ -131,11 +131,10 @@ private void RenderColumnHeaders(RenderTreeBuilder __builder) { - @for (var colIndex = 0; colIndex < _columns.Count; colIndex++) + @for (var i = 0; i < _columns.Count; i++) { - var col = _columns[colIndex]; - var oneBasedIndex = colIndex + 1; - //string CellId = Identifier.NewId(); + var col = _columns[i]; + if (_sortByColumn == col) col.IsActiveSortColumn = true; else @@ -143,7 +142,7 @@ + }
@@ -177,7 +176,7 @@ @if (ResizeType is not null) { - + @if (@col.ColumnOptions is not null) { diff --git a/src/Core/Components/DataGrid/FluentDataGrid.razor.cs b/src/Core/Components/DataGrid/FluentDataGrid.razor.cs index 015d69c83..8d6942183 100644 --- a/src/Core/Components/DataGrid/FluentDataGrid.razor.cs +++ b/src/Core/Components/DataGrid/FluentDataGrid.razor.cs @@ -448,6 +448,7 @@ internal void AddColumn(ColumnBase column, SortDirection? initialSort { if (_collectingColumns) { + column.Index = _columns.Count + 1; _columns.Add(column); if (isDefaultSortColumn && _sortByColumn is null && initialSortDirection.HasValue) From 4bf7001414c762f2a2bee86cb79c78c456b521e7 Mon Sep 17 00:00:00 2001 From: Vincent Baaij Date: Fri, 29 Nov 2024 14:04:19 +0100 Subject: [PATCH 39/39] Fix tests --- .../Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml | 2 +- ...elect_MultiSelect_Customized_Rendering.verified.razor.html | 4 ++-- ...Grid_ColumSelect_MultiSelect_Rendering.verified.razor.html | 4 ++-- ...rid_ColumSelect_SingleSelect_Rendering.verified.razor.html | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml b/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml index d1ab3b69f..e1407fac8 100644 --- a/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml +++ b/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml @@ -1185,7 +1185,7 @@ - Gets or sets the (1-based) index of the column + Gets or sets the index (1-based) of the column diff --git a/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_MultiSelect_Customized_Rendering.verified.razor.html b/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_MultiSelect_Customized_Rendering.verified.razor.html index 666165676..6bd3fb6c6 100644 --- a/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_MultiSelect_Customized_Rendering.verified.razor.html +++ b/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_MultiSelect_Customized_Rendering.verified.razor.html @@ -2,7 +2,7 @@ - -
+
@@ -27,4 +27,4 @@ Julie Smith
\ No newline at end of file + diff --git a/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_MultiSelect_Rendering.verified.razor.html b/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_MultiSelect_Rendering.verified.razor.html index 11b0bc5b3..45c4837ee 100644 --- a/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_MultiSelect_Rendering.verified.razor.html +++ b/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_MultiSelect_Rendering.verified.razor.html @@ -2,7 +2,7 @@ - -
+
\ No newline at end of file + diff --git a/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_SingleSelect_Rendering.verified.razor.html b/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_SingleSelect_Rendering.verified.razor.html index e52d79405..d59aed370 100644 --- a/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_SingleSelect_Rendering.verified.razor.html +++ b/tests/Core/DataGrid/FluentDataGridColumSelectTests.FluentDataGrid_ColumSelect_SingleSelect_Rendering.verified.razor.html @@ -2,7 +2,7 @@ - + -
Name
@@ -39,4 +39,4 @@
Julie Smith
\ No newline at end of file +