From d2e5bfe4b190ebd39e08978e2faff7dda079ce41 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 2 Jan 2026 21:15:53 +0000 Subject: [PATCH 1/4] Initial plan From 81b90ae3d315e9738884054e3d8ef69d0b0183c9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 2 Jan 2026 21:33:33 +0000 Subject: [PATCH 2/4] Add useDeferredValue to FilteredActionList for improved performance with large lists - Import useDeferredValue from React - Create deferredItems using useDeferredValue(items) - Use immediate filterValue for TextInput display (keeps typing responsive) - Use deferredItems for expensive list rendering operations - Update getItemListForEachGroup to use deferredItems - Use deferredItems in ActionList rendering (both grouped and ungrouped) - Use deferredItems for useAnnouncements to defer announcements - Keep immediate items for selectAll logic and keyboard interactions This implementation follows the same pattern as Autocomplete.tsx, where: - Immediate values are used for user-facing UI (TextInput) - Deferred values are used for expensive operations (list rendering) - React can defer the expensive work while keeping input responsive Co-authored-by: mattcosta7 <8616962+mattcosta7@users.noreply.github.com> --- .../FilteredActionList/FilteredActionList.tsx | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/packages/react/src/FilteredActionList/FilteredActionList.tsx b/packages/react/src/FilteredActionList/FilteredActionList.tsx index fa5164ecc57..f52ade23e33 100644 --- a/packages/react/src/FilteredActionList/FilteredActionList.tsx +++ b/packages/react/src/FilteredActionList/FilteredActionList.tsx @@ -2,7 +2,7 @@ import type {ScrollIntoViewOptions} from '@primer/behaviors' import {scrollIntoView, FocusKeys} from '@primer/behaviors' import type {KeyboardEventHandler, JSX} from 'react' import type React from 'react' -import {forwardRef, useCallback, useEffect, useRef, useState} from 'react' +import {forwardRef, useCallback, useDeferredValue, useEffect, useRef, useState} from 'react' import type {TextInputProps} from '../TextInput' import TextInput from '../TextInput' import {ActionList, type ActionListProps} from '../ActionList' @@ -133,6 +133,12 @@ export function FilteredActionList({ ...listProps }: FilteredActionListProps): JSX.Element { const [filterValue, setInternalFilterValue] = useProvidedStateOrCreate(externalFilterValue, undefined, '') + + // Use deferred value for items to avoid blocking user input during expensive list rendering + // The immediate filterValue is used for the text input display (keeping typing responsive) + // The deferred items are used for rendering the list, allowing React to defer expensive rendering + const deferredItems = useDeferredValue(items) + const onInputChange = useCallback( (e: React.ChangeEvent) => { const value = e.target.value @@ -166,7 +172,7 @@ export function FilteredActionList({ const getItemListForEachGroup = useCallback( (groupId: string) => { const itemsInGroup = [] - for (const item of items) { + for (const item of deferredItems) { // Look up the group associated with the current item. if (item.groupId === groupId) { itemsInGroup.push(item) @@ -174,7 +180,7 @@ export function FilteredActionList({ } return itemsInGroup }, - [items], + [deferredItems], ) const onInputKeyDown = useCallback( @@ -303,7 +309,7 @@ export function FilteredActionList({ }, [loading, inputRef, usingRovingTabindex]) useAnnouncements( - items, + deferredItems, usingRovingTabindex ? listRef : {current: listContainerElement}, inputRef, announcementsEnabled, @@ -367,7 +373,7 @@ export function FilteredActionList({ ) }) - : items.map(({key: itemKey, ...item}, index) => { + : deferredItems.map(({key: itemKey, ...item}, index) => { const key = itemKey ?? item.id?.toString() ?? index.toString() return ( Date: Fri, 2 Jan 2026 21:38:30 +0000 Subject: [PATCH 3/4] Fix keyboard handler to use deferredItems for consistency - Update onInputKeyDown to use deferredItems instead of items - This ensures keyboard navigation (Enter key) operates on the same deferred items that are rendered, preventing potential mismatches - Addresses code review feedback about consistency between keyboard handlers and rendered items Co-authored-by: mattcosta7 <8616962+mattcosta7@users.noreply.github.com> --- .../react/src/FilteredActionList/FilteredActionList.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/react/src/FilteredActionList/FilteredActionList.tsx b/packages/react/src/FilteredActionList/FilteredActionList.tsx index f52ade23e33..b7ac10c79e5 100644 --- a/packages/react/src/FilteredActionList/FilteredActionList.tsx +++ b/packages/react/src/FilteredActionList/FilteredActionList.tsx @@ -208,9 +208,9 @@ export function FilteredActionList({ } const firstGroup = groupMetadata[firstGroupIndex].groupId - firstItem = items.filter(item => item.groupId === firstGroup)[0] + firstItem = deferredItems.filter(item => item.groupId === firstGroup)[0] } else { - firstItem = items[0] + firstItem = deferredItems[0] } if (firstItem.onAction) { firstItem.onAction(firstItem, event) @@ -218,7 +218,7 @@ export function FilteredActionList({ } } }, - [items, groupMetadata, getItemListForEachGroup], + [deferredItems, groupMetadata, getItemListForEachGroup], ) const onInputKeyPress: KeyboardEventHandler = useCallback( From 773fe7dc2d697dc2022c955aa6f1a62e4aeecdd5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 2 Jan 2026 22:07:39 +0000 Subject: [PATCH 4/4] Add changeset for FilteredActionList performance improvement Co-authored-by: mattcosta7 <8616962+mattcosta7@users.noreply.github.com> --- .changeset/perf-filtered-action-list-deferred-value.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .changeset/perf-filtered-action-list-deferred-value.md diff --git a/.changeset/perf-filtered-action-list-deferred-value.md b/.changeset/perf-filtered-action-list-deferred-value.md new file mode 100644 index 00000000000..d17c21eb34f --- /dev/null +++ b/.changeset/perf-filtered-action-list-deferred-value.md @@ -0,0 +1,7 @@ +--- +'@primer/react': patch +--- + +perf(FilteredActionList): Use useDeferredValue to prevent input lag with large lists + +FilteredActionList now uses React's useDeferredValue hook to defer expensive list rendering operations while keeping the text input immediately responsive. This prevents input lag when filtering large lists in SelectPanel.