Summary
FluentOverflow currently renders all FluentOverflowItem children as DOM elements, then uses JavaScript interop (MutationObserver/ResizeObserver) to detect which ones overflow. When there are hundreds or thousands of items, this forces an expensive browser reflow that can block the UI thread long enough to kill a Blazor Server SignalR connection (~10+ seconds of unresponsive layout).
Problem
In the Aspire Dashboard, we use FluentOverflow to display resource URLs and metric filter tags. Some resources can have hundreds of URLs or filter dimension values. Rendering all of them as DOM elements triggers a forced reflow that's catastrophically expensive — in our case, it disconnects the SignalR connection entirely.
The component only ever displays a handful of items (the ones that fit in the available space), so rendering all items into the DOM just to measure which ones overflow is wasteful when the item count is large.
Current Workaround
We manually cap the number of items passed into ChildContent and track a "pre-overflowed" count to include in the +N badge:
@{
var maxRenderedUrls = 20;
var renderedUrls = DisplayedUrls.Take(maxRenderedUrls).ToList();
var preOverflowedCount = DisplayedUrls.Count - renderedUrls.Count;
}
<FluentOverflow>
<ChildContent>
@for (var i = 0; i < renderedUrls.Count; i++)
{
<FluentOverflowItem Data="renderedUrls[i]">...</FluentOverflowItem>
}
</ChildContent>
<MoreButtonTemplate Context="overflow">
<FluentButton>@($"+{overflow.ItemsOverflow.Count() + preOverflowedCount}")</FluentButton>
</MoreButtonTemplate>
<OverflowTemplate Context="overflow">
@* Must manually concat pre-overflowed items into the popup *@
@foreach (var item in overflow.ItemsOverflow.Select(i => i.Data).Concat(allItems.Skip(maxRenderedUrls)))
{
...
}
</OverflowTemplate>
</FluentOverflow>
This works but requires every consumer to duplicate the same capping logic and manually merge pre-overflowed items into templates.
Proposed Solution
Add a MaxRenderedItems parameter (or similar) to FluentOverflow:
/// <summary>
/// Maximum number of items to render as DOM elements for overflow measurement.
/// Items beyond this limit are treated as pre-overflowed without being added to the DOM.
/// When null (default), all items are rendered (current behavior).
/// </summary>
[Parameter]
public int? MaxRenderedItems { get; set; }
When set, the component would:
- Only render the first
MaxRenderedItems items as FluentOverflowItem DOM elements
- Automatically include the remaining items in
ItemsOverflow (and thus in MoreButtonTemplate / OverflowTemplate counts and collections)
- Preserve the existing
Data property on overflow items so consumers can still access the underlying data in templates
This keeps backward compatibility (default is null = render all, same as today) while giving consumers a simple escape hatch for large collections.
Environment
- Package: Microsoft.FluentUI.AspNetCore.Components 4.14.1
- Scenario: Blazor Server with SignalR (most sensitive to long UI thread blocks)
- Scale: 100-500+ items in a single
FluentOverflow
Summary
FluentOverflowcurrently renders allFluentOverflowItemchildren as DOM elements, then uses JavaScript interop (MutationObserver/ResizeObserver) to detect which ones overflow. When there are hundreds or thousands of items, this forces an expensive browser reflow that can block the UI thread long enough to kill a Blazor Server SignalR connection (~10+ seconds of unresponsive layout).Problem
In the Aspire Dashboard, we use
FluentOverflowto display resource URLs and metric filter tags. Some resources can have hundreds of URLs or filter dimension values. Rendering all of them as DOM elements triggers a forced reflow that's catastrophically expensive — in our case, it disconnects the SignalR connection entirely.The component only ever displays a handful of items (the ones that fit in the available space), so rendering all items into the DOM just to measure which ones overflow is wasteful when the item count is large.
Current Workaround
We manually cap the number of items passed into
ChildContentand track a "pre-overflowed" count to include in the+Nbadge:This works but requires every consumer to duplicate the same capping logic and manually merge pre-overflowed items into templates.
Proposed Solution
Add a
MaxRenderedItemsparameter (or similar) toFluentOverflow:When set, the component would:
MaxRenderedItemsitems asFluentOverflowItemDOM elementsItemsOverflow(and thus inMoreButtonTemplate/OverflowTemplatecounts and collections)Dataproperty on overflow items so consumers can still access the underlying data in templatesThis keeps backward compatibility (default is
null= render all, same as today) while giving consumers a simple escape hatch for large collections.Environment
FluentOverflow