Skip to content

Fix Dashboard popup positioning and persistence - #20362

Merged
James Newton-King (JamesNK) merged 6 commits into
mainfrom
jamesnk/dashboard-popup-continuity
Sep 23, 2026
Merged

James Newton-King (JamesNK) merged 6 commits into
mainfrom
jamesnk/dashboard-popup-continuity

Conversation

@JamesNK

@JamesNK James Newton-King (JamesNK) commented Sep 23, 2026 •

Copy link
Copy Markdown
Member

Description

Dashboard popups could be misaligned with their trigger, overflow below the viewport, or disappear while live metric dimensions were updating. This change aligns affected popups to the right edge of their trigger, allows them to flip above when needed, keeps the Resources view-options button visible, and keeps an open chart-filter popup mounted while new dimension values arrive.

Chart filter popup state now belongs to the stable filter component rather than replaceable metric snapshots. Stable tab, row, trigger, and popover identities preserve the browser top-layer popup while its values update.

User-facing usage

On the Resources and Metrics pages, users can open filter, view-options, profile, and URL-overflow popups and have them remain aligned with their trigger. An open metric dimension filter remains open as live values such as process.id are added.

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.

The Resources filter popup aligns its right edge with the filter button:

Resources filter popup aligned with its trigger

The always-visible view options button uses the same right-edge alignment:

Resources view options popup aligned with its trigger

Validation

  • Aspire.Dashboard.Components.Tests: 568 passed
  • Aspire.Dashboard.Tests: 1892 passed
  • Live Stress dashboard: the open process.id popup remained the same DOM host and stayed opened and :popover-open while values increased from 1173 to 1196

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

@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 -- 20362

Or

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

@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.

Copilot review overview

🟡 Changes recommended

Fluent’s inline positioning overrides the new anchor rules, and sanitized dimension names can create duplicate anchor IDs.

Get a fresh assessment by requesting another Copilot review.

Review effort: Balanced
Findings: 5 Medium severity

Open (5)
What changed in this PR

Fixes Dashboard popup alignment and preserves open metric filters during live updates.

Changes:

  • Uses CSS anchors for right-aligned, viewport-aware popups.
  • Moves popup state to stable chart-filter components.
  • Keeps Resources view options available and adds regression coverage.
File Description
tests/​Aspire.Dashboard.Tests/​Integration/​Playwright/​ResourcesTests.cs Verifies child actions are omitted when unavailable.
tests/​Aspire.Dashboard.Components.Tests/​Pages/​MetricsTests.cs Tests popup identity across metric updates.
tests/​Aspire.Dashboard.Components.Tests/​Controls/​ChartFiltersTests.cs Covers opening and preserving filter popups.
src/​Aspire.Dashboard/​Model/​DimensionFilterViewModel.cs Removes popup state from metric snapshots.
src/​Aspire.Dashboard/​Components/​ResourcesGridColumns/​UrlsColumnDisplay.razor.css Adds URL popup anchor positioning.
src/​Aspire.Dashboard/​Components/​Pages/​Resources.razor.css Adds resource-filter anchor positioning.
src/​Aspire.Dashboard/​Components/​Pages/​Resources.razor.cs Omits collapse actions without children.
src/​Aspire.Dashboard/​Components/​Pages/​Resources.razor Always displays view options and defines an anchor.
src/​Aspire.Dashboard/​Components/​Controls/​UserProfile.razor.css Adds profile popup anchor positioning.
src/​Aspire.Dashboard/​Components/​Controls/​UserProfile.razor Connects profile trigger and popup anchors.
src/​Aspire.Dashboard/​Components/​Controls/​Chart/​ChartFilterTags.razor.cs Delegates popup opening to the parent.
src/​Aspire.Dashboard/​Components/​Controls/​Chart/​ChartFilterTags.razor Uses the delegated popup callback.
src/​Aspire.Dashboard/​Components/​Controls/​Chart/​ChartFilters.razor.css Moves filter-button sizing styles.
src/​Aspire.Dashboard/​Components/​Controls/​Chart/​ChartFilters.razor.cs Owns popup state and anchor identities.
src/​Aspire.Dashboard/​Components/​Controls/​Chart/​ChartFilters.razor Stabilizes rows, buttons, and popovers.
src/​Aspire.Dashboard/​Components/​Controls/​Chart/​ChartFilterPopover.razor.css Adds chart popup anchor positioning.
src/​Aspire.Dashboard/​Components/​Controls/​Chart/​ChartFilterPopover.razor.cs Handles replacement filter subscriptions.
src/​Aspire.Dashboard/​Components/​Controls/​Chart/​ChartFilterPopover.razor Separates trigger and popover rendering.
src/​Aspire.Dashboard/​Components/​Controls/​Chart/​ChartContainer.razor Keys filters by selected instrument.

Comment thread src/Aspire.Dashboard/Components/Controls/Chart/ChartFilterPopover.razor.css Outdated
Comment thread src/Aspire.Dashboard/Components/Controls/Chart/ChartFilters.razor.cs Outdated
Comment thread src/Aspire.Dashboard/Components/Controls/UserProfile.razor.css Outdated
Comment thread src/Aspire.Dashboard/Components/Pages/Resources.razor.css Outdated
Comment thread src/Aspire.Dashboard/Components/ResourcesGridColumns/UrlsColumnDisplay.razor.css Outdated

@mitchdenny Mitch Denny (mitchdenny) left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Validated the popup positioning and persistence behavior in the live dashboard. The tested URL overflow popup aligned correctly with its trigger, and I did not find a blocking functional issue.

Non-blocking follow-up: metric filter anchor IDs are derived from SanitizeHtmlId, which replaces invalid characters with _. Distinct dimension names such as foo.bar and foo/bar can therefore produce the same DOM ID and potentially target the wrong popover. This should be addressed with collision-safe ID generation and focused regression coverage.

@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.

Copilot review overview

🔵 Needs a closer look

Popup state can leak across resources, and the browser top-layer persistence regression lacks Playwright coverage.

Review effort: Balanced
Findings: None

Resolved since last review (5)
Previously missed (2)

In code that hasn't changed since last review

Medium severity Include ResourceKey in popup state key

src/​Aspire.Dashboard/​Components/​Controls/​Chart/​ChartContainer.razor:42

This key omits ResourceKey, even though ChartContainer is reused when the selected resource changes and its request identity includes the resource. If two resources expose the same meter/instrument and filter name, _openFilterNames is retained and the new resource's popup opens automatically. Include ResourceKey so popup state is stable only within the same metric selection.

This issue also appears on line 52 of the same file.

Medium severity Add browser regression for popover state after DOM updates

tests/​Aspire.Dashboard.Components.Tests/​Pages/​MetricsTests.cs:186

The regression being fixed is browser-only: an element can retain opened="true" in bUnit while no longer matching :popover-open after Blazor updates its DOM. These assertions therefore cannot catch the reported popup disappearance. Add a Playwright regression that opens a metric filter, publishes a new dimension value, and verifies the same popover host still matches :popover-open after the update.

@github-actions

This comment has been minimized.

Cache a stable hash of each original filter name so sanitized name collisions do not share an anchor. Cover colliding names in component tests.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Ensure chart filters, profile menu, resource filters, and URL overflow dialogs honor their CSS anchors and flip fallback despite Fluent's inline insets.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace obsolete SetParametersAndRender calls with the Render pattern used by dashboard component tests.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

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.

Copilot review overview

🟢 Approval recommended

The popup lifecycle and positioning changes are coherent and covered by focused component and browser tests.

Review effort: Balanced
Findings: None

@github-actions

This comment has been minimized.

@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.

@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.

@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.

@IEvangelist

Copy link
Copy Markdown
Member

Triggered, I just noticed that the dropdown content for the filters has square corners while the other dropdown has the preferred border-radius. We should fix that.

Replace deprecated WebHostBuilder/TestServer constructors with a shared generic-host test server setup for terminal stream coverage.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Use bUnit Render in the menu test added on main so the PR merge builds on Linux and Windows.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@aspire-repo-bot
aspire-repo-bot Bot requested a balanced review from Copilot September 23, 2026 13:24
@github-actions

Copy link
Copy Markdown
Contributor

Tests selector

13 / 99 PR test projects · 2 PR jobs, from 21 changed files.

Selected PR test projects (13 / 99)

Aspire.Dashboard.Components.Tests, Aspire.Dashboard.Tests, Aspire.Hosting.Azure.Kubernetes.Tests, Aspire.Hosting.Azure.Tests, Aspire.Hosting.Blazor.Tests, Aspire.Hosting.Dotnet.Tests, Aspire.Hosting.DotnetTool.Tests, Aspire.Hosting.JavaScript.Tests, Aspire.Hosting.Radius.Tests, Aspire.Hosting.Testing.Tests, Aspire.Hosting.Tests, Aspire.Playground.Tests, Aspire.Templates.Tests

Selected PR jobs (2)

extension-e2e, native-dashboard-validation


How these were chosen — grouped by what changed

⚠️ 10 of the 13 selected test projects come from a single change — src/Aspire.Dashboard/Components/Controls/Chart/ChartContainer.razor.

🔧 src/Aspire.Dashboard/Components/Controls/Chart/ChartContainer.razor (changed source)
→ 10 via the project graph: Aspire.Hosting.Azure.Kubernetes.Tests (3 hops), Aspire.Hosting.Azure.Tests (2 hops), Aspire.Hosting.Blazor.Tests (2 hops), Aspire.Hosting.Dotnet.Tests (2 hops), Aspire.Hosting.DotnetTool.Tests (2 hops), Aspire.Hosting.JavaScript.Tests, Aspire.Hosting.Radius.Tests (2 hops), Aspire.Hosting.Testing.Tests, Aspire.Hosting.Tests, Aspire.Playground.Tests (2 hops)

📦 affected project Aspire.Dashboard
→ 1 test: Aspire.Templates.Tests

🧪 tests/Aspire.Dashboard.Components.Tests/Controls/AspireMenuTests.cs (changed test)
→ 1 directly: Aspire.Dashboard.Components.Tests

🧪 tests/Aspire.Dashboard.Components.Tests/Controls/ChartFiltersTests.cs (changed test)
→ 1 directly: Aspire.Dashboard.Components.Tests

🧪 tests/Aspire.Dashboard.Components.Tests/Pages/MetricsTests.cs (changed test)
→ 1 directly: Aspire.Dashboard.Components.Tests

🧪 tests/Aspire.Dashboard.Tests/Integration/Playwright/ResourcesTests.cs (changed test)
→ 1 directly: Aspire.Dashboard.Tests

🧪 tests/Aspire.Dashboard.Tests/Model/DashboardClientTests.cs (changed test)
→ 1 directly: Aspire.Dashboard.Tests

Job reasons

Job Triggered by
extension-e2e • src/Aspire.Dashboard/Components/Controls/Chart/ChartContainer.razor, src/Aspire.Dashboard/Components/Controls/Chart/ChartFilterPopover.razor, src/Aspire.Dashboard/Components/Controls/Chart/ChartFilterPopover.razor.cs, src/Aspire.Dashboard/Components/Controls/Chart/ChartFilterPopover.razor.css, src/Aspire.Dashboard/Components/Controls/Chart/ChartFilterTags.razor, src/Aspire.Dashboard/Components/Controls/Chart/ChartFilterTags.razor.cs, src/Aspire.Dashboard/Components/Controls/Chart/ChartFilters.razor, src/Aspire.Dashboard/Components/Controls/Chart/ChartFilters.razor.cs, src/Aspire.Dashboard/Components/Controls/Chart/ChartFilters.razor.css, src/Aspire.Dashboard/Components/Controls/UserProfile.razor, src/Aspire.Dashboard/Components/Controls/UserProfile.razor.css, src/Aspire.Dashboard/Components/Pages/Resources.razor, src/Aspire.Dashboard/Components/Pages/Resources.razor.cs, src/Aspire.Dashboard/Components/Pages/Resources.razor.css, src/Aspire.Dashboard/Components/ResourcesGridColumns/UrlsColumnDisplay.razor.css, src/Aspire.Dashboard/Model/DimensionFilterViewModel.cs
• affected project Aspire.Dashboard
native-dashboard-validation affected project Aspire.Dashboard

Selection computed for commit c7ec1d0.

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.

Copilot review overview

🟢 Approval recommended

The popup lifecycle, positioning changes, and affected interactions have focused regression coverage with no blocking issues found.

Review effort: Balanced
Findings: None

@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.

@JamesNK
James Newton-King (JamesNK) merged commit 151d9cc into main Sep 23, 2026
299 of 303 checks passed
@github-actions github-actions Bot added this to the 13.6 milestone Sep 23, 2026
aspire-repo-bot Bot added a commit to microsoft/aspire.dev that referenced this pull request Sep 23, 2026
…c updates

Documents changes from microsoft/aspire#20362

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@aspire-repo-bot

Copy link
Copy Markdown
Contributor

Pull request created: #1728

Generated by PR Documentation Check · copilot · auto · 68.9 AIC · ⌖ 10.4 AIC · ⊞ 18.7K

@aspire-repo-bot

Copy link
Copy Markdown
Contributor

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

Triggered signals (2): dashboard_user_facing_page_changed (Resources.razor / Resources.razor.cs edited for popup positioning/view-options visibility), pr_body_has_user_facing_section (PR body User-facing usage: "On the Resources and Metrics pages, users can open filter, view-options, profile, and URL-overflow popups and have them remain aligned with their trigger. An open metric dimension filter remains open as live values such as process.id are added."). Updated src/frontend/src/content/docs/dashboard/explore.mdx to note that the metrics dimension-filter popover now stays open while live tag values continue to update, matching the PRs core user-facing fix. Positioning/alignment fixes for the filter, view-options, profile, and URL-overflow popups are internal visual/CSS corrections with no new user-facing concept requiring separate prose.

Note

This draft PR needs human review before merging.

David Pine (IEvangelist) pushed a commit to microsoft/aspire.dev that referenced this pull request Sep 23, 2026
…c updates (#1728)

Documents changes from microsoft/aspire#20362

Co-authored-by: aspire-repo-bot[bot] <268009190+aspire-repo-bot[bot]@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Jose Perez Rodriguez (joperezr) pushed a commit that referenced this pull request Sep 24, 2026
Backports #20360, #20341, and #20362 to release/13.6.

## Customer Impact

Dashboard users can encounter popups that are misaligned, overflow the
viewport, or disappear while metric dimensions update. Resource graph
context menus may not reopen immediately after dismissal, and terminal
auto-fit can move focus away from the active control.

## Testing

Validated on the release/13.6 backport branch: 570
Aspire.Dashboard.Components.Tests and 1,892 Aspire.Dashboard.Tests
passed, excluding quarantined and outerloop tests. The source changes
also include targeted Playwright coverage for resources, terminal,
navigation, authentication, accessibility, and popup behavior. `git diff
--check` passes.

## Risk

Medium. The production changes are localized to Dashboard popup, focus,
and component-state behavior with no public API changes, but this
combines three related changes and a broad component-test migration.

## Regression?

Yes — fixes Dashboard behavior and test regressions introduced by the
Fluent UI v5 migration.
David Pine (IEvangelist) pushed a commit that referenced this pull request Oct 1, 2026
Backports #20360, #20341, and #20362 to release/13.6.

## Customer Impact

Dashboard users can encounter popups that are misaligned, overflow the
viewport, or disappear while metric dimensions update. Resource graph
context menus may not reopen immediately after dismissal, and terminal
auto-fit can move focus away from the active control.

## Testing

Validated on the release/13.6 backport branch: 570
Aspire.Dashboard.Components.Tests and 1,892 Aspire.Dashboard.Tests
passed, excluding quarantined and outerloop tests. The source changes
also include targeted Playwright coverage for resources, terminal,
navigation, authentication, accessibility, and popup behavior. `git diff
--check` passes.

## Risk

Medium. The production changes are localized to Dashboard popup, focus,
and component-state behavior with no public API changes, but this
combines three related changes and a broad component-test migration.

## Regression?

Yes — fixes Dashboard behavior and test regressions introduced by the
Fluent UI v5 migration.
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