Skip to content

Virtualization supports Beginning|End|None anchor modes for fixed-height items#66073

Closed
ilonatommy wants to merge 8 commits intomainfrom
fix-65742-anchor-modes
Closed

Virtualization supports Beginning|End|None anchor modes for fixed-height items#66073
ilonatommy wants to merge 8 commits intomainfrom
fix-65742-anchor-modes

Conversation

@ilonatommy
Copy link
Copy Markdown
Member

@ilonatommy ilonatommy commented Mar 30, 2026

Summary

Adds a new AnchorMode parameter to the Virtualize<TItem> component that controls how the viewport behaves at list edges when items are added dynamically.

Out of scope

This PR adds tests for both: fixed and variable height items but focuses on supporting only the former. Variable height support for prepended items scenario turns out to be more time consuming than expected and is out of scope for this PR.
The exact scroll compensation is unknown until the new items are rendered and measured in the DOM, so keeping the viewport perfectly stable requires an asynchronous, race-free post-layout correction rather than a deterministic precomputed shift (which is sufficient for fixed height scenarios).

New API

[Flags]
public enum VirtualizeAnchorMode
{
    None = 0,      // No edge pinning — viewport stays at current scroll position
    Beginning = 1, // Pins to top — new items at the beginning keep viewport at the top (news feed UX)
    End = 2,       // Pins to bottom — new items at the end auto-scroll to show them (chat/log UX)
}

Virtualize<TItem>.AnchorMode — default is Beginning (matches .NET 10 behavior at the top edge).

Modes can be combined: Beginning | End pins both edges. Combining None with other modes is supported but does not change the combined value -> since None = 0 the combination None | Beginning is just Beginning.

Behavior matrix

Scenario None Beginning End
Prepend at top Viewport stable (scroll compensated) Stays at top showing new items Viewport stable
Append at bottom Viewport stable Viewport stable Follows to new bottom
Mid-list changes Viewport stable Viewport stable Viewport stable
Home/End keys Still works Works Works

Changes

C# (Virtualize.cs, VirtualizeJsInterop.cs)

  • New AnchorMode component parameter with [Parameter]
  • _pendingScrollToBottom gated on (AnchorMode & End) != 0 instead of != None
  • Dynamic AnchorMode updates: detects changes in OnAfterRenderAsync, pushes to JS via SetAnchorModeAsync
  • None-mode prepend compensation: sets data-scroll-compensate attribute, JS adjusts scrollTop

JS (Virtualize.ts)

  • anchorMode parameter flows into init(), gating convergence logic:
    • Top convergence (onSpacerBeforeVisible): gated on anchorMode & 1 (Beginning)
    • Bottom convergence (onSpacerAfterVisible): gated on anchorMode & 2 (End)
  • setAnchorMode export for dynamic updates
  • scrollEventTarget fix: uses scrollContainer ?? window for scroll unlock handler (fixes window-scrolling mode)
  • Prepend compensation: scrollElement.scrollTop += spacerBefore.offsetHeight (was =, broke window-scrolling)

Contributes to #65742.

@ilonatommy ilonatommy self-assigned this Mar 30, 2026
@ilonatommy ilonatommy requested a review from a team as a code owner March 30, 2026 18:59
@ilonatommy ilonatommy added the area-blazor Includes: Blazor, Razor Components label Mar 30, 2026
Copilot AI review requested due to automatic review settings March 30, 2026 18:59
Copy link
Copy Markdown
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 an opt-in anchoring API to Virtualize<TItem> so apps can control whether the viewport “pins” to the beginning and/or end of a virtualized list as items are added, enabling chat/log/feed-style UX patterns.

Changes:

  • Introduces VirtualizeAnchorMode (None|Beginning|End) and exposes it as Virtualize<TItem>.AnchorMode (default: Beginning).
  • Extends Virtualize JS interop to accept anchorMode, gating convergence behavior and adding a None-mode prepend compensation path.
  • Adds a BasicTestApp test page plus new E2E coverage for anchor mode scenarios.

Reviewed changes

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

Show a summary per file
File Description
src/Components/Web/src/Virtualization/VirtualizeJsInterop.cs Extends JS init interop to pass anchorMode (and root margin).
src/Components/Web/src/Virtualization/VirtualizeAnchorMode.cs Adds new public [Flags] enum defining anchoring modes.
src/Components/Web/src/Virtualization/Virtualize.cs Adds AnchorMode parameter and C#/render hooks for None-mode prepend compensation + bottom convergence suppression in None.
src/Components/Web/src/PublicAPI.Unshipped.txt Declares the new public API surface.
src/Components/Web.JS/src/Virtualize.ts Implements anchor-mode gated convergence and None-mode prepend compensation + suppression logic.
src/Components/test/testassets/BasicTestApp/VirtualizationAnchorMode.razor Adds a manual test page for switching anchor mode and prepending/appending items.
src/Components/test/testassets/BasicTestApp/Index.razor Adds navigation entry for the new test page.
src/Components/test/E2ETest/Tests/VirtualizationTest.cs Adds E2E tests validating behavior for None/Beginning/End modes.

Comment thread src/Components/Web.JS/src/Virtualize.ts Outdated
Comment thread src/Components/test/E2ETest/Tests/VirtualizationTest.cs
Comment thread src/Components/test/E2ETest/Tests/VirtualizationTest.cs Outdated
Comment thread src/Components/test/E2ETest/Tests/VirtualizationTest.cs Outdated
Comment thread src/Components/Web/src/Virtualization/Virtualize.cs
@ilonatommy ilonatommy changed the title Virtualization supports Beginning|End|None anchor modes Virtualization supports Beginning|End|None anchor modes for fixed-height items Apr 8, 2026
@ilonatommy
Copy link
Copy Markdown
Member Author

All 5 variableHeight: True E2E failures are expected and will be blocked before merging, threated as "out-of-scope" for now.

@ilonatommy
Copy link
Copy Markdown
Member Author

Closing in favor of #66262.

@ilonatommy ilonatommy closed this Apr 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-blazor Includes: Blazor, Razor Components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants