Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/dry-pets-appear.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@primer/react': minor
---

Make MappedActionListItem a forwardRef component
Original file line number Diff line number Diff line change
Expand Up @@ -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 {useCallback, useEffect, useRef, useState} from 'react'
import {forwardRef, useCallback, useEffect, useRef, useState} from 'react'
import type {TextInputProps} from '../TextInput'
import TextInput from '../TextInput'
import {ActionList, type ActionListProps} from '../ActionList'
Expand Down Expand Up @@ -426,8 +426,7 @@ export function FilteredActionList({
</div>
)
}

function MappedActionListItem(item: ItemInput & {renderItem?: RenderItemFn}) {
const MappedActionListItem = forwardRef<HTMLLIElement, ItemInput & {renderItem?: RenderItemFn}>((item, ref) => {
// keep backward compatibility for renderItem
// escape hatch for custom Item rendering
if (typeof item.renderItem === 'function') return item.renderItem(item)
Expand Down Expand Up @@ -455,6 +454,7 @@ function MappedActionListItem(item: ItemInput & {renderItem?: RenderItemFn}) {
onAction(item, e as React.MouseEvent<HTMLDivElement> | React.KeyboardEvent<HTMLDivElement>)
}}
data-id={id}
ref={ref}
{...rest}
>
{LeadingVisual ? (
Expand All @@ -481,6 +481,6 @@ function MappedActionListItem(item: ItemInput & {renderItem?: RenderItemFn}) {
) : null}
</ActionList.Item>
)
}
})
Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Consider adding a displayName to the MappedActionListItem component for better debugging experience in React DevTools. While it's an internal component, setting displayName is a best practice for forwardRef components in this codebase.

Example:

const MappedActionListItem = forwardRef<HTMLLIElement, ItemInput & {renderItem?: RenderItemFn}>((item, ref) => {
  // ... component implementation
})

MappedActionListItem.displayName = 'MappedActionListItem'
Suggested change
})
})
MappedActionListItem.displayName = 'MappedActionListItem'

Copilot uses AI. Check for mistakes.

FilteredActionList.displayName = 'FilteredActionList'
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,14 @@ export const WithDefaultMessage = () => {

const NUMBER_OF_ITEMS = 1800
const lotsOfItems = Array.from({length: NUMBER_OF_ITEMS}, (_, index) => {
if (index === 5) {
return {
id: index,
text: `This is being used to show what would happen if you returned an item that needed text wrapping`,
description: `Description ${index}`,
leadingVisual: getColorCircle('#a2eeef'),
}
}
return {
id: index,
text: `Item ${index}`,
Expand Down Expand Up @@ -620,8 +628,10 @@ export const Virtualized = () => {
getScrollElement: () => scrollContainer ?? null,
estimateSize: () => DEFAULT_VIRTUAL_ITEM_HEIGHT,
overscan: 10,
debug: true,
enabled: renderSubset,
measureElement: el => {
return (el as HTMLElement).scrollHeight
},
})

const virtualizedContainerStyle = useMemo(
Expand All @@ -645,6 +655,12 @@ export const Virtualized = () => {
return {
...item,
key: virtualItem.index,
'data-index': virtualItem.index,
ref: (node: Element | null) => {
if (node && node.getAttribute('data-index')) {
virtualizer.measureElement(node)
}
},
style: {
position: 'absolute',
top: 0,
Expand Down
Loading