Skip to content

Migrate dashboard to Fluent UI Blazor v5 - #19431

Merged
James Newton-King (JamesNK) merged 15 commits into
mainfrom
jamesnk/fluentui-v5-dashboard
Sep 9, 2026
Merged

Migrate dashboard to Fluent UI Blazor v5#19431
James Newton-King (JamesNK) merged 15 commits into
mainfrom
jamesnk/fluentui-v5-dashboard

Conversation

@JamesNK

@JamesNK James Newton-King (JamesNK) commented Aug 17, 2026

Copy link
Copy Markdown
Member

Description

Migrates the Aspire Dashboard from Fluent UI Blazor v4 to v5 so the Dashboard can adopt the current component model and continue receiving Fluent UI fixes. The Dashboard references the Fluent UI Blazor v5 component package and its matching v5 icon package. Both packages contain .NET 8 assets. The Dashboard and Dashboard tests use $(DefaultTargetFramework) (currently net8.0), and Dashboard packaging remains on net8.0.

The v5 packages are restored from the existing dotnet9 feed; the Fluent UI mappings should move back to dotnet-public when v5 is public. .NET 8 compatibility includes DI-backed Blazor component activation and guarded certificate-loading APIs. The temporary .NET 9 hosting runtime-selection workaround and cross-framework test-reference metadata have been removed.

The migration replaces removed v4 component APIs and services across dialogs, notifications, menus, grids, tabs, trees, selectors, inputs, splitters, and test infrastructure. It also removes the legacy app.css and tokens.css files and establishes a smaller shared layout stylesheet for the v5 controls.

User-facing behavior restored or updated as part of the migration includes:

  • Responsive filter toolbars that align controls to the end, use bounded search widths, and wrap without horizontal scrollbars.
  • Working resource, level, type, and duration selectors with stable sizing and pointer interaction.
  • Search icons and correctly slotted v5 text inputs.
  • Metrics and GenAI tree selection/expansion state restored through the v5 tree APIs.
  • Determinate trace duration indicators.
  • A collapsible desktop navigation rail with persisted icon-only and icon-plus-label modes.
  • Stable Resources graph, tab, details, grid, and footer layouts.
  • Text Visualizer header and footer styling aligned with v4, with shared vertically centered dropdown text.
  • Empty states aligned with v4 across Resources, Structured Logs, Traces, and detail property grids.
  • Shared v4 status-icon colors and centrally declared light/dark theme variables.

User-facing usage

Dashboard users can continue navigating and filtering Resources, Console Logs, Structured Logs, Traces, and Metrics with the same workflows. The desktop navigation can now be expanded to show page labels or collapsed to icons, and the selected mode persists across reloads.

Screenshots / Recordings

This PR includes UI changes. Please add screenshots or screen recordings so reviewers can evaluate the visual changes without running locally.

  • For before/after comparisons, place them side-by-side or label them clearly.
  • For interactive changes (animations, transitions, new flows), prefer a short screen recording (GIF or video).
  • If you cannot capture visuals now, note what scenario to test and mark this section as TODO.

Validation

  • .NET 8 Dashboard build passed; NuGet asset inspection confirmed both Fluent UI packages select their lib/net8.0 compile/runtime assets.
  • Fluent UI v5/.NET 8 validation: 295 component tests and 1,732 non-browser Dashboard tests passed, excluding quarantined and outerloop tests.
  • After removing the temporary hosting workaround, all 40 DashboardEventHandlersTests passed.
  • MSBuild evaluation confirmed the Dashboard, its tests, Hosting.Testing tests, and all seven Dashboard packaging projects resolve to net8.0; restored project-reference framework negotiation passed. A full packaging run was not performed for this cleanup.
  • Live TestShop smoke testing confirmed runtime .NET 8.0.21, resource rendering, Settings, and Text Visualizer format selection.
  • Playwright regressions cover shared responsive toolbars, selector visibility and interaction, Resources graph layout, trace duration indicators, and desktop navigation expansion/persistence.
  • TestShop was used for manual validation across Resources, Console Logs, Structured Logs, Traces, Trace Detail, and Metrics on desktop and mobile-sized viewports.

Fixes # (issue)

Checklist

  • Is this feature complete?
    • Yes. Ready to ship.
    • No. Follow-up changes expected.
  • Are you including unit tests for the changes and scenario tests if relevant?
    • Yes
    • No
  • Did you add public API?
    • Yes
      • If yes, did you have an API Review for it?
        • Yes
        • No
      • Did you add <remarks /> and <code /> elements on your triple slash comments?
        • Yes
        • No
    • No
  • Does the change make any security assumptions or guarantees?
    • Yes
      • If yes, have you done a threat model and had a security review?
        • Yes
        • No
    • No

Copilot AI balanced review requested due to automatic review settings August 17, 2026 09:20
@github-actions

Copy link
Copy Markdown
Contributor

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 19431

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 19431"

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Migrates the Aspire Dashboard to Fluent UI Blazor v5 and .NET 9 while updating component behavior, styling, dialogs, navigation, and tests.

Changes:

  • Updates Fluent UI packages and Dashboard targets.
  • Migrates removed v4 component APIs and introduces shared layout/dialog services.
  • Adds and updates bUnit and Playwright regression coverage.

Reviewed changes

Copilot reviewed 177 out of 177 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
tests/Shared/TestCertificateLoader.cs Uses modern certificate loading.
tests/Shared/Telemetry/TelemetryTestHelpers.cs Updates PKCS#12 loading.
tests/Aspire.Dashboard.Tests/Model/ResourceStateViewModelTests.cs Updates expected icon color.
tests/Aspire.Dashboard.Tests/Integration/StartupTests.cs Adjusts CSP assertion.
tests/Aspire.Dashboard.Tests/Integration/ResponseCompressionTests.cs Tests new stylesheet.
tests/Aspire.Dashboard.Tests/Integration/Playwright/TracesLayoutTests.cs Tests duration indicators.
tests/Aspire.Dashboard.Tests/Integration/Playwright/ResourcesTests.cs Adds graph layout coverage.
tests/Aspire.Dashboard.Tests/Integration/Playwright/ResourceSelectInteractionTests.cs Tests selector interaction.
tests/Aspire.Dashboard.Tests/Integration/Playwright/DesktopNavMenuTests.cs Tests navigation persistence.
tests/Aspire.Dashboard.Tests/Integration/Playwright/DashboardInteractionsTests.cs Updates resize-handle detection.
tests/Aspire.Dashboard.Tests/Integration/Playwright/AspireMenuButtonFocusTests.cs Updates menu focus test.
tests/Aspire.Dashboard.Tests/Aspire.Dashboard.Tests.csproj Targets .NET 9.
tests/Aspire.Dashboard.Components.Tests/Shared/TestMessageService.cs Removes obsolete test service.
tests/Aspire.Dashboard.Components.Tests/Pages/TraceDetailsTests.cs Updates toolbar/grid assertions.
tests/Aspire.Dashboard.Components.Tests/Pages/ResourcesTests.cs Migrates component interactions.
tests/Aspire.Dashboard.Components.Tests/Pages/MetricsTests.cs Adds tree-selection coverage.
tests/Aspire.Dashboard.Components.Tests/Pages/LoginTests.cs Updates login rendering setup.
tests/Aspire.Dashboard.Components.Tests/Pages/ConsoleLogsTerminalTests.cs Migrates selectors and search.
tests/Aspire.Dashboard.Components.Tests/Layout/MobileNavMenuTests.cs Updates navigation assertion comment.
tests/Aspire.Dashboard.Components.Tests/Dialogs/ManageDataDialogTests.cs Stabilizes dialog tests.
tests/Aspire.Dashboard.Components.Tests/Dialogs/InteractionsInputDialogTests.cs Migrates dialog test infrastructure.
tests/Aspire.Dashboard.Components.Tests/Dialogs/FilterDialogTests.cs Updates v5 input assertions.
tests/Aspire.Dashboard.Components.Tests/Controls/UrlsColumnDisplayTests.cs Updates overflow assertions.
tests/Aspire.Dashboard.Components.Tests/Controls/ResourceSelectTests.cs Adds selector display test.
tests/Aspire.Dashboard.Components.Tests/Controls/ResourceDetailsTests.cs Updates menu ownership tests.
tests/Aspire.Dashboard.Components.Tests/Controls/AspireMenuTests.cs Migrates menu behavior tests.
tests/Aspire.Dashboard.Components.Tests/Controls/AspireMenuButtonTests.cs Updates menu-button tests.
tests/Aspire.Dashboard.Components.Tests/Aspire.Dashboard.Components.Tests.csproj Targets .NET 9.
src/Aspire.Dashboard/wwwroot/js/app.js Migrates grid resize handling.
src/Aspire.Dashboard/wwwroot/css/markdown.css Replaces removed font token.
src/Aspire.Dashboard/wwwroot/css/layout.css Adds shared v5 layout styles.
src/Aspire.Dashboard/Utils/DashboardUIHelpers.cs Migrates message bars.
src/Aspire.Dashboard/ServiceClient/DashboardClient.cs Modernizes certificate loading.
src/Aspire.Dashboard/Otlp/Storage/TelemetryRepository.cs Stores new message references.
src/Aspire.Dashboard/Model/TraceLinkHelpers.cs Migrates message-box dialogs.
src/Aspire.Dashboard/Model/ThemeManager.cs Updates theme documentation.
src/Aspire.Dashboard/Model/ResourceStateViewModel.cs Updates default icon color.
src/Aspire.Dashboard/Model/MenuButtonItem.cs Migrates roles and IDs.
src/Aspire.Dashboard/Model/Interaction/InteractionMessageBoxContent.cs Adds message-box content model.
src/Aspire.Dashboard/Model/Interaction/InputViewModel.cs Updates input terminology.
src/Aspire.Dashboard/Model/INotificationService.cs Migrates notification intent.
src/Aspire.Dashboard/Model/DashboardMessageBarService.cs Adds message-bar abstraction.
src/Aspire.Dashboard/Model/DashboardDialogParameters.cs Adds dialog abstractions.
src/Aspire.Dashboard/Extensions/ComponentExtensions.cs Forces grid refreshes.
src/Aspire.Dashboard/DashboardWebApplication.cs Registers migrated services.
src/Aspire.Dashboard/Configuration/DashboardOptions.cs Modernizes certificate loading.
src/Aspire.Dashboard/Components/ResourcesGridColumns/UrlsColumnDisplay.razor Migrates overflow/popover APIs.
src/Aspire.Dashboard/Components/ResourcesGridColumns/UnreadLogErrorsBadge.razor Migrates badge and link.
src/Aspire.Dashboard/Components/ResourcesGridColumns/ResourceNameDisplay.razor Updates icon color.
src/Aspire.Dashboard/Components/ResourcesGridColumns/LogMessageColumnDisplay.razor Migrates button appearance.
src/Aspire.Dashboard/Components/Pages/Traces.razor.css Styles determinate progress bars.
src/Aspire.Dashboard/Components/Pages/Traces.razor.cs Migrates grid and dialogs.
src/Aspire.Dashboard/Components/Pages/TraceDetail.razor.css Updates trace-detail layout.
src/Aspire.Dashboard/Components/Pages/TraceDetail.razor.cs Migrates dialog results.
src/Aspire.Dashboard/Components/Pages/StructuredLogs.razor.css Stabilizes grid layout.
src/Aspire.Dashboard/Components/Pages/StructuredLogs.razor.cs Migrates message and grid APIs.
src/Aspire.Dashboard/Components/Pages/StructuredLogs.razor Rebuilds filter toolbar.
src/Aspire.Dashboard/Components/Pages/Resources.razor.css Updates responsive toolbar layout.
src/Aspire.Dashboard/Components/Pages/Resources.razor.cs Migrates tab lifecycle handling.
src/Aspire.Dashboard/Components/Pages/Metrics.razor Migrates selectors and splitter.
src/Aspire.Dashboard/Components/Pages/Login.razor.cs Migrates text-input focus.
src/Aspire.Dashboard/Components/Pages/Login.razor Migrates login controls.
src/Aspire.Dashboard/Components/Pages/ConsoleLogs.razor.cs Migrates menu roles.
src/Aspire.Dashboard/Components/Pages/ConsoleLogs.razor Rebuilds console toolbar.
src/Aspire.Dashboard/Components/Layout/ToolbarPanel.razor Migrates mobile toolbar.
src/Aspire.Dashboard/Components/Layout/ReconnectModal.razor Updates button appearances.
src/Aspire.Dashboard/Components/Layout/NotificationsHeaderButton.razor Migrates notification controls.
src/Aspire.Dashboard/Components/Layout/MobileNavMenu.razor Migrates mobile menu rendering.
src/Aspire.Dashboard/Components/Layout/MainLayout.razor.cs Migrates themes and dialogs.
src/Aspire.Dashboard/Components/Layout/DesktopToolbarDivider.razor Removes obsolete slot.
src/Aspire.Dashboard/Components/Layout/AspirePageContentLayout.razor.css Stabilizes page layout.
src/Aspire.Dashboard/Components/Layout/AspirePageContentLayout.razor.cs Migrates toolbar dialog reference.
src/Aspire.Dashboard/Components/Layout/AspirePageContentLayout.razor Replaces Fluent toolbars.
src/Aspire.Dashboard/Components/Dialogs/TextVisualizerDialog.razor.cs Migrates dialog reference.
src/Aspire.Dashboard/Components/Dialogs/TextVisualizerDialog.razor Migrates dialog content.
src/Aspire.Dashboard/Components/Dialogs/SettingsDialog.razor.cs Migrates dialog instance.
src/Aspire.Dashboard/Components/Dialogs/SettingsDialog.razor Migrates language selector.
src/Aspire.Dashboard/Components/Dialogs/NotificationsDialog.razor.cs Migrates notification dialog.
src/Aspire.Dashboard/Components/Dialogs/NotificationsDialog.razor Updates v5 appearances.
src/Aspire.Dashboard/Components/Dialogs/NotificationEntryComponent.razor.cs Migrates intents and actions.
src/Aspire.Dashboard/Components/Dialogs/NotificationEntryComponent.razor Updates notification controls.
src/Aspire.Dashboard/Components/Dialogs/ManageDataDialog.razor.cs Removes obsolete interface.
src/Aspire.Dashboard/Components/Dialogs/ManageDataDialog.razor Migrates grid and buttons.
src/Aspire.Dashboard/Components/Dialogs/InteractionsProgressDialog.razor.cs Migrates dialog instance.
src/Aspire.Dashboard/Components/Dialogs/InteractionsProgressDialog.razor Migrates progress dialog UI.
src/Aspire.Dashboard/Components/Dialogs/InteractionsInputDialog.razor.cs Migrates input references.
src/Aspire.Dashboard/Components/Dialogs/InteractionMessageBoxDialog.razor Adds message-box component.
src/Aspire.Dashboard/Components/Dialogs/HelpDialog.razor Replaces Fluent anchor.
src/Aspire.Dashboard/Components/Dialogs/GenAIVisualizerDialog.razor.cs Migrates nullable tab events.
src/Aspire.Dashboard/Components/Dialogs/FilterDialog.razor.cs Migrates dialog instance.
src/Aspire.Dashboard/Components/Dialogs/FilterDialog.razor Migrates filter controls.
src/Aspire.Dashboard/Components/Dialogs/ExemplarsDialog.razor Updates button appearance.
src/Aspire.Dashboard/Components/Dialogs/AIAgentsDialog.razor.cs Removes obsolete interface.
src/Aspire.Dashboard/Components/Dialogs/AIAgentsDialog.razor Migrates dialog header.
src/Aspire.Dashboard/Components/Controls/UserProfile.razor Replaces removed profile menu.
src/Aspire.Dashboard/Components/Controls/TreeMetricSelector.razor.cs Adds tree state management.
src/Aspire.Dashboard/Components/Controls/TreeMetricSelector.razor Migrates metric tree selection.
src/Aspire.Dashboard/Components/Controls/TreeGenAISelector.razor.cs Adds stable tree IDs.
src/Aspire.Dashboard/Components/Controls/TreeGenAISelector.razor Migrates GenAI tree selection.
src/Aspire.Dashboard/Components/Controls/TraceActions.razor Updates menu appearance.
src/Aspire.Dashboard/Components/Controls/SummaryDetailsView.razor.cs Migrates splitter state.
src/Aspire.Dashboard/Components/Controls/SummaryDetailsView.razor Migrates multi-splitter markup.
src/Aspire.Dashboard/Components/Controls/StructuredLogDetails.razor Rebuilds details toolbar.
src/Aspire.Dashboard/Components/Controls/StructuredLogActions.razor Updates menu appearance.
src/Aspire.Dashboard/Components/Controls/SpanTypeSelect.razor Migrates span selector.
src/Aspire.Dashboard/Components/Controls/SpanDetails.razor.cs Removes obsolete grid labels.
src/Aspire.Dashboard/Components/Controls/SpanActions.razor Updates menu appearance.
src/Aspire.Dashboard/Components/Controls/ResourceSelectOptionTemplate.razor Fixes pointer interaction.
src/Aspire.Dashboard/Components/Controls/ResourceSelect.razor.cs Removes obsolete binding workaround.
src/Aspire.Dashboard/Components/Controls/ResourceSelect.razor Migrates resource selector.
src/Aspire.Dashboard/Components/Controls/ResourceDetails.razor.cs Removes obsolete grid labels.
src/Aspire.Dashboard/Components/Controls/ResourceActions.razor.css Replaces removed spacing tokens.
src/Aspire.Dashboard/Components/Controls/ResourceActions.razor Updates action appearances.
src/Aspire.Dashboard/Components/Controls/PropertyValues/TraceIdButtonValue.razor Updates link-button appearance.
src/Aspire.Dashboard/Components/Controls/PropertyValues/SpanKindValue.razor Updates icon color.
src/Aspire.Dashboard/Components/Controls/PropertyValues/SpanIdButtonValue.razor Updates link-button appearance.
src/Aspire.Dashboard/Components/Controls/PropertyValues/ResourceNameButtonValue.razor Updates link-button appearance.
src/Aspire.Dashboard/Components/Controls/PropertyValues/IconValue.razor Updates icon color.
src/Aspire.Dashboard/Components/Controls/PropertyGrid.razor.cs Migrates generated-header API.
src/Aspire.Dashboard/Components/Controls/PropertyGrid.razor Removes obsolete grid labels.
src/Aspire.Dashboard/Components/Controls/PauseIncomingDataSwitch.razor Updates button appearance.
src/Aspire.Dashboard/Components/Controls/LogLevelSelect.razor Migrates log-level selector.
src/Aspire.Dashboard/Components/Controls/InteractionInputField.razor.cs Removes Fluent base class.
src/Aspire.Dashboard/Components/Controls/InteractionInputField.razor Migrates labels and spinner.
src/Aspire.Dashboard/Components/Controls/IconCheckbox.razor.cs Updates unchecked icon color.
src/Aspire.Dashboard/Components/Controls/GridValue.razor Updates action appearances.
src/Aspire.Dashboard/Components/Controls/Grid/AspireTemplateColumn.cs Removes redundant column ID.
src/Aspire.Dashboard/Components/Controls/Grid/AspirePropertyColumn.cs Removes redundant column ID.
src/Aspire.Dashboard/Components/Controls/FluentIconSwitch.razor Migrates appearance type.
src/Aspire.Dashboard/Components/Controls/ExceptionDetails.razor Updates button and icon.
src/Aspire.Dashboard/Components/Controls/DetailView.razor Updates header actions.
src/Aspire.Dashboard/Components/Controls/DashboardMessageBar.razor Adds message-bar renderer.
src/Aspire.Dashboard/Components/Controls/ClearSignalsButton.razor Migrates clear menu styling.
src/Aspire.Dashboard/Components/Controls/Chart/MetricTable.razor Updates exemplar button.
src/Aspire.Dashboard/Components/Controls/Chart/ChartFilterTags.razor.cs Removes obsolete overflow metadata.
src/Aspire.Dashboard/Components/Controls/Chart/ChartFilterTags.razor Migrates overflow templates.
src/Aspire.Dashboard/Components/Controls/Chart/ChartFilters.razor Migrates generated-header API.
src/Aspire.Dashboard/Components/Controls/Chart/ChartFilterPopover.razor Migrates popover controls.
src/Aspire.Dashboard/Components/Controls/Chart/ChartContainer.razor.cs Migrates tab lifecycle.
src/Aspire.Dashboard/Components/Controls/Chart/ChartContainer.razor Migrates chart tabs.
src/Aspire.Dashboard/Components/Controls/AspireMenuButton.razor.cs Migrates component lifecycle.
src/Aspire.Dashboard/Components/Controls/AspireMenuButton.razor Restores expanded-state ARIA.
src/Aspire.Dashboard/Components/Controls/AspireMenu.razor.cs Migrates menu state handling.
src/Aspire.Dashboard/Components/Controls/AspireMenu.razor Migrates menu APIs.
src/Aspire.Dashboard/Components/BlazorScript.razor Updates target documentation.
src/Aspire.Dashboard/Components/App.razor Replaces legacy global styles.
src/Aspire.Dashboard/BlazorAssets.targets Updates assets and synchronization.
src/Aspire.Dashboard/Aspire.Dashboard.csproj Targets .NET 9.
eng/dashboardpack/Common.projitems Packages Dashboard for .NET 9.
Directory.Packages.props Updates Fluent UI packages.
Directory.Build.props Updates Dashboard artifact path.

Comment thread src/Aspire.Dashboard/Components/Pages/Login.razor Outdated
Comment thread src/Aspire.Dashboard/Components/Dialogs/SettingsDialog.razor Outdated
Comment thread tests/Aspire.Dashboard.Tests/Integration/Playwright/ResourcesTests.cs Outdated
Comment thread src/Aspire.Dashboard/Model/DashboardMessageBarService.cs Outdated
Comment thread src/Aspire.Dashboard/Components/Controls/DashboardMessageBar.razor Outdated
Copilot AI review requested due to automatic review settings August 17, 2026 23:01

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 179 out of 179 changed files in this pull request and generated no new comments.

Suppressed comments (5)

src/Aspire.Dashboard/Components/Dialogs/SettingsDialog.razor:26

  • TOption is specified twice on the same component. Razor reports duplicate component parameters, so the Dashboard project cannot compile until the second attribute is removed.
    src/Aspire.Dashboard/Components/Pages/Login.razor:26
  • FluentTextInput v5 uses TextInputType; TextFieldType is no longer a component parameter and is emitted only as an unmatched HTML attribute. The underlying input therefore remains a plain text input and exposes the dashboard token instead of masking it.
    tests/Aspire.Dashboard.Tests/Integration/Playwright/ResourcesTests.cs:116
  • This test navigates directly to the Graph URL, so it never exercises the tab switch or ActiveTabChanged. It would still pass if clicking Graph caused a full reload or failed to update the layout. Start on the table view, record the navigation count, click graphTab, and then assert the graph and unchanged count.
    src/Aspire.Dashboard/Components/Controls/DashboardMessageBar.razor:34
  • This introduces an unlocalized visible label and accessible name. Dashboard notification actions already localize the equivalent text via Dialogs.NotificationEntryDismiss (see Components/Dialogs/NotificationEntryComponent.razor:18); inject the dialog localizer here and use a resource string for both values.
    @if (Content.AllowDismiss)
    {
        <FluentButton OnClick="@(() => CloseAsync(null))" aria-label="Dismiss">Dismiss</FluentButton>
    }

src/Aspire.Dashboard/Components/Controls/AspireMenu.razor.cs:132

  • The edge calculation reserves only 200px, but this menu is allowed to grow to 368px below. Near the right viewport edge, a menu wider than 200px is positioned at clientX - 200 and can overflow by up to 168px. Use the same maximum width for placement (or measure the rendered menu).
            const int estimatedMenuWidth = 200;
            _targetOffsetLeft = clientX + estimatedMenuWidth > screenWidth
                ? Math.Max(0, clientX - estimatedMenuWidth)

Copilot AI review requested due to automatic review settings August 18, 2026 01:56

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 179 out of 179 changed files in this pull request and generated no new comments.

Suppressed comments (5)

src/Aspire.Dashboard/Components/Dialogs/SettingsDialog.razor:25

  • TOption is specified again on the next line. Razor rejects duplicate component parameters, so the Dashboard project will not compile until the duplicate is removed.
    src/Aspire.Dashboard/Components/Controls/DashboardMessageBar.razor:33
  • This newly rendered button text and accessible name are hardcoded in English, so message-bar dismissal is not localized. Use the existing localized dismissal resource (for example, the pattern in Components/Dialogs/NotificationEntryComponent.razor:18) for both the label and visible text.
        <FluentButton OnClick="@(() => CloseAsync(null))" aria-label="Dismiss">Dismiss</FluentButton>

src/Aspire.Dashboard/wwwroot/css/layout.css:64

  • The removed legacy stylesheets were the only source of the --layout-left-padding and --layout-right-padding custom properties; no definitions remain in src/Aspire.Dashboard. Consequently this entire padding declaration is invalid at computed-value time, and the migrated toolbars lose their page gutters. Define the layout variables in this shared stylesheet (including --layout-top-padding, which is still used elsewhere) or replace all remaining uses with concrete values.
    Directory.Build.props:58
  • The target-framework migration leaves the CLI's generated in-repo AppHost project pointing at artifacts/bin/Aspire.Dashboard/Debug/net8.0/ in src/Aspire.Cli/Projects/DotNetBasedAppHostServerProject.cs:156. Since this project now emits under net9.0, CLI local-development launches will receive a nonexistent dashboard directory. Update that hardcoded path as part of this migration.
    <AspireDashboardDir>$(MSBuildThisFileDirectory)/artifacts/bin/Aspire.Dashboard/$(Configuration)/net9.0/</AspireDashboardDir>

src/Aspire.Dashboard/Components/Pages/Login.razor:47

  • Appearance is a Fluent component parameter, but this element is now a native <a>. The browser only receives an inert Appearance="ButtonAppearance.Subtle" attribute, so the intended link appearance is not applied. Use a CSS class supported by the native anchor (or a supported Fluent link component) instead.

Copilot AI review requested due to automatic review settings August 18, 2026 02:32

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 180 out of 180 changed files in this pull request and generated 1 comment.

Suppressed comments (3)

src/Aspire.Dashboard/Components/Dialogs/SettingsDialog.razor:26

  • TOption is specified twice on this component, which causes Razor's duplicate-parameter diagnostic and prevents the Dashboard project from compiling. Keep the v5 TOption/TValue pair and remove the second TOption.
    src/Aspire.Dashboard/Components/Controls/DashboardMessageBar.razor:34
  • The new dismiss control hard-codes an English user-facing label, so localized Dashboard sessions now show untranslated text. Use the existing localized Dialogs.NotificationEntryDismiss resource, as NotificationEntryComponent.razor:17-20 already does for the equivalent action.
    @if (Content.AllowDismiss)
    {
        <FluentButton OnClick="@(() => CloseAsync(null))" aria-label="Dismiss">Dismiss</FluentButton>
    }

src/Aspire.Dashboard/Components/Controls/DashboardMessageBar.razor:8

  • This renders Title as plain text, but InteractionsProvider still passes WebUtility.HtmlEncode(item.Title). Blazor therefore encodes the value a second time, so titles containing &, <, or similar characters display HTML entities to users. Define Title as plain text and stop pre-encoding that caller (while retaining encoding/sanitization for markup message bodies).
    @if (!string.IsNullOrEmpty(Content.Title))
    {
        <strong>@Content.Title</strong>
    }

Comment thread src/Aspire.Dashboard/Components/App.razor Outdated
Copilot AI review requested due to automatic review settings August 18, 2026 03:33
@github-actions

This comment has been minimized.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 180 out of 180 changed files in this pull request and generated no new comments.

Suppressed comments (6)

src/Aspire.Dashboard/Components/Dialogs/SettingsDialog.razor:26

  • TOption is specified twice on the same component, which causes Razor's duplicate-attribute diagnostic and prevents the dashboard project from building. Keep only the declaration that also adds TValue.
    src/Aspire.Dashboard/Components/Pages/Login.razor:26
  • FluentTextInput v5 exposes TextInputType, not TextFieldType. Because unmatched attributes are forwarded, this silently leaves the login token control as a normal text input, exposing the authentication token on screen instead of masking it.
    src/Aspire.Dashboard/Components/Controls/DashboardMessageBar.razor:33
  • The newly rendered button text and accessible name are hard-coded, so localized dashboard sessions now show English here. Dashboard controls consistently source user-facing labels from resources (for example, NotificationEntryComponent.razor:18-20), and Dialogs.NotificationEntryDismiss already provides the appropriate localized label.
        <FluentButton OnClick="@(() => CloseAsync(null))" aria-label="Dismiss">Dismiss</FluentButton>

src/Aspire.Dashboard/wwwroot/css/layout.css:64

  • This padding declaration now depends on --layout-left-padding and --layout-right-padding, but neither custom property is defined anywhere in the loaded dashboard styles after tokens.css/app.css were removed. Browsers therefore discard the whole declaration, and the shared desktop toolbars lose their intended page gutters. Define these layout tokens in layout.css (also covering the remaining component CSS references) or replace the references with concrete values.
    src/Aspire.Dashboard/Components/Controls/UserProfile.razor:8
  • The replacement <details> content has no positioning styles: the remaining UserProfile.razor.css rules target the removed Fluent profile/persona elements and there are no rules for details or summary. Opening the profile therefore inserts the account panel into normal header flow instead of displaying a popup, expanding and shifting the dashboard header. Add popup/trigger styling for the new markup or replace it with a v5 popover/menu component.
    src/Aspire.Dashboard/Components/Controls/DashboardMessageBar.razor:7
  • This renders Title as ordinary Razor text, but interaction notifications pass WebUtility.HtmlEncode(item.Title). Razor encodes that value again, so titles containing &, <, or similar characters are displayed as HTML entities. Keep this safe text rendering and stop pre-encoding the title at the interaction caller.
        <strong>@Content.Title</strong>

Copilot AI review requested due to automatic review settings August 18, 2026 06:45

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 185 out of 185 changed files in this pull request and generated 1 comment.

Suppressed comments (4)

src/Aspire.Dashboard/Components/ResourcesGridColumns/UrlsColumnDisplay.razor:24

  • MaxRenderedItems only limits how many overflow records Fluent returns to Blazor; it does not limit these DOM children. Iterating every URL here therefore restores the hundreds-of-elements layout/reflow path that the removed Take(20) explicitly avoided, including the SignalR disconnect regression. Keep the child list capped and add the unrendered remainder back into the badge/popover calculation.
    src/Aspire.Dashboard/Components/Controls/Chart/ChartFilterTags.razor:17
  • MaxRenderedItems limits only the overflow metadata returned to Blazor, not the number of child elements rendered. This loop now puts every dimension value into the DOM, reintroducing the expensive layout behavior that the removed Take(MaxRenderedTags) guarded against for high-cardinality metrics. Cap the rendered values and account for the remaining values in the badge/selection logic.
        @foreach (var item in orderedValues)
        {
            var isIncludedInFilters = Filter.SelectedValues.Contains(item);
            var isIncludedInFiltersClass = isIncludedInFilters ? "included-in-filters" : "";
            // Always display the first item by setting a fixed value.
            <div behavior="@(i == 0 ? "fixed" : null)">

src/Aspire.Dashboard/Components/Controls/AspireMenu.razor:56

  • FluentMenuItem already wraps its MenuItems fragment in a FluentMenuList for the submenu slot. Returning another FluentMenuList here produces nested menu-list elements, so resource URL/command submenus no longer have the direct menu-item structure expected by Fluent and can break submenu interaction and keyboard navigation. Return only the nested items from this fragment.
        return @<FluentMenuList>
            @foreach (var nestedItem in item.NestedMenuItems)
            {
                @RenderMenuItem(nestedItem)
            }

src/Aspire.Dashboard/Components/Controls/UserProfile.razor:9

  • The replacement is rendered inside a 52px header whose CSS sets overflow: hidden, while the existing profile CSS only targets the removed Fluent profile-menu elements. Native <details> keeps this <div> in the header's normal flow, so expanding it clips the account details and sign-out action instead of displaying a popup. Add a properly positioned/light-dismiss profile surface outside the clipped header (and update the obsolete profile CSS).

Comment thread src/Aspire.Dashboard/BlazorAssets.targets
Copilot AI review requested due to automatic review settings August 18, 2026 08:18

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 187 out of 187 changed files in this pull request and generated 1 comment.

Suppressed comments (3)

src/Aspire.Dashboard/Components/Layout/AspirePageContentLayout.razor.cs:101

  • This closing callback now runs for every completed dialog result, including DashboardDialogReference.CloseAsync(). CloseMobileToolbarAsync() still invokes the same listeners manually after calling CloseAsync, so programmatic closure (for example when switching to desktop) notifies every listener twice. Await the reference result and let this callback be the single cleanup path.
    src/Aspire.Dashboard/Components/Controls/AspireMenu.razor.cs:133
  • The context-menu offset reserves 200px, but the same menu is allowed to be 368px wide. Near the right viewport edge, a menu wider than 200px is positioned at clientX - 200 and can still overflow by up to 168px. Reserve the configured maximum width (and add an edge-position regression case) so the menu remains inside the viewport.
            const int estimatedMenuWidth = 200;
            _targetOffsetLeft = clientX + estimatedMenuWidth > screenWidth
                ? Math.Max(0, clientX - estimatedMenuWidth)
                : clientX;

src/Aspire.Dashboard/Components/Dialogs/NotificationEntryComponent.razor.cs:65

  • Primary actions used to hide the notification center while the action ran and then restore it. Closing the dialog here permanently changes that flow: after “View response” opens and is dismissed, the notification center is gone, and even a quick cancel action closes it. The empty finally also confirms the restoration step was lost during the migration. Preserve the temporary hide/restore behavior, or explicitly reopen the notification center after the action completes.

Comment thread src/Aspire.Dashboard/Components/Controls/DashboardMessageBar.razor
@github-actions

Copy link
Copy Markdown
Contributor

Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt.

Copilot AI review requested due to automatic review settings August 18, 2026 10:30
@github-actions

This comment has been minimized.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Fractional duration filtering is regressed, and notification and trace-grid tests omit required behavioral assertions.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details

Suppressed comments (2)

src/Aspire.Dashboard/Components/Layout/DashboardDialogProvider.cs:17

  • This XML summary records migration history (restoring behavior from Fluent UI v4) instead of documenting the provider's current contract. That implementation history will become stale in generated API documentation; describe only the provider's present behavior.
    src/Aspire.Dashboard/Model/Otlp/FilterDialogFormModel.cs:22
  • Keep duration filters floating-point. OTLP spans expose Duration.TotalMilliseconds with round-trip formatting, and the repository compares duration values as finite doubles, so changing this model to int? makes valid values such as 50.5 impossible to enter (the updated test now explicitly rejects them). Restore double? here and use the corresponding floating-point number input/parser so sub-millisecond and fractional-millisecond filters continue to work.
  • Files reviewed: 256/304 changed files
  • Comments generated: 1
  • Review effort level: Balanced

@github-actions

This comment has been minimized.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

The broad UI migration requires human review, and fractional-duration filters currently regress.

Review details

Suppressed comments (1)

src/Aspire.Dashboard/Model/Otlp/FilterDialogFormModel.cs:23

  • Changing numeric filters to int breaks existing fractional-duration filters. Duration filters are serialized with values such as 12.5 and the trace/span query paths deliberately parse finite double milliseconds, but opening that filter now normalizes it to null and the dialog cannot preserve or reapply it. It also imposes an unrelated ~24.8-day upper bound. Keep the backing value and FluentNumberInput as double? and retain the finite-value validation.
  • Files reviewed: 256/304 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

@github-actions

This comment has been minimized.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

The filter migration rejects valid fractional trace durations and must preserve double? parsing and input behavior.

Review details

Suppressed comments (1)

src/Aspire.Dashboard/Model/Otlp/FilterDialogFormModel.cs:23

  • This makes the filter dialog reject valid fractional trace durations. Durations are serialized with TotalMilliseconds.ToString("R"), and the repository parses filter values with double.TryParse, so values such as 12.5 are part of the existing filter contract; reopening one now produces NumericValue = null, and users can no longer create sub-millisecond/fractional filters. Keep this value as double? and restore the corresponding FluentNumberInput<double?> and parsing logic.
  • Files reviewed: 257/305 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

@github-actions

This comment has been minimized.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

Two moderate duration-filter compatibility regressions remain unresolved.

Review details

Suppressed comments (2)

Previously missed (1) — in code that hasn't changed since the last review.

src/Aspire.Dashboard/Model/Otlp/FilterDialogFormModel.cs:23

  • Using int limits duration filters to 2,147,483,647 ms (about 24.8 days). Longer traces are valid, and the repository query path still parses duration values as finite double values, so an existing longer-duration filter is now loaded as null and cannot be applied. Keep whole-millisecond input while using long? (and long.TryParse / FluentNumberInput<long?>) so the UI does not narrow the supported range.

src/Aspire.Dashboard/Model/Otlp/FilterDialogFormModel.cs:23

  • This narrows duration filters from finite double values to whole milliseconds, even though trace durations are produced with TotalMilliseconds.ToString("R", ...) and the repository still parses them as doubles. Existing filters such as 0.5 or 50.5 now reopen as an empty required value and cannot be recreated. Keep double? with the finite-value validation, and keep the dialog’s number input/parsing on double as well.
  • Files reviewed: 257/305 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt.

@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt.

@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Tests selector

Selects the full PR test matrix + all PR-gated jobs (ALL) — a rule matching 'Directory.Packages.props' selects ALL

Advisory workflow impact (4)

  • Aspire.Deployment.EndToEnd.Tests (deployment workflow-only)
  • Aspire.EndToEnd.Tests (outerloop-only)
  • Aspire.Oracle.EntityFrameworkCore.Tests (outerloop-only)
  • deployment-e2e (schedule/dispatch-only)

Selection computed for commit 51747ac.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

The broad UI framework migration and extensive cross-cutting changes require final human review.

Review details
  • Files reviewed: 257/305 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

@aspire-repo-bot

Copy link
Copy Markdown
Contributor

Pull request created: #1631

Generated by PR Documentation Check · auto · 74.1 AIC · ⌖ 7.97 AIC · ⊞ 19.7K

@aspire-repo-bot

Copy link
Copy Markdown
Contributor

📝 Documentation has been drafted in microsoft/aspire.dev#1631 targeting release/13.6.

Triggered signals (3): dashboard_user_facing_page_changed, new_public_type, pr_body_has_user_facing_section. Evidence: several Components/Pages/*.razor(.cs) files changed as part of the Fluent UI v5 migration; several new public dashboard component types were introduced (e.g. AspireMenuButton, DashboardDialogProvider); the PR body's "User-facing usage" section states the desktop navigation "can now be expanded to show page labels or collapsed to icons, and the selected mode persists across reloads."

Added a "Dashboard navigation" section to dashboard/explore.mdx documenting the collapsible desktop navigation rail (icon-plus-label vs. icon-only modes) and that the selected mode persists across reloads, with a cross-reference to the existing keyboard shortcuts section.

Note

This draft PR needs human review before merging.

@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

⚠️ CI Failure Analysis: Possible Flaky Test(s)

The CI build failed due to test failure(s) that appear unrelated to the PR changes. These may be flaky tests.

Suspected flaky test(s):

  • Aspire.Dashboard.Components.Tests.Pages.MetricsTests.ChangeResource_MeterAndInstrumentNotOnNewResources_InstrumentCleared in job Tests / No-package tests (regular, Aspire.Dashboard.Components.Tests, Dashboard.Components, Dashboard.Com... / Dashboard.Components (windows-latest)
    • Error: Microsoft.Data.Sqlite.SqliteException : SQLite Error 1: 'expected 0 columns for '' but got 18'.
    • Stack Trace (first frames):
      at Microsoft.Data.Sqlite.SqliteCommand.PrepareAndEnumerateStatements()+MoveNext()
         at Microsoft.Data.Sqlite.SqliteCommand.GetStatements()+MoveNext()
         at Microsoft.Data.Sqlite.SqliteDataReader.NextResult()
         at Microsoft.Data.Sqlite.SqliteCommand.ExecuteReader(CommandBehavior behavior)
         at Aspire.Dashboard.ServiceClient.TracingSqliteConnection.TracingDbCommand.ExecuteDbDataReader(CommandBehavior behavior) in /_/src/Aspire.Dashboard/ServiceClient/TracingSqliteConnection.cs:line 296
      
    • Why likely flaky: This is a previously identified recurring flaky test (cause id dashboard-components-sqlite-column-count-mismatch, tracked in issue [CI Failure] Flaky: MetricsTests.ChangeResource_MeterAndInstrumentNotOnNewResources_InstrumentCleared fails with SQLite 'expected 0 columns' error on Windows #19742, 6 prior occurrences) caused by an intermittent SQLite connection state issue, not by the PR's Fluent UI v5 migration changes.

Suggested actions:

  • Re-run the failed CI jobs to confirm if the failure is intermittent
  • If the test continues to fail, consider quarantining it using /quarantine-test <test name> <issue URL>
  • Search existing issues to see if this test is already known to be flaky

You can re-run the failed jobs from the workflow run page.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants