From 6fff099d9468fa3801f149b22e148c974ecf20c9 Mon Sep 17 00:00:00 2001 From: Taylor Jones Date: Fri, 18 Sep 2026 13:03:15 -0500 Subject: [PATCH] prevent virtualized SelectPanel measurement warnings Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .../fix-virtualized-select-panel-measurement.md | 5 +++++ packages/react/src/ActionList/Item.test.tsx | 15 +++++++++++++++ packages/react/src/ActionList/Item.tsx | 2 +- .../FilteredActionList.test.tsx | 15 +++++++++++++++ 4 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 .changeset/fix-virtualized-select-panel-measurement.md diff --git a/.changeset/fix-virtualized-select-panel-measurement.md b/.changeset/fix-virtualized-select-panel-measurement.md new file mode 100644 index 00000000000..622f2df5849 --- /dev/null +++ b/.changeset/fix-virtualized-select-panel-measurement.md @@ -0,0 +1,5 @@ +--- +'@primer/react': patch +--- + +SelectPanel: Prevent console warnings when measuring virtualized items diff --git a/packages/react/src/ActionList/Item.test.tsx b/packages/react/src/ActionList/Item.test.tsx index 1dbfb0d453b..0a34bacba76 100644 --- a/packages/react/src/ActionList/Item.test.tsx +++ b/packages/react/src/ActionList/Item.test.tsx @@ -387,6 +387,21 @@ describe('ActionList.Item', () => { expect(tabs).toHaveLength(3) }) + it('should forward a list-semantic item ref only to the outer list item', () => { + const ref = vi.fn<(node: HTMLLIElement | null) => void>() + const {getByRole} = HTMLRender( + + + Primer React + + , + ) + const option = getByRole('option') + + expect(ref.mock.calls.filter(([node]) => node !== null)).toEqual([[option]]) + expect(option.tagName).toBe('LI') + }) + it('should preserve consumer ref when tooltip wraps trigger', async () => { const user = userEvent.setup() diff --git a/packages/react/src/ActionList/Item.tsx b/packages/react/src/ActionList/Item.tsx index 1606952e3e1..f811925983f 100644 --- a/packages/react/src/ActionList/Item.tsx +++ b/packages/react/src/ActionList/Item.tsx @@ -340,7 +340,7 @@ const UnwrappedItem = ( className={classes.ActionListContent} data-size={size} // @ts-ignore: ItemWrapper is polymorphic and the ref type depends on the rendered element ('button' or 'li') - ref={forwardedRef} + ref={listSemantics ? null : forwardedRef} > {/* Reset TooltipContext so that child components don't detect the ConditionalTooltip and suppress their own internal tooltips. */} diff --git a/packages/react/src/FilteredActionList/FilteredActionList.test.tsx b/packages/react/src/FilteredActionList/FilteredActionList.test.tsx index f90ba4fd845..0263b63d2bd 100644 --- a/packages/react/src/FilteredActionList/FilteredActionList.test.tsx +++ b/packages/react/src/FilteredActionList/FilteredActionList.test.tsx @@ -100,6 +100,21 @@ describe('FilteredActionList', () => { ).toBeInTheDocument() }) }) + + it('does not warn when measuring virtualized items', () => { + const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {}) + + try { + const {container} = render() + + expect(container.querySelector('[data-index]')).toBeInTheDocument() + expect(warnSpy.mock.calls.flat().join(' ')).not.toContain( + "Missing attribute name 'data-index={index}' on measured element.", + ) + } finally { + warnSpy.mockRestore() + } + }) }) describe('FilteredActionListBodyLoader', () => {