Skip to content

feat(ScrollArea): add virtualizer - #2775

Open
yan-ad wants to merge 2 commits into
unovue:v2from
yan-ad:feat/scroll-area-virtualization
Open

feat(ScrollArea): add virtualizer#2775
yan-ad wants to merge 2 commits into
unovue:v2from
yan-ad:feat/scroll-area-virtualization

Conversation

@yan-ad

@yan-ad yan-ad commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Closes #2491

Description

  • Add ScrollAreaVirtualizer powered by @tanstack/vue-virtual
  • Export the new ScrollArea part and include it in generated component metadata
  • Add vertical and horizontal virtualization regression tests
  • Document usage in ScrollArea docs and migration guide

Verification

  • pnpm --filter reka-ui exec vitest run src/ScrollArea/ScrollArea.test.ts
  • pnpm --filter reka-ui type-check
  • pnpm exec eslint packages/core/src/ScrollArea/ScrollAreaVirtualizer.vue packages/core/src/ScrollArea/ScrollArea.test.ts packages/core/src/ScrollArea/index.ts packages/core/src/ScrollArea/story/ScrollAreaBasic.story.vue packages/core/constant/components.ts docs/content/docs/components/scroll-area.md docs/content/docs/guides/migration.md
  • pnpm docs:gen
  • pnpm lint (passes with existing warnings)

Summary by CodeRabbit

  • New Features

    • Added ScrollAreaVirtualizer to enable virtualized scrolling for large lists, rendering only visible items for better performance.
    • Added a new virtualized variant to the Scroll Area story with a large dataset example.
  • Documentation

    • Updated Scroll Area docs to include ScrollAreaVirtualizer, added a Virtualizer API section, and introduced a virtualized list example.
    • Extended the migration guide with a breaking-change section for virtualizing large scrollable lists.
  • Tests

    • Added tests validating visible-item rendering, total size behavior, and horizontal virtualization styling/positioning.

@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 10ca58d6-68f2-4d64-87a1-08cfbe903221

📥 Commits

Reviewing files that changed from the base of the PR and between c25410e and 76ea18f.

📒 Files selected for processing (2)
  • docs/content/docs/guides/migration.md
  • packages/core/src/ScrollArea/ScrollAreaVirtualizer.vue
💤 Files with no reviewable changes (1)
  • packages/core/src/ScrollArea/ScrollAreaVirtualizer.vue
✅ Files skipped from review due to trivial changes (1)
  • docs/content/docs/guides/migration.md

📝 Walkthrough

Walkthrough

A new ScrollAreaVirtualizer component is added to ScrollArea, exported from the package, covered by tests, shown in a story, and documented in the component docs and migration guide.

Changes

ScrollAreaVirtualizer Feature

Layer / File(s) Summary
ScrollAreaVirtualizer implementation
packages/core/src/ScrollArea/ScrollAreaVirtualizer.vue
Defines ScrollAreaVirtualizerProps and implements virtualization with scroll-root context, slot rendering, vnode cloning, and sized container output.
Package exports and registry
packages/core/src/ScrollArea/index.ts, packages/core/constant/components.ts
Re-exports ScrollAreaVirtualizer and its props type, and adds the component name to the ScrollArea component list.
Virtualized ScrollArea tests
packages/core/src/ScrollArea/ScrollArea.test.ts
Adds a virtualized ScrollArea suite that mocks layout measurements and checks vertical and horizontal virtualization behavior.
Virtualized story variant
packages/core/src/ScrollArea/story/ScrollAreaBasic.story.vue
Adds a ScrollArea story variant that renders 10,000 items through ScrollAreaVirtualizer with a scrollbar.
Documentation and migration guide
docs/content/meta/ScrollAreaVirtualizer.md, docs/content/docs/components/scroll-area.md, docs/content/docs/guides/migration.md
Adds ScrollAreaVirtualizer metadata, updates the ScrollArea docs with the new API and example, and adds the migration guide section.

Sequence Diagram(s)

sequenceDiagram
  participant App
  participant ScrollAreaViewport
  participant ScrollAreaVirtualizer
  participant useVirtualizer

  App->>ScrollAreaViewport: mount scroll container
  App->>ScrollAreaVirtualizer: pass options, estimateSize, horizontal
  ScrollAreaVirtualizer->>ScrollAreaViewport: inject viewport context
  ScrollAreaVirtualizer->>useVirtualizer: configure virtualization
  useVirtualizer-->>ScrollAreaVirtualizer: virtual items
  ScrollAreaVirtualizer->>App: invoke slot for visible items
  ScrollAreaVirtualizer->>ScrollAreaVirtualizer: render positioned vnodes
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐇 I hop through lists both big and small,
With virtual feet, I see them all.
A tiny viewport, swift and neat,
Makes long scrolls light beneath my feet.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning DropdownMenu.test.ts has an unrelated import reorder that does not support the ScrollArea virtualizer work. Remove the unrelated DropdownMenu test edit or split it into a separate housekeeping PR.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly names the new ScrollArea virtualizer feature and matches the main change.
Linked Issues check ✅ Passed The PR implements native virtualized ScrollArea support with component export, tests, and docs, matching #2491.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 markdownlint-cli2 (0.22.1)
docs/content/docs/guides/migration.md

markdownlint-cli2 wrapper config was not available before execution


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@pkg-pr-new

pkg-pr-new Bot commented Jun 29, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/reka-ui@2775

commit: 76ea18f

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

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
docs/content/meta/ScrollAreaVirtualizer.md (1)

1-70: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Add the missing horizontal prop to the generated docs. docs/content/meta/ScrollAreaVirtualizer.md is missing horizontal, so the API table no longer matches packages/core/src/ScrollArea/ScrollAreaVirtualizer.vue.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/content/meta/ScrollAreaVirtualizer.md` around lines 1 - 70, The
generated docs for ScrollAreaVirtualizer are missing the horizontal prop, so
update the Props/Slots content in ScrollAreaVirtualizer.md to include horizontal
alongside estimateSize, options, and overscan. Use the existing
ScrollAreaVirtualizer docs structure and ensure the generated API table matches
the ScrollAreaVirtualizer.vue component’s props exactly.

Source: Coding guidelines

🧹 Nitpick comments (1)
docs/content/docs/components/scroll-area.md (1)

37-54: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Anatomy import includes ScrollAreaVirtualizer but template doesn't demonstrate its placement.

The Anatomy section (lines 37-54) lists ScrollAreaVirtualizer in the import but the <template> only shows the non-virtualized structure. This is inconsistent with other parts that demonstrate all imported components. Consider adding a comment or second example showing where ScrollAreaVirtualizer fits, or remove it from the Anatomy import to avoid confusion. However, since the Virtualized list example (lines 119-150) already covers usage, this is minor.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/content/docs/components/scroll-area.md` around lines 37 - 54, The
Anatomy example imports ScrollAreaVirtualizer but does not show it in the
template, so the snippet is misleading. Update the ScrollAreaRoot example to
either remove ScrollAreaVirtualizer from the import or add a brief
note/placement hint in the template that shows where ScrollAreaVirtualizer
belongs, using the existing ScrollAreaRoot, ScrollAreaViewport, and
ScrollAreaScrollbar structure as the reference.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/content/docs/guides/migration.md`:
- Around line 146-166: The migration example in ScrollAreaVirtualizer is using
undefined item data and an invalid slot shape, so update it to match the actual
items source used by the docs (or clearly define a matching object array) and
render properties that exist on the slot value. Remove the manual key from the
virtualized slot content because ScrollAreaVirtualizer already assigns stable
keys internally via its vnode cloning behavior. If you keep this example, also
include ScrollAreaScrollbar alongside ScrollAreaRoot and ScrollAreaViewport so
the virtualized scroll area demonstrates usable scrolling UI.

In `@packages/core/src/ScrollArea/ScrollArea.test.ts`:
- Around line 15-77: The virtualized ScrollArea tests currently miss the
accessibility coverage used by the other ScrollArea cases. Update the
virtualized suite in ScrollArea.test.ts to include an axe assertion for the
mounted ScrollAreaRoot/ScrollAreaViewport/ScrollAreaVirtualizer setup, using the
existing test utilities or axe helper already used elsewhere in this file. Keep
the new assertion alongside the existing render and horizontal virtualization
tests so the virtualized variant is checked for a11y too.

In `@packages/core/src/ScrollArea/ScrollAreaVirtualizer.vue`:
- Around line 60-62: The cloned VNode and the template loop are both assigning a
key, which creates duplicate/conflicting identity handling. In
ScrollAreaVirtualizer.vue, update the render logic around cloneVNode and the
<component> loop so there is only one source of truth for the item key: remove
the manual key passed into cloneVNode and keep the template :key="item.key" (or
otherwise ensure both use the same stable value without duplicating assignment).
- Around line 47-56: The virtualized slot rendering in ScrollAreaVirtualizer
should be made defensive because slots.default is assumed to exist and Fragment
unwrapping can leave targetNode undefined. Update the computed virtualizedItems
logic to safely handle a missing default slot, then make the Fragment handling
in the slots.default result more robust by checking children safely and avoiding
the fragile symbol-based find/cast path. Ensure targetNode always has a valid
fallback before cloneVNode is used, and add a warning or guard when no usable
vnode can be extracted.
- Around line 14-19: ScrollAreaVirtualizer is missing ref forwarding, so parent
components cannot access the underlying container/virtualizer state. Update the
ScrollAreaVirtualizer.vue component to use the useForwardExpose composable
alongside its existing setup logic, and bind the forwarded ref to the root div
so consumers can interact with the virtualizer container (for example, to scroll
to items). Keep the change aligned with the component’s existing useVirtualizer,
injectScrollAreaRootContext, and root element wiring.

---

Outside diff comments:
In `@docs/content/meta/ScrollAreaVirtualizer.md`:
- Around line 1-70: The generated docs for ScrollAreaVirtualizer are missing the
horizontal prop, so update the Props/Slots content in ScrollAreaVirtualizer.md
to include horizontal alongside estimateSize, options, and overscan. Use the
existing ScrollAreaVirtualizer docs structure and ensure the generated API table
matches the ScrollAreaVirtualizer.vue component’s props exactly.

---

Nitpick comments:
In `@docs/content/docs/components/scroll-area.md`:
- Around line 37-54: The Anatomy example imports ScrollAreaVirtualizer but does
not show it in the template, so the snippet is misleading. Update the
ScrollAreaRoot example to either remove ScrollAreaVirtualizer from the import or
add a brief note/placement hint in the template that shows where
ScrollAreaVirtualizer belongs, using the existing ScrollAreaRoot,
ScrollAreaViewport, and ScrollAreaScrollbar structure as the reference.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7729bf97-df0b-486a-91a1-fc225f3c4edf

📥 Commits

Reviewing files that changed from the base of the PR and between 47c433a and c25410e.

📒 Files selected for processing (9)
  • docs/content/docs/components/scroll-area.md
  • docs/content/docs/guides/migration.md
  • docs/content/meta/ScrollAreaVirtualizer.md
  • packages/core/constant/components.ts
  • packages/core/src/DropdownMenu/DropdownMenu.test.ts
  • packages/core/src/ScrollArea/ScrollArea.test.ts
  • packages/core/src/ScrollArea/ScrollAreaVirtualizer.vue
  • packages/core/src/ScrollArea/index.ts
  • packages/core/src/ScrollArea/story/ScrollAreaBasic.story.vue

Comment thread docs/content/docs/guides/migration.md
Comment thread packages/core/src/ScrollArea/ScrollArea.test.ts
Comment thread packages/core/src/ScrollArea/ScrollAreaVirtualizer.vue
Comment thread packages/core/src/ScrollArea/ScrollAreaVirtualizer.vue
Comment thread packages/core/src/ScrollArea/ScrollAreaVirtualizer.vue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Virtualized scroll area

1 participant