Skip to content

Commit a9166ad

Browse files
authored
[DataGrid] Add icons to column menus (#3621)
* [DataGrid] Add icon to column menu items, update docs [DataGrid] Runtime error when using Virtualize together with Multiple * Rename and change slot in label records to bool
1 parent f6409d1 commit a9166ad

9 files changed

Lines changed: 134 additions & 10 deletions

File tree

examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1370,14 +1370,25 @@
13701370
Gets or sets the text shown in the column menu
13711371
</summary>
13721372
</member>
1373+
<member name="P:Microsoft.FluentUI.AspNetCore.Components.ColumnOptionsLabels.Icon">
1374+
<summary>
1375+
Gets or sets the icon to show in the column menu
1376+
</summary>
1377+
</member>
1378+
<member name="P:Microsoft.FluentUI.AspNetCore.Components.ColumnOptionsLabels.IconPositionStart">
1379+
<summary>
1380+
Gets or sets whether the icon is positioned at the start (true) or
1381+
at the end (false) of the menu item
1382+
</summary>
1383+
</member>
13731384
<member name="P:Microsoft.FluentUI.AspNetCore.Components.ColumnOptionsLabels.Default">
13741385
<summary>
13751386
Gets the default labels for the options UI.
13761387
</summary>
13771388
</member>
13781389
<member name="P:Microsoft.FluentUI.AspNetCore.Components.ColumnResizeLabels.ResizeMenu">
13791390
<summary>
1380-
Gets or sets the text shown in the column menu
1391+
Gets or sets the text shown in the column menu
13811392
</summary>
13821393
</member>
13831394
<member name="P:Microsoft.FluentUI.AspNetCore.Components.ColumnResizeLabels.DiscreteLabel">
@@ -1410,6 +1421,17 @@
14101421
Gets or sets the aria label for the submit button in the resize UI
14111422
</summary>
14121423
</member>
1424+
<member name="P:Microsoft.FluentUI.AspNetCore.Components.ColumnResizeLabels.Icon">
1425+
<summary>
1426+
Gets or sets the icon to show in the column menu
1427+
</summary>
1428+
</member>
1429+
<member name="P:Microsoft.FluentUI.AspNetCore.Components.ColumnResizeLabels.IconPositionStart">
1430+
<summary>
1431+
Gets or sets whether the icon is positioned at the start (true) or
1432+
at the end (false) of the menu item
1433+
</summary>
1434+
</member>
14131435
<member name="P:Microsoft.FluentUI.AspNetCore.Components.ColumnResizeLabels.Default">
14141436
<summary>
14151437
Gets the default labels for the resize UI.
@@ -1435,7 +1457,7 @@
14351457
</member>
14361458
<member name="P:Microsoft.FluentUI.AspNetCore.Components.ColumnSortLabels.SortMenu">
14371459
<summary>
1438-
Gets or sets the text shown in the column menu
1460+
Gets or sets the text shown in the column menu
14391461
</summary>
14401462
</member>
14411463
<member name="P:Microsoft.FluentUI.AspNetCore.Components.ColumnSortLabels.SortMenuAscendingLabel">
@@ -1448,6 +1470,17 @@
14481470
Gets or sets the text shown in the column menu when in descending order
14491471
</summary>
14501472
</member>
1473+
<member name="P:Microsoft.FluentUI.AspNetCore.Components.ColumnSortLabels.Icon">
1474+
<summary>
1475+
Gets or sets the icon to show in the column menu
1476+
</summary>
1477+
</member>
1478+
<member name="P:Microsoft.FluentUI.AspNetCore.Components.ColumnSortLabels.IconPositionStart">
1479+
<summary>
1480+
Gets or sets whether the icon is positioned at the start (true) or
1481+
at the end (false) of the menu item
1482+
</summary>
1483+
</member>
14511484
<member name="P:Microsoft.FluentUI.AspNetCore.Components.ColumnSortLabels.Default">
14521485
<summary>
14531486
Gets the default labels for the sort UI.
@@ -2059,6 +2092,7 @@
20592092
<member name="P:Microsoft.FluentUI.AspNetCore.Components.FluentDataGrid`1.MultiLine">
20602093
<summary>
20612094
Gets or sets a value indicating whether the grid should allow multiple lines of text in cells.
2095+
Cannot be used together with Virtualize.
20622096
</summary>
20632097
</member>
20642098
<member name="P:Microsoft.FluentUI.AspNetCore.Components.FluentDataGrid`1.SaveStateInUrl">
@@ -2195,7 +2229,7 @@
21952229
Guards the CurrentPageIndex from getting greater than the LastPageIndex
21962230

21972231
</summary>
2198-
<param name="visibleRows">The maixmum number of rows that fits the available space</param>
2232+
<param name="visibleRows">The maximum number of rows that fits the available space</param>
21992233
<returns></returns>
22002234
</member>
22012235
<member name="M:Microsoft.FluentUI.AspNetCore.Components.FluentDataGrid`1.SetColumnWidthDiscreteAsync(System.Nullable{System.Int32},System.Single)">

examples/Demo/Shared/Pages/DataGrid/DataGridPage.razor

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,25 @@
173173

174174
<ApiDocumentation Component="typeof(SelectColumn<>)" GenericLabel="TGridItem" />
175175

176+
<h3>Column menu labels and icons</h3>
177+
<p>
178+
For customizing/translating the labels and icons used in the column menus, the following <code>records</code> are available. They can be applied
179+
to a grid by setting the respective parameters to an instance of these records. If you do not want to use an icon for a menu item, supply a null
180+
value to the Icon property in a record:
181+
<CodeSnippet>
182+
ColumnResizeLabels resizeLabels = ColumnResizeLabels.Default with
183+
{
184+
DiscreteLabel = "Abcd efg",
185+
ResetAriaLabel = "hij klm",
186+
Icon = null
187+
};
188+
</CodeSnippet>
189+
</p>
190+
<ApiDocumentation Component="typeof(ColumnSortLabels)" />
191+
<ApiDocumentation Component="typeof(ColumnOptionsLabels)" />
192+
<ApiDocumentation Component="typeof(ColumnResizeLabels)" />
193+
194+
176195
<div class="demopanel">
177196
<p>
178197
<strong>The <code>FluentDataGridRow</code> and <code>FluentDataGridCell</code> API's are usually not used directly </strong>

examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTypical.razor

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
RowClass="@rowClass"
1414
RowStyle="@rowStyle"
1515
HeaderCellAsButtonWithMenu="true"
16-
ColumnResizeLabels="@customLabels">
16+
ColumnResizeLabels="@resizeLabels">
1717
<TemplateColumn Tooltip="true" TooltipText="@(c => "Flag of " + c.Name)" Title="Rank" SortBy="@rankSort" Align="Align.Center" InitialSortDirection="SortDirection.Ascending" IsDefaultSortColumn=true>
1818
<img class="flag" src="_content/FluentUI.Demo.Shared/flags/@(context.Code).svg" alt="Flag of @(context.Code)" />
1919
</TemplateColumn>
@@ -66,7 +66,11 @@
6666
int minMedals;
6767
int maxMedals = 130;
6868

69-
ColumnResizeLabels customLabels = ColumnResizeLabels.Default with { DiscreteLabel = "Width (+/- 10px)", ResetAriaLabel = "Restore" };
69+
ColumnResizeLabels resizeLabels = ColumnResizeLabels.Default with
70+
{
71+
DiscreteLabel = "Width (+/- 10px)",
72+
ResetAriaLabel = "Restore"
73+
};
7074

7175
GridSort<Country> rankSort = GridSort<Country>
7276
.ByDescending(x => x.Medals.Gold)

src/Core/Components/DataGrid/Columns/ColumnBase.razor

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,15 +52,37 @@
5252
{
5353
<FluentMenuItem OnClick="@(async () => await Grid.SortByColumnAsync(this))" @onkeydown="HandleSortMenuKeyDownAsync">
5454
@GetSortOptionText()
55+
@if (Grid.ColumnSortLabels.Icon is not null)
56+
{
57+
<span style="display:flex; align-items: center;" slot="@(Grid.ColumnSortLabels.IconPositionStart ? "start" : "end")">
58+
<FluentIcon Value="@(Grid.ColumnSortLabels.Icon)" Slot="@(Grid.ColumnSortLabels.IconPositionStart ? "start" : "end")" />
59+
</span>
60+
}
5561
</FluentMenuItem>
5662
}
5763
@if (Grid.ResizeType is not null && Grid.ResizableColumns)
5864
{
59-
<FluentMenuItem OnClick="@(async () => await Grid.ShowColumnResizeAsync(this))" @onkeydown="HandleResizeMenuKeyDownAsync">@Grid.ColumnResizeLabels.ResizeMenu</FluentMenuItem>
65+
<FluentMenuItem OnClick="@(async () => await Grid.ShowColumnResizeAsync(this))" @onkeydown="HandleResizeMenuKeyDownAsync">
66+
@Grid.ColumnResizeLabels.ResizeMenu
67+
@if (Grid.ColumnResizeLabels.Icon is not null)
68+
{
69+
<span style="display:flex; align-items: center;" slot="@(Grid.ColumnResizeLabels.IconPositionStart ? "start" : "end")">
70+
<FluentIcon Value="@(Grid.ColumnResizeLabels.Icon)" Slot="@(Grid.ColumnResizeLabels.IconPositionStart ? "start" : "end")" />
71+
</span>
72+
}
73+
</FluentMenuItem>
6074
}
6175
@if (ColumnOptions is not null)
6276
{
63-
<FluentMenuItem OnClick="@(async () => await Grid.ShowColumnOptionsAsync(this))" @onkeydown="HandleOptionsMenuKeyDownAsync">@Grid.ColumnOptionsLabels.OptionsMenu</FluentMenuItem>
77+
<FluentMenuItem OnClick="@(async () => await Grid.ShowColumnOptionsAsync(this))" @onkeydown="HandleOptionsMenuKeyDownAsync">
78+
@Grid.ColumnOptionsLabels.OptionsMenu
79+
@if (Grid.ColumnOptionsLabels.Icon is not null)
80+
{
81+
<span style="display:flex; align-items: center;" slot="@(Grid.ColumnOptionsLabels.IconPositionStart ? "start" : "end")">
82+
<FluentIcon Value="@(Grid.ColumnOptionsLabels.Icon)" Slot="@(Grid.ColumnOptionsLabels.IconPositionStart ? "start" : "end")" />
83+
</span>
84+
}
85+
</FluentMenuItem>
6486
}
6587
</FluentMenu>
6688
</FluentKeyCode>

src/Core/Components/DataGrid/Columns/ColumnOptionsLabels.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,17 @@ public record ColumnOptionsLabels
1010
/// </summary>
1111
public string OptionsMenu { get; set; } = "Filter";
1212

13+
/// <summary>
14+
/// Gets or sets the icon to show in the column menu
15+
/// </summary>
16+
public Icon? Icon { get; set; } = new CoreIcons.Regular.Size16.Filter();
17+
18+
/// <summary>
19+
/// Gets or sets whether the icon is positioned at the start (true) or
20+
/// at the end (false) of the menu item
21+
/// </summary>
22+
public bool IconPositionStart { get; set; } = true;
23+
1324
/// <summary>
1425
/// Gets the default labels for the options UI.
1526
/// </summary>

src/Core/Components/DataGrid/Columns/ColumnResizeLabels.cs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ namespace Microsoft.FluentUI.AspNetCore.Components;
77
public record ColumnResizeLabels
88
{
99
/// <summary>
10-
/// Gets or sets the text shown in the column menu
10+
/// Gets or sets the text shown in the column menu
1111
/// </summary>
1212
public string ResizeMenu { get; set; } = "Resize";
1313

@@ -41,6 +41,17 @@ public record ColumnResizeLabels
4141
/// </summary>
4242
public string? SubmitAriaLabel { get; set; } = "Set column widths";
4343

44+
/// <summary>
45+
/// Gets or sets the icon to show in the column menu
46+
/// </summary>
47+
public Icon? Icon { get; set; } = new CoreIcons.Regular.Size16.TableResizeColumn();
48+
49+
/// <summary>
50+
/// Gets or sets whether the icon is positioned at the start (true) or
51+
/// at the end (false) of the menu item
52+
/// </summary>
53+
public bool IconPositionStart { get; set; } = true;
54+
4455
/// <summary>
4556
/// Gets the default labels for the resize UI.
4657
/// </summary>

src/Core/Components/DataGrid/Columns/ColumnSortLabels.cs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ namespace Microsoft.FluentUI.AspNetCore.Components;
66
public record ColumnSortLabels
77
{
88
/// <summary>
9-
/// Gets or sets the text shown in the column menu
9+
/// Gets or sets the text shown in the column menu
1010
/// </summary>
1111
public string SortMenu { get; set; } = "Sort";
1212

@@ -20,6 +20,17 @@ public record ColumnSortLabels
2020
/// </summary>
2121
public string SortMenuDescendingLabel { get; set; } = "Sort (descending)";
2222

23+
/// <summary>
24+
/// Gets or sets the icon to show in the column menu
25+
/// </summary>
26+
public Icon? Icon { get; set; } = new CoreIcons.Regular.Size16.ArrowSort();
27+
28+
/// <summary>
29+
/// Gets or sets whether the icon is positioned at the start (true) or
30+
/// at the end (false) of the menu item
31+
/// </summary>
32+
public bool IconPositionStart { get; set; } = true;
33+
2334
/// <summary>
2435
/// Gets the default labels for the sort UI.
2536
/// </summary>

src/Core/Components/DataGrid/FluentDataGrid.razor.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,7 @@ public partial class FluentDataGrid<TGridItem> : FluentComponentBase, IHandleEve
293293

294294
/// <summary>
295295
/// Gets or sets a value indicating whether the grid should allow multiple lines of text in cells.
296+
/// Cannot be used together with Virtualize.
296297
/// </summary>
297298
[Parameter]
298299
public bool MultiLine { get; set; } = false;
@@ -419,6 +420,11 @@ protected override Task OnParametersSetAsync()
419420
throw new InvalidOperationException($"FluentDataGrid requires one of {nameof(Items)} or {nameof(ItemsProvider)}, but both were specified.");
420421
}
421422

423+
if (Virtualize && MultiLine)
424+
{
425+
throw new InvalidOperationException($"FluentDataGrid cannot use both {nameof(Virtualize)} and {nameof(MultiLine)} at the same time.");
426+
}
427+
422428
// Perform a re-query only if the data source or something else has changed
423429
var dataSourceHasChanged = !Equals(Items, _lastAssignedItems) || !Equals(ItemsProvider, _lastAssignedItemsProvider);
424430
if (dataSourceHasChanged)
@@ -997,7 +1003,7 @@ private void SaveStateToQueryString()
9971003
/// Guards the CurrentPageIndex from getting greater than the LastPageIndex
9981004
///
9991005
/// </summary>
1000-
/// <param name="visibleRows">The maixmum number of rows that fits the available space</param>
1006+
/// <param name="visibleRows">The maximum number of rows that fits the available space</param>
10011007
/// <returns></returns>
10021008
[JSInvokable]
10031009
public async Task UpdateItemsPerPageAsync(int visibleRows)

src/Core/Components/Icons/CoreIcons.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
// ------------------------------------------------------------------------
2+
// MIT License - Copyright (c) Microsoft Corporation. All rights reserved.
3+
// ------------------------------------------------------------------------
4+
15
namespace Microsoft.FluentUI.AspNetCore.Components;
26

37
internal static partial class CoreIcons
@@ -80,6 +84,7 @@ internal static partial class Regular
8084
[global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
8185
internal static partial class Size16
8286
{
87+
public class ArrowSort : Icon { public ArrowSort() : base("ArrowSort", IconVariant.Regular, IconSize.Size16, "<path d=\"M4.85 2.15a.5.5 0 0 0-.7 0l-3 3a.5.5 0 1 0 .7.7L4 3.71v9.79a.5.5 0 0 0 1 0V3.7l2.15 2.15a.5.5 0 1 0 .7-.7l-3-3Zm6.3 11.71c.2.19.5.19.7 0l3-2.9a.5.5 0 1 0-.7-.72L12 12.32V2.5a.5.5 0 0 0-1 0v9.82l-2.15-2.08a.5.5 0 1 0-.7.72l3 2.9Z\"/>") { } }
8388
public class ArrowSortDown : Icon { public ArrowSortDown() : base("ArrowSortDown", IconVariant.Regular, IconSize.Size16, "<path d=\"M7.15 13.85c.2.2.5.2.7 0l3-3a.5.5 0 0 0-.7-.7L8 12.29V2.5a.5.5 0 0 0-1 0v9.8l-2.15-2.15a.5.5 0 0 0-.7.7l3 3Z\"/>") { } }
8489
public class ArrowSortUp : Icon { public ArrowSortUp() : base("ArrowSortUp", IconVariant.Regular, IconSize.Size16, "<path d=\"M7.15 2.15c.2-.2.5-.2.7 0l3 3a.5.5 0 0 1-.7.7L8 3.71v9.79a.5.5 0 0 1-1 0V3.7L4.85 5.86a.5.5 0 1 1-.7-.7l3-3Z\"/>") { } }
8590
public class CheckmarkCircle : Icon { public CheckmarkCircle() : base("CheckmarkCircle", IconVariant.Regular, IconSize.Size16, "<path d=\"M8 2a6 6 0 1 1 0 12A6 6 0 0 1 8 2Zm0 1a5 5 0 1 0 0 10A5 5 0 0 0 8 3Zm-.75 6.04 2.87-2.88a.5.5 0 0 1 .77.64l-.06.07L7.6 10.1a.5.5 0 0 1-.63.06l-.07-.06-1.75-1.75a.5.5 0 0 1 .63-.76l.07.06 1.4 1.4 2.87-2.89-2.87 2.88Z\"/>") { } }
@@ -88,6 +93,7 @@ public class DismissCircle : Icon { public DismissCircle() : base("DismissCircle
8893
public class Filter : Icon { public Filter() : base("Filter", IconVariant.Regular, IconSize.Size16, "<path d=\"M2 3.5c0-.28.22-.5.5-.5h11a.5.5 0 0 1 0 1h-11a.5.5 0 0 1-.5-.5Zm2 4c0-.28.22-.5.5-.5h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1-.5-.5Zm2 4c0-.28.22-.5.5-.5h3a.5.5 0 0 1 0 1h-3a.5.5 0 0 1-.5-.5Z\"/>") { } }
8994
public class Info : Icon { public Info() : base("Info", IconVariant.Regular, IconSize.Size16, "<path d=\"M8 7c.28 0 .5.22.5.5v3a.5.5 0 0 1-1 0v-3c0-.28.22-.5.5-.5Zm0-.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5ZM2 8a6 6 0 1 1 12 0A6 6 0 0 1 2 8Zm6-5a5 5 0 1 0 0 10A5 5 0 0 0 8 3Z\"/>") { } }
9095
public class MoreVertical : Icon { public MoreVertical() : base("MoreVertical", IconVariant.Regular, IconSize.Size16, "<path d=\"M8 5a1 1 0 1 1 0-2 1 1 0 0 1 0 2Zm0 4a1 1 0 1 1 0-2 1 1 0 0 1 0 2Zm-1 3a1 1 0 1 0 2 0 1 1 0 0 0-2 0Z\"/>") { } }
96+
public class TableResizeColumn : Icon { public TableResizeColumn() : base("TableResizeColumn", IconVariant.Regular, IconSize.Size16, "<path d=\"M6.35 6.15c.2.2.2.5 0 .7l-.64.65h4.58l-.64-.65a.5.5 0 1 1 .7-.7l1.5 1.5c.2.2.2.5 0 .7l-1.5 1.5a.5.5 0 0 1-.7-.7l.64-.65H5.71l.64.65a.5.5 0 1 1-.7.7l-1.5-1.5a.5.5 0 0 1 0-.7l1.5-1.5c.2-.2.5-.2.7 0ZM11.5 2A2.5 2.5 0 0 1 14 4.5v7a2.5 2.5 0 0 1-2.5 2.5h-7A2.5 2.5 0 0 1 2 11.5v-7A2.5 2.5 0 0 1 4.5 2h7Zm.5 1.09v3.29l-.94-.94a1.6 1.6 0 0 0-.06-.06V3H5v2.38l-.06.06-.94.94v-3.3c-.58.21-1 .77-1 1.42v7c0 .65.42 1.2 1 1.41V9.62l.94.94.06.06V13h6v-2.38l.06-.06.94-.94v3.3c.58-.21 1-.77 1-1.42v-7c0-.65-.42-1.2-1-1.41Zm-.94 7.47L11 10.5Z\"/>") { } }
9197
public class Warning : Icon { public Warning() : base("Warning", IconVariant.Regular, IconSize.Size16, "<path d=\"M8.75 10.25a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0ZM7.5 8a.5.5 0 0 0 1 0V5.5a.5.5 0 0 0-1 0V8Zm-.6-5.36c.49-.86 1.71-.86 2.2 0l4.74 8.5c.47.83-.14 1.86-1.09 1.86h-9.5a1.25 1.25 0 0 1-1.1-1.86l4.76-8.5Zm1.32.49a.25.25 0 0 0-.44 0l-4.75 8.5c-.1.16.03.37.22.37h9.5c.2 0 .31-.2.22-.37l-4.75-8.5Z\"/>") { } }
9298
public class Search : Icon { public Search() : base("Search", IconVariant.Regular, IconSize.Size16, "<path d=\"M9.1 10.17a4.5 4.5 0 1 1 1.06-1.06l3.62 3.61a.75.75 0 1 1-1.06 1.06l-3.61-3.61Zm.4-3.67a3 3 0 1 0-6 0 3 3 0 0 0 6 0Z\"/>") { } }
9399
}

0 commit comments

Comments
 (0)