Skip to content

feat(VirtualSelectList): add virtualized list for Select/Menu dropdowns - #43

Open
stefanonardo wants to merge 1 commit into
patternfly:mainfrom
stefanonardo:add-virtual-select-list
Open

feat(VirtualSelectList): add virtualized list for Select/Menu dropdowns#43
stefanonardo wants to merge 1 commit into
patternfly:mainfrom
stefanonardo:add-virtual-select-list

Conversation

@stefanonardo

@stefanonardo stefanonardo commented May 15, 2026

Copy link
Copy Markdown

Issue #44

Summary

  • Add VirtualSelectList, a virtualized replacement for PatternFly's SelectList that renders only visible items in a scrollable dropdown, enabling Select menus with thousands of options without DOM performance degradation
  • Add innerScrollContainerClassName prop to VirtualGrid so non-table consumers can override the hardcoded pf-v6-c-table__tbody class
  • Add documentation examples (basic, typeahead with filtering, multi-select) and 14 unit tests

Motivation

In OpenShift Console PR #16252, the Search page Resources dropdown has 1000+ items. After algorithmic optimizations (O(n²) → O(1) lookups, memoization), the remaining bottleneck is PatternFly's Select component measuring DOM geometry (refCallback forced reflow) after inserting all items. Even capped at 100 items, INP is 270ms ("needs improvement" on Core Web Vitals).

VirtualSelectList reduces INP from 270ms → 107ms ("good"), a 60% further reduction by rendering only ~10-20 visible items instead of 100.

Metric Before (100-item cap) After (VirtualSelectList)
INP 270ms (needs improvement) 107ms (good)
Processing duration ~200ms 77ms
Presentation delay ~70ms 22ms

Usage

Drop-in replacement for <SelectList> inside a composable <Select>:

import { Select, SelectOption, MenuToggle } from '@patternfly/react-core';
import { VirtualSelectList } from '@patternfly/react-virtualized-extension';

<Select isOpen={isOpen} onSelect={onSelect} toggle={toggle} isScrollable>
  <VirtualSelectList
    rowCount={items.length}
    rowHeight={36}
    maxHeight={300}
    rowRenderer={({ index, style, key }) => (
      <SelectOption key={key} style={style} value={items[index]}>
        {items[index]}
      </SelectOption>
    )}
  />
</Select>

Design decisions

  • Wraps VirtualGrid with 1 column, N rows — mirrors VirtualTableBody pattern
  • Renders <ul role="listbox"> as outer container via scrollContainerComponent
  • rowRenderer callback (not children) — required for lazy virtualized rendering, matches VirtualTableBody.rowRenderer naming
  • Internal keyboard navigation — ArrowUp/Down/Home/End with scrollToRow
  • Functional component — modern React style (vs VirtualTableBody's class component)

Known limitations

  • Browser Ctrl+F won't find off-screen items — typeahead filter covers this use case
  • Items are absolutely positioned, so the dropdown menu won't auto-size to content width — consumers should set popperProps={{ minWidth: '...' }} on the <Select>
  • No grouped/categorized support — flat lists only; <SelectGroup> support is a follow-up

Test plan

  • yarn build passes (ESM + CJS)
  • yarn test — 26 tests pass (14 new for VirtualSelectList, 12 existing unchanged)
  • Tested in OpenShift Console against a live cluster with 1000+ API resources
  • INP profiled at 107ms (good) via Chrome DevTools Performance trace

Add VirtualSelectList, a virtualized replacement for PatternFly's
SelectList that renders only visible items in a scrollable dropdown.
This enables Select menus with thousands of options without DOM
performance degradation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@stefanonardo
stefanonardo force-pushed the add-virtual-select-list branch from d666c71 to 982696e Compare May 15, 2026 13:46
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.

1 participant