Skip to content

Commit 57ffdbc

Browse files
authored
fix(AnchoredOverlay): do not overwrite ref from prop spread (#7130)
1 parent 21cefb9 commit 57ffdbc

File tree

3 files changed

+53
-2
lines changed

3 files changed

+53
-2
lines changed

.changeset/quiet-spiders-cough.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@primer/react': patch
3+
---
4+
5+
Update the `AnchoredOverlay` component so that the `ref` value is not overridden when spreading props

packages/react/src/AnchoredOverlay/AnchoredOverlay.test.tsx

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {act, useCallback, useState} from 'react'
1+
import {act, createRef, useCallback, useRef, useState} from 'react'
22
import {describe, expect, it, vi} from 'vitest'
33
import {render} from '@testing-library/react'
44
import {userEvent} from 'vitest/browser'
@@ -145,4 +145,34 @@ describe('AnchoredOverlay', () => {
145145
},
146146
})
147147
})
148+
149+
it('should support a `ref` through `overlayProps` on the overlay element', () => {
150+
const ref = createRef<HTMLDivElement>()
151+
152+
function Test() {
153+
const anchorRef = useRef(null)
154+
return (
155+
<AnchoredOverlay
156+
overlayProps={{
157+
ref,
158+
id: 'overlay',
159+
}}
160+
open
161+
renderAnchor={props => {
162+
return (
163+
<button {...props} ref={anchorRef} type="button">
164+
anchor
165+
</button>
166+
)
167+
}}
168+
>
169+
<div>content</div>
170+
</AnchoredOverlay>
171+
)
172+
}
173+
174+
render(<Test />)
175+
176+
expect(document.getElementById('overlay')).toBe(ref.current)
177+
})
148178
})

packages/react/src/AnchoredOverlay/AnchoredOverlay.tsx

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,6 @@ export const AnchoredOverlay: React.FC<React.PropsWithChildren<AnchoredOverlayPr
249249
onClickOutside={onClickOutside}
250250
ignoreClickRefs={[anchorRef]}
251251
onEscape={onEscape}
252-
ref={updateOverlayRef}
253252
role="none"
254253
visibility={position ? 'visible' : 'hidden'}
255254
height={height}
@@ -262,6 +261,12 @@ export const AnchoredOverlay: React.FC<React.PropsWithChildren<AnchoredOverlayPr
262261
className={className}
263262
preventOverflow={preventOverflow}
264263
{...overlayProps}
264+
ref={node => {
265+
if (overlayProps?.ref) {
266+
assignRef(overlayProps.ref, node)
267+
}
268+
updateOverlayRef(node)
269+
}}
265270
>
266271
{showXIcon ? (
267272
<div className={classes.ResponsiveCloseButtonContainer}>
@@ -288,4 +293,15 @@ export const AnchoredOverlay: React.FC<React.PropsWithChildren<AnchoredOverlayPr
288293
)
289294
}
290295

296+
function assignRef<T>(
297+
ref: React.MutableRefObject<T | null> | ((instance: T | null) => void) | null | undefined,
298+
value: T | null,
299+
) {
300+
if (typeof ref === 'function') {
301+
ref(value)
302+
} else if (ref) {
303+
ref.current = value
304+
}
305+
}
306+
291307
AnchoredOverlay.displayName = 'AnchoredOverlay'

0 commit comments

Comments
 (0)