Skip to content

Virtualization supports Beginning|End|None anchor modes#66073

Open
ilonatommy wants to merge 6 commits intomainfrom
fix-65742-anchor-modes
Open

Virtualization supports Beginning|End|None anchor modes#66073
ilonatommy wants to merge 6 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.

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)

Fixes #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.

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.

Virtualization supports anchor modes

2 participants