Skip to content

MudDataGrid: Add parameters for filter icons#11864

Merged
danielchalmers merged 7 commits intoMudBlazor:devfrom
CyrilArtFX:feature/datagrid-icons-custom
Sep 24, 2025
Merged

MudDataGrid: Add parameters for filter icons#11864
danielchalmers merged 7 commits intoMudBlazor:devfrom
CyrilArtFX:feature/datagrid-icons-custom

Conversation

@CyrilArtFX
Copy link
Contributor

This PR addresses the the issue #7478 by giving the possibility to customize the icons used in the filter feature of the MudDataGrid, as well as a possibility to change the color of the sort and filter icons of the MudDataGrid.

The intended use-case is to have more feedback when the filter feature is used for a better user experience.
(For example, having the filter icon of a column become yellow when filters are applied on this column.)

I made the changes as light as possible, by just creating new parameters to replace hard coded values and not adding any logic.
Feel free to suggest better names for those parameters if you have ideas.

Checklist:

  • The PR is submitted to the correct branch (dev).
  • My code follows the style of this project.
  • I've added relevant tests or tested on existing ones.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces new parameters to customize the sort and filter icons in the MudDataGrid, which is a great enhancement for user experience. The implementation is clean and directly addresses the feature request. I have two suggestions: one is a critical style guide adherence issue regarding default parameter initialization, and the other is a minor code simplification to remove a redundant if/else block. Overall, a solid contribution.

Comment on lines 308 to 348
/// <summary>
/// The color of the sort icon.
/// </summary>
[Parameter]
public Color SortIconColor { get; set; } = Color.Default;

/// <summary>
/// The empty filter icon shown when <see cref="Filterable"/> is <c>true</c>.
/// </summary>
[Parameter]
public string FilterIconEmpty { get; set; } = Icons.Material.Outlined.FilterAlt;

/// <summary>
/// The filled filter icon shown when <see cref="Filterable"/> is <c>true</c>.
/// </summary>
[Parameter]
public string FilterIconFilled { get; set; } = Icons.Material.Filled.FilterAlt;

/// <summary>
/// The clear filter icon shown when <see cref="Filterable"/> is <c>true</c>.
/// </summary>
[Parameter]
public string FilterIconClear { get; set; } = Icons.Material.Filled.FilterAltOff;

/// <summary>
/// The color of the empty filter icon.
/// </summary>
[Parameter]
public Color FilterIconEmptyColor { get; set; } = Color.Default;

/// <summary>
/// The color of the filled filter icon.
/// </summary>
[Parameter]
public Color FilterIconFilledColor { get; set; } = Color.Default;

/// <summary>
/// The color of the clear filter icon.
/// </summary>
[Parameter]
public Color FilterIconClearColor { get; set; } = Color.Default;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The new Color parameters (SortIconColor, FilterIconEmptyColor, FilterIconFilledColor, FilterIconClearColor) are initialized to Color.Default. According to the style guide, members should not be initialized to their default values.1 Since Color.Default is the default value for the Color enum, these initializations are redundant and should be removed. Please remove the = Color.Default from these property declarations.

Style Guide References

Footnotes

  1. Members should not be initialized to their default values. (link)

Comment on lines 77 to 84
if (SortDirection == SortDirection.None)
{
<MudIconButton Icon="@Column.SortIcon" Class="@sortIconClass" Size="@Size.Small" OnClick="@SortChangedAsync" aria-label="@Localizer[LanguageResource.MudDataGrid_Sort]"></MudIconButton>
<MudIconButton Icon="@Column.SortIcon" Class="@sortIconClass" Size="@Size.Small" Color="@Column.SortIconColor" OnClick="@SortChangedAsync" aria-label="@Localizer[LanguageResource.MudDataGrid_Sort]"></MudIconButton>
}
else
{
<MudIconButton Icon="@Column.SortIcon" Class="@sortIconClass" Size="@Size.Small" OnClick="@SortChangedAsync" aria-label="@Localizer[LanguageResource.MudDataGrid_Sort]"></MudIconButton>
<MudIconButton Icon="@Column.SortIcon" Class="@sortIconClass" Size="@Size.Small" Color="@Column.SortIconColor" OnClick="@SortChangedAsync" aria-label="@Localizer[LanguageResource.MudDataGrid_Sort]"></MudIconButton>
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This if/else block is redundant because both branches render the exact same MudIconButton component with identical parameters. This can be simplified to a single component declaration, which improves readability and maintainability.

                    <MudIconButton Icon="@Column.SortIcon" Class="@sortIconClass" Size="@Size.Small" Color="@Column.SortIconColor" OnClick="@SortChangedAsync" aria-label="@Localizer[LanguageResource.MudDataGrid_Sort]"></MudIconButton>

@FeuFeve
Copy link
Contributor

FeuFeve commented Sep 10, 2025

This would be very useful for us as well.

Our use case: we use many datagrids with filters, and we persist filter settings in cookies/local storage so users don’t need to reapply them when navigating between pages.
The challenge is that, on returning to a page, it’s not always obvious at first glance whether a datagrid is filtered (especially when there are many columns).

Having the ability to customize the FilterIconFilledColor would make this much clearer for our users.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Adds per-column parameters to customize sort and filter icons and their colors in MudDataGrid to improve UX feedback when filtering/sorting.

  • Introduces new Column parameters for icon names and colors (sort, filter-empty, filter-filled, filter-clear).
  • Wires these parameters into MudDataGrid, HeaderCell, and FilterHeaderCell components.

Reviewed Changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
src/MudBlazor/Components/DataGrid/MudDataGrid.razor Uses column/context-provided Sort/Filter icon colors and icons instead of hardcoded values.
src/MudBlazor/Components/DataGrid/HeaderCell.razor Applies new Column icon/color parameters to sort and filter buttons.
src/MudBlazor/Components/DataGrid/FilterHeaderCell.razor Applies new Column icon/color parameters to filter menu and clear button.
src/MudBlazor/Components/DataGrid/Column.razor.cs Adds new [Parameter]s for icons and colors, with defaults for icon names.

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Comment on lines 77 to 84
if (SortDirection == SortDirection.None)
{
<MudIconButton Icon="@Column.SortIcon" Class="@sortIconClass" Size="@Size.Small" OnClick="@SortChangedAsync" aria-label="@Localizer[LanguageResource.MudDataGrid_Sort]"></MudIconButton>
<MudIconButton Icon="@Column.SortIcon" Class="@sortIconClass" Size="@Size.Small" Color="@Column.SortIconColor" OnClick="@SortChangedAsync" aria-label="@Localizer[LanguageResource.MudDataGrid_Sort]"></MudIconButton>
}
else
{
<MudIconButton Icon="@Column.SortIcon" Class="@sortIconClass" Size="@Size.Small" OnClick="@SortChangedAsync" aria-label="@Localizer[LanguageResource.MudDataGrid_Sort]"></MudIconButton>
<MudIconButton Icon="@Column.SortIcon" Class="@sortIconClass" Size="@Size.Small" Color="@Column.SortIconColor" OnClick="@SortChangedAsync" aria-label="@Localizer[LanguageResource.MudDataGrid_Sort]"></MudIconButton>
}
Copy link

Copilot AI Sep 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both branches of the SortDirection check render identical content, making the conditional redundant. Remove the if/else and keep a single MudIconButton to simplify and reduce maintenance.

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The objective of this PR is to have as few as possible changes to the source code of MudBlazor to be sure my changes are non-breaking.
This redundant condition already existed before I added the SortIconColor, so I didn't removed it, but I can do it if you believe it's necessary.


<div>
<MudIconButton Ripple="false" Icon="@context.SortIcon" Class="@context.HeaderCell.sortIconClass" Size="@Size.Small" title=@Localizer[LanguageResource.MudDataGrid_Sort] Disabled="!context.sortable" OnClick="@(e => context?.HeaderCell.SortChangedAsync(e))"></MudIconButton>
<MudIconButton Ripple="false" Icon="@context.SortIcon" Class="@context.HeaderCell.sortIconClass" Size="@Size.Small" Color="@context.SortIconColor" title=@Localizer[LanguageResource.MudDataGrid_Sort] Disabled="!context.sortable" OnClick="@(e => context?.HeaderCell.SortChangedAsync(e))"></MudIconButton>
Copy link

Copilot AI Sep 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sort button lacks an aria-label, while similar buttons in HeaderCell.razor use one. Add aria-label='@localizer[LanguageResource.MudDataGrid_Sort]' for screen readers and consistency.

Suggested change
<MudIconButton Ripple="false" Icon="@context.SortIcon" Class="@context.HeaderCell.sortIconClass" Size="@Size.Small" Color="@context.SortIconColor" title=@Localizer[LanguageResource.MudDataGrid_Sort] Disabled="!context.sortable" OnClick="@(e => context?.HeaderCell.SortChangedAsync(e))"></MudIconButton>
<MudIconButton Ripple="false" Icon="@context.SortIcon" Class="@context.HeaderCell.sortIconClass" Size="@Size.Small" Color="@context.SortIconColor" title=@Localizer[LanguageResource.MudDataGrid_Sort] aria-label="@Localizer[LanguageResource.MudDataGrid_Sort]" Disabled="!context.sortable" OnClick="@(e => context?.HeaderCell.SortChangedAsync(e))"></MudIconButton>

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like the other comment, I didn't want to do any changes to the code beside adding the SortIconColor, so I didn't add the aria-label to the button, but I can also do this if you believe it's necessary.

Comment on lines 314 to 331
/// <summary>
/// The empty filter icon shown when <see cref="Filterable"/> is <c>true</c>.
/// </summary>
[Parameter]
public string FilterIconEmpty { get; set; } = Icons.Material.Outlined.FilterAlt;

/// <summary>
/// The filled filter icon shown when <see cref="Filterable"/> is <c>true</c>.
/// </summary>
[Parameter]
public string FilterIconFilled { get; set; } = Icons.Material.Filled.FilterAlt;

/// <summary>
/// The clear filter icon shown when <see cref="Filterable"/> is <c>true</c>.
/// </summary>
[Parameter]
public string FilterIconClear { get; set; } = Icons.Material.Filled.FilterAltOff;

Copy link

Copilot AI Sep 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The summaries suggest icons are shown when Filterable is true, but their actual usage differs by state (empty when no filter is applied, filled when a filter is applied, clear in the filter header). Consider clarifying to: 'The empty filter icon used when no filter is applied,' 'The filled filter icon used when a filter is applied to the column,' and 'The clear filter icon used to remove the current filter in the filter header.'

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can update these summaries to add a bit more precision. I suggest this:
The empty filter icon shown when Filterable is true and no filters are applied to the column.
The filled filter icon shown when Filterable is true and filters are applied to the column.
The clear filter icon shown when Filterable is true to remove filters applied to the column.
If you prefer something else, please let me know so I can change these to whatever you like the most.

@danielchalmers danielchalmers added enhancement Adds a new feature or enhances existing functionality (not fixing a defect) in the main library design labels Sep 19, 2025
@versile2
Copy link
Contributor

I am looking now, hold off on changes until I'm done thinking.

As for the unrelated changes the AI is suggesting, most are appreciated but not required since you didn't create the original issue. The exception is the aria changes if you are touching the code it has to be fixed.

@versile2
Copy link
Contributor

versile2 commented Sep 19, 2025

We aim to keep things as simple as possible (which you’ve also emphasized in your responses), and we really appreciate the work you’ve put into this. That said, I don’t think we should introduce Color parameters here. Since colors can be customized through CSS, it might be cleaner to rely on that. If an icon doesn’t already have a specific class attached, it would be helpful to add one (for example: mud-filter-off, mud-filter-on, mud-filter-alt, etc.) so users can easily target them with CSS.

As for the icons themselves, assigning them per column feels like it could get a bit heavy. With @danielchalmers ’ go-ahead, I’d suggest adding parameters for the icons at the MudDataGrid level using the defaults you’ve proposed. The column-level parameters could remain but simply fall back to the grid-level defaults. That way, users can set them once on the grid and override them per column if needed. Let’s wait for DC to confirm if that approach works before moving forward.

As a final note, we will also need a unit test for the filter icons and a unit test for the sort icons verifying they change.

@danielchalmers
Copy link
Member

We aim to keep things as simple as possible (which you’ve also emphasized in your responses), and we really appreciate the work you’ve put into this. That said, I don’t think we should introduce Color parameters here. Since colors can be customized through CSS, it might be cleaner to rely on that. If an icon doesn’t already have a specific class attached, it would be helpful to add one (for example: mud-filter-off, mud-filter-on, mud-filter-alt, etc.) so users can easily target them with CSS.

As for the icons themselves, assigning them per column feels like it could get a bit heavy. With @danielchalmers ’ go-ahead, I’d suggest adding parameters for the icons at the MudDataGrid level using the defaults you’ve proposed. The column-level parameters could remain but simply fall back to the grid-level defaults. That way, users can set them once on the grid and override them per column if needed. Let’s wait for DC to confirm if that approach works before moving forward.

As a final note, we will also need a unit test for the filter icons and a unit test for the sort icons verifying they change.

Great points. I agree that if we don't include color logic then the icons themselves could be moved up to the MudDataGrid level. For sake of simplicity, I would remove the column-level parameters unless there's a solid use-case for that.

@versile2
Copy link
Contributor

@CyrilArtFX Tag me when you've made the changes. Thank you!

@mudbot mudbot bot added the needs: changes A maintainer has asked for further modifications to be made to this pull request label Sep 21, 2025
@CyrilArtFX
Copy link
Contributor Author

I'll start working on the changes very soon, I'll let you know when they're done.

@CyrilArtFX
Copy link
Contributor Author

@versile2 I just have a question to be sure I'm doing the changes you expect, you said that the filter icons parameters should be at the DataGrid level, and Daniel said that the override at Column level isn't necessary, so that's good for me, but what do I do for the sort icon?
The parameter at Column level already exists in the release version of MudBlazor, and it doesn't exist at DataGrid level. Should I:

  • move it to harmonize with the filter icons at the risk of it being a breaking change for many apps
  • add the parameter at DataGrid level and keep the parameter at Column level as override
  • don't change anything on the sort icon and focus this PR on the filter icons

@versile2
Copy link
Contributor

@versile2 I just have a question to be sure I'm doing the changes you expect, you said that the filter icons parameters should be at the DataGrid level, and Daniel said that the override at Column level isn't necessary, so that's good for me, but what do I do for the sort icon? The parameter at Column level already exists in the release version of MudBlazor, and it doesn't exist at DataGrid level. Should I:

* move it to harmonize with the filter icons at the risk of it being a breaking change for many apps

* add the parameter at DataGrid level and keep the parameter at Column level as override

* don't change anything on the sort icon and focus this PR on the filter icons

Option 2 with an obsolete on column parameter would be best.

V

@CyrilArtFX
Copy link
Contributor Author

CyrilArtFX commented Sep 23, 2025

@versile2 I made the changes to move the icons parameters in the DataGrid component, remove the color parameters and add a Unit Test for the icons.
Some notes on these changes:

  • I found that the filter icons already have associated class (filter-button and filter-button.filtered) so there is no need to do any changes on that, it is already possible to change their colors with CSS (tested and working).
  • I tried to find an simple way to add a "SortIcon" parameter in the DataGrid and keep the Column one for override, but I couldn't do this easily. Since I made this PR for the filter icons (I originally added a color parameter for the sort just because it was easy to do), I didn't want to take too much time on this and decided to just remove any change related to the sort icon.
  • The "unrealted changes" the AI pointed out were all linked to the sort icon changes, so I didn't fix them, I can still do it if you want but since they are not anymore in the scope of this PR, I believe it's better to keep it like this. Also for the aria-label problem, its content would be what's inside of the title, so I'm not sure how it's supposed to work.
  • The unit test check the icons in a weird way, but it's the only way I found that gave the correct result, otherwise I had issues with the html format that made the unit test fail every time.

@CyrilArtFX CyrilArtFX changed the title MudDataGrid: Add parameters for sort and filter icons MudDataGrid: Add parameters for filter icons Sep 23, 2025
.ToList().First();
filterFilledButton.Html().Should().Contain(expectedFilterFilledIconPath);
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The easiest way I find is to look at other components and see how they test it. In IconTests.cs there is a similar approach to this:

        [Test]
        public void DataGridFilterIconsTest2()
        {
            var comp = Context.RenderComponent<DataGridFilterIconsTest>();
            MudIconButton firstButton() =>
                comp.FindComponents<MudIconButton>().Where(x => x.Markup.Contains("filter-button")).FirstOrDefault().Instance;

            var mudIconButton = firstButton();
            mudIconButton.Icon.Should().Be(Icons.Material.Filled.Battery0Bar);

            comp.Find("button.filter-button").Click();

            mudIconButton = firstButton();
            mudIconButton.Icon.Should().Be(Icons.Material.Filled.BatteryFull);
        }

That being said your test works. I do want to make sure this applies to all 3 modes of DataGridFilterMode though, the one you test is just Simple. Maybe make that a parameter you can pass and do testcases for the first the simple and ColumnMenu and a separate tests for ColumnFilterRow option?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your suggestion, it will make the test easier to understand, and it helped me expanding the test to other filter modes. I tried yesterday to search in other unit tests to understand how it would work to properly test an icon, but couldn't succeed.
I updated the unit test to be more complete, and also had to add a class filter-button clear to the clear filter button of the filter mode "ColumnFilterRow" to be able to find it in the unit test. It also allows it to be colored with CSS (again, tested and working).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can always ping me here or on discord if something stumps you. I've been through a lot of the Mud code at some point.

@danielchalmers
Copy link
Member

  • The "unrealted changes" the AI pointed out were all linked to the sort icon changes, so I didn't fix them, I can still do it if you want but since they are not anymore in the scope of this PR, I believe it's better to keep it like this. Also for the aria-label problem, its content would be what's inside of the title, so I'm not sure how it's supposed to work.

Please feel free to ignore the out-of-scope review from the bot

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement Adds a new feature or enhances existing functionality (not fixing a defect) in the main library needs: changes A maintainer has asked for further modifications to be made to this pull request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants