From 23162867f4acaf312d893be67ca4e9296faba4ff Mon Sep 17 00:00:00 2001 From: Pavithra Kodmad Date: Wed, 26 Nov 2025 12:12:49 +1100 Subject: [PATCH 1/4] Grateful if this fixes type compatibility --- examples/nextjs/src/app/products/page.tsx | 13 +++++++++++++ packages/react/src/ActionList/List.tsx | 1 + .../react/src/AnchoredOverlay/AnchoredOverlay.tsx | 4 ++-- packages/react/src/ButtonGroup/ButtonGroup.tsx | 3 ++- packages/react/src/Checkbox/Checkbox.tsx | 2 +- packages/react/src/Dialog/Dialog.tsx | 7 ++++--- .../src/FilteredActionList/FilteredActionList.tsx | 6 ++++-- .../src/FilteredActionList/useAnnouncements.tsx | 6 +++--- packages/react/src/Overlay/Overlay.tsx | 6 +++--- packages/react/src/PageHeader/PageHeader.tsx | 1 + .../SelectPanel/SelectPanel.examples.stories.tsx | 4 ++-- packages/react/src/SelectPanel/SelectPanel.tsx | 1 + packages/react/src/TextInput/TextInput.tsx | 3 ++- packages/react/src/TooltipV2/Tooltip.tsx | 1 + .../experimental/Tabs/Tabs.examples.stories.tsx | 1 + packages/react/src/experimental/Tabs/Tabs.tsx | 3 ++- packages/react/src/hooks/useAnchoredPosition.ts | 10 +++++----- packages/react/src/hooks/useFocusTrap.ts | 8 ++++---- packages/react/src/hooks/useFocusZone.ts | 9 ++++++--- packages/react/src/hooks/useMenuInitialFocus.ts | 4 ++-- .../react/src/hooks/useMenuKeyboardNavigation.ts | 14 +++++++------- packages/react/src/hooks/useMnemonics.ts | 2 +- packages/react/src/hooks/useOnOutsideClick.tsx | 4 ++-- packages/react/src/hooks/useOpenAndCloseFocus.ts | 6 +++--- packages/react/src/hooks/useOverlay.tsx | 12 ++++++------ packages/react/src/hooks/useProvidedRefOrCreate.ts | 2 +- packages/react/src/hooks/useResizeObserver.ts | 2 +- packages/react/src/hooks/useScrollFlash.ts | 2 +- 28 files changed, 82 insertions(+), 55 deletions(-) create mode 100644 examples/nextjs/src/app/products/page.tsx diff --git a/examples/nextjs/src/app/products/page.tsx b/examples/nextjs/src/app/products/page.tsx new file mode 100644 index 00000000000..e67345d472d --- /dev/null +++ b/examples/nextjs/src/app/products/page.tsx @@ -0,0 +1,13 @@ +import React from 'react' +import {Button} from '@primer/react' + +// Minimal products page to satisfy type generation and provide a simple sample. +export default function ProductsPage() { + return ( +
+

Products

+

This is a placeholder Products page for the Next.js example.

+ +
+ ) +} diff --git a/packages/react/src/ActionList/List.tsx b/packages/react/src/ActionList/List.tsx index 0546d85abca..6fa8fa56ac9 100644 --- a/packages/react/src/ActionList/List.tsx +++ b/packages/react/src/ActionList/List.tsx @@ -66,6 +66,7 @@ const UnwrappedList = ( }} > {slots.heading} + {/* @ts-expect-error ref needs a non nullable ref */} + anchorRef?: React.RefObject /** * An override to the internal id that will be spread on to the renderAnchor @@ -46,7 +46,7 @@ interface AnchoredOverlayPropsWithoutAnchor { * An override to the internal renderAnchor ref that will be used to position the overlay. * When renderAnchor is null this can be used to make an anchor that is detached from ActionMenu. */ - anchorRef: React.RefObject + anchorRef: React.RefObject /** * An override to the internal id that will be spread on to the renderAnchor */ diff --git a/packages/react/src/ButtonGroup/ButtonGroup.tsx b/packages/react/src/ButtonGroup/ButtonGroup.tsx index cd07d132175..eff345f616b 100644 --- a/packages/react/src/ButtonGroup/ButtonGroup.tsx +++ b/packages/react/src/ButtonGroup/ButtonGroup.tsx @@ -17,7 +17,7 @@ const ButtonGroup = React.forwardRef(function ButtonGroup( forwardRef, ) { const buttons = React.Children.map(children, (child, index) =>
{child}
) - const buttonRef = useProvidedRefOrCreate(forwardRef as React.RefObject) + const buttonRef = useProvidedRefOrCreate(forwardRef as React.RefObject) useFocusZone({ containerRef: buttonRef, @@ -27,6 +27,7 @@ const ButtonGroup = React.forwardRef(function ButtonGroup( }) return ( + //@ts-expect-error it needs a non nullable ref {buttons} diff --git a/packages/react/src/Checkbox/Checkbox.tsx b/packages/react/src/Checkbox/Checkbox.tsx index a83bb60ccf6..c992f840ebb 100644 --- a/packages/react/src/Checkbox/Checkbox.tsx +++ b/packages/react/src/Checkbox/Checkbox.tsx @@ -84,7 +84,7 @@ const Checkbox = React.forwardRef( checkbox.setAttribute('aria-checked', checkbox.checked ? 'true' : 'false') } }) - + // @ts-expect-error inputProp needs a non nullable ref return }, ) diff --git a/packages/react/src/Dialog/Dialog.tsx b/packages/react/src/Dialog/Dialog.tsx index 301bc80304c..0381c445e58 100644 --- a/packages/react/src/Dialog/Dialog.tsx +++ b/packages/react/src/Dialog/Dialog.tsx @@ -44,7 +44,7 @@ export type DialogButtonProps = Omit & { * A reference to the rendered Button’s DOM node, used together with * `autoFocus` for `focusTrap`’s `initialFocus`. */ - ref?: React.RefObject + ref?: React.RefObject } /** @@ -136,12 +136,12 @@ export interface DialogProps { * Return focus to this element when the Dialog closes, * instead of the element that had focus immediately before the Dialog opened */ - returnFocusRef?: React.RefObject + returnFocusRef?: React.RefObject /** * The element to focus when the Dialog opens */ - initialFocusRef?: React.RefObject + initialFocusRef?: React.RefObject /** * Additional class names to apply to the dialog @@ -408,6 +408,7 @@ const Buttons: React.FC> {...buttonProps} // 'normal' value is equivalent to 'default', this is used for backwards compatibility variant={buttonType === 'normal' ? 'default' : buttonType} + // @ts-expect-error it needs a non nullable ref ref={autoFocus && autoFocusCount === 0 ? (autoFocusCount++, autoFocusRef) : null} > {content} diff --git a/packages/react/src/FilteredActionList/FilteredActionList.tsx b/packages/react/src/FilteredActionList/FilteredActionList.tsx index 6cc5a08076d..eceecae8dd3 100644 --- a/packages/react/src/FilteredActionList/FilteredActionList.tsx +++ b/packages/react/src/FilteredActionList/FilteredActionList.tsx @@ -31,13 +31,13 @@ export interface FilteredActionListProps extends Partial | null) => void onListContainerRefChanged?: (ref: HTMLElement | null) => void - onInputRefChanged?: (ref: React.RefObject) => void + onInputRefChanged?: (ref: React.RefObject) => void /** * A ref assigned to the scrollable container wrapping the ActionList */ scrollContainerRef?: React.Ref textInputProps?: Partial> - inputRef?: React.RefObject + inputRef?: React.RefObject message?: React.ReactNode messageText?: { title: string @@ -382,6 +382,7 @@ export function FilteredActionList({
)} + {/* @ts-expect-error div needs a non nullable ref */}
{getBodyContent()}
diff --git a/packages/react/src/FilteredActionList/useAnnouncements.tsx b/packages/react/src/FilteredActionList/useAnnouncements.tsx index c3026078eba..dcc3a03062a 100644 --- a/packages/react/src/FilteredActionList/useAnnouncements.tsx +++ b/packages/react/src/FilteredActionList/useAnnouncements.tsx @@ -19,7 +19,7 @@ const useFirstRender = () => { } const getItemWithActiveDescendant = ( - listRef: React.RefObject, + listRef: React.RefObject, items: FilteredActionListProps['items'], ) => { const listElement = listRef.current @@ -40,8 +40,8 @@ const getItemWithActiveDescendant = ( export const useAnnouncements = ( items: FilteredActionListProps['items'], - listContainerRef: React.RefObject, - inputRef: React.RefObject, + listContainerRef: React.RefObject, + inputRef: React.RefObject, enabled: boolean = true, loading: boolean = false, message?: {title: string; description: string}, diff --git a/packages/react/src/Overlay/Overlay.tsx b/packages/react/src/Overlay/Overlay.tsx index b2cf178ff32..9f588146323 100644 --- a/packages/react/src/Overlay/Overlay.tsx +++ b/packages/react/src/Overlay/Overlay.tsx @@ -138,14 +138,14 @@ export const BaseOverlay = React.forwardRef( type ContainerProps = { anchorSide?: AnchorSide - ignoreClickRefs?: React.RefObject[] - initialFocusRef?: React.RefObject + ignoreClickRefs?: React.RefObject[] + initialFocusRef?: React.RefObject onClickOutside: (e: TouchOrMouseEvent) => void onEscape: (e: KeyboardEvent) => void portalContainerName?: string preventOverflow?: boolean preventFocusOnOpen?: boolean - returnFocusRef: React.RefObject + returnFocusRef: React.RefObject } type internalOverlayProps = Merge diff --git a/packages/react/src/PageHeader/PageHeader.tsx b/packages/react/src/PageHeader/PageHeader.tsx index 0a333c5bcf0..1acaadf06f3 100644 --- a/packages/react/src/PageHeader/PageHeader.tsx +++ b/packages/react/src/PageHeader/PageHeader.tsx @@ -209,6 +209,7 @@ const TitleArea = React.forwardRef { const virtualizedItems = useMemo( () => renderSubset - ? virtualizer.getVirtualItems().map(virtualItem => { + ? virtualizer.getVirtualItems().map((virtualItem: VirtualItem) => { const item = filteredItems[virtualItem.index] return { diff --git a/packages/react/src/SelectPanel/SelectPanel.tsx b/packages/react/src/SelectPanel/SelectPanel.tsx index 4e5f84e5df5..a705ea647a0 100644 --- a/packages/react/src/SelectPanel/SelectPanel.tsx +++ b/packages/react/src/SelectPanel/SelectPanel.tsx @@ -857,6 +857,7 @@ function Panel({ filterValue={filterValue} onFilterChange={onFilterChange} onListContainerRefChanged={onListContainerRefChanged} + // @ts-expect-error it needs a non nullable ref onInputRefChanged={onInputRefChanged} placeholderText={placeholderText} {...listProps} diff --git a/packages/react/src/TextInput/TextInput.tsx b/packages/react/src/TextInput/TextInput.tsx index be52c1d5e2f..dee4f95edef 100644 --- a/packages/react/src/TextInput/TextInput.tsx +++ b/packages/react/src/TextInput/TextInput.tsx @@ -90,7 +90,7 @@ const TextInput = React.forwardRef( ref, ) => { const [isInputFocused, setIsInputFocused] = useState(false) - const inputRef = useProvidedRefOrCreate(ref as React.RefObject) + const inputRef = useProvidedRefOrCreate(ref as React.RefObject) // this class is necessary to style FilterSearch, plz no touchy! const wrapperClasses = clsx(className, 'TextInput-wrapper') const showLeadingLoadingIndicator = @@ -164,6 +164,7 @@ const TextInput = React.forwardRef( {typeof LeadingVisual !== 'string' && isValidElementType(LeadingVisual) ? : LeadingVisual} , { + // @ts-expect-error it needs a non nullable ref ref: triggerRef, // If it is a type description, we use tooltip to describe the trigger 'aria-describedby': (() => { diff --git a/packages/react/src/experimental/Tabs/Tabs.examples.stories.tsx b/packages/react/src/experimental/Tabs/Tabs.examples.stories.tsx index df2d7a518e4..ebe9a81a5aa 100644 --- a/packages/react/src/experimental/Tabs/Tabs.examples.stories.tsx +++ b/packages/react/src/experimental/Tabs/Tabs.examples.stories.tsx @@ -17,6 +17,7 @@ const CustomTabList = (props: React.PropsWithChildren) => { return (
+ {/* @ts-expect-error it needs a non nullable ref */} {props.children}
) diff --git a/packages/react/src/experimental/Tabs/Tabs.tsx b/packages/react/src/experimental/Tabs/Tabs.tsx index 71fe02c0e4b..69c891b5350 100644 --- a/packages/react/src/experimental/Tabs/Tabs.tsx +++ b/packages/react/src/experimental/Tabs/Tabs.tsx @@ -114,7 +114,7 @@ function useTabList( 'aria-orientation': AriaAttributes['aria-orientation'] 'aria-label': AriaAttributes['aria-label'] 'aria-labelledby': AriaAttributes['aria-labelledby'] - ref: React.RefObject + ref: React.RefObject role: 'tablist' } } { @@ -186,6 +186,7 @@ function TabList({children, ...rest}: TabListProps) { const {tabListProps} = useTabList(rest) return ( + // @ts-expect-error it needs a non nullable ref
{children}
diff --git a/packages/react/src/hooks/useAnchoredPosition.ts b/packages/react/src/hooks/useAnchoredPosition.ts index e4e54f61c51..32777aad1d7 100644 --- a/packages/react/src/hooks/useAnchoredPosition.ts +++ b/packages/react/src/hooks/useAnchoredPosition.ts @@ -6,8 +6,8 @@ import {useResizeObserver} from './useResizeObserver' import useLayoutEffect from '../utils/useIsomorphicLayoutEffect' export interface AnchoredPositionHookSettings extends Partial { - floatingElementRef?: React.RefObject - anchorElementRef?: React.RefObject + floatingElementRef?: React.RefObject + anchorElementRef?: React.RefObject pinPosition?: boolean onPositionChange?: (position: AnchorPosition | undefined) => void } @@ -25,8 +25,8 @@ export function useAnchoredPosition( settings?: AnchoredPositionHookSettings, dependencies: React.DependencyList = [], ): { - floatingElementRef: React.RefObject - anchorElementRef: React.RefObject + floatingElementRef: React.RefObject + anchorElementRef: React.RefObject position: AnchorPosition | undefined } { const floatingElementRef = useProvidedRefOrCreate(settings?.floatingElementRef) @@ -98,7 +98,7 @@ export function useAnchoredPosition( useLayoutEffect(updatePosition, [updatePosition]) useResizeObserver(updatePosition) // watches for changes in window size - useResizeObserver(updatePosition, floatingElementRef as React.RefObject) // watches for changes in floating element size + useResizeObserver(updatePosition, floatingElementRef as React.RefObject) // watches for changes in floating element size return { floatingElementRef, diff --git a/packages/react/src/hooks/useFocusTrap.ts b/packages/react/src/hooks/useFocusTrap.ts index 62fbc68e636..ab599d7fb92 100644 --- a/packages/react/src/hooks/useFocusTrap.ts +++ b/packages/react/src/hooks/useFocusTrap.ts @@ -7,13 +7,13 @@ export interface FocusTrapHookSettings { * Ref that will be used for the trapping container. If not provided, one will * be created by this hook and returned. */ - containerRef?: React.RefObject + containerRef?: React.RefObject /** * Ref for the element that should receive focus when the focus trap is first enabled. If * not provided, one will be created by this hook and returned. Its use is optional. */ - initialFocusRef?: React.RefObject + initialFocusRef?: React.RefObject /** * Set to true to disable the focus trap and clean up listeners. Can be re-enabled at @@ -33,7 +33,7 @@ export interface FocusTrapHookSettings { * * Overrides restoreFocusOnCleanUp */ - returnFocusRef?: React.RefObject + returnFocusRef?: React.RefObject } /** @@ -44,7 +44,7 @@ export interface FocusTrapHookSettings { export function useFocusTrap( settings?: FocusTrapHookSettings, dependencies: React.DependencyList = [], -): {containerRef: React.RefObject; initialFocusRef: React.RefObject} { +): {containerRef: React.RefObject; initialFocusRef: React.RefObject} { const containerRef = useProvidedRefOrCreate(settings?.containerRef) const initialFocusRef = useProvidedRefOrCreate(settings?.initialFocusRef) const disabled = settings?.disabled diff --git a/packages/react/src/hooks/useFocusZone.ts b/packages/react/src/hooks/useFocusZone.ts index 71b49a01708..a4e5a7bce4d 100644 --- a/packages/react/src/hooks/useFocusZone.ts +++ b/packages/react/src/hooks/useFocusZone.ts @@ -10,13 +10,13 @@ export interface FocusZoneHookSettings extends Omit + containerRef?: React.RefObject /** * If using the "active descendant" focus pattern, pass `true` or a ref to the controlling * element. If a ref object is not passed, we will create one for you. */ - activeDescendantFocus?: boolean | React.RefObject + activeDescendantFocus?: boolean | React.RefObject /** * Set to true to disable the focus zone and clean up listeners. Can be re-enabled at @@ -28,7 +28,10 @@ export interface FocusZoneHookSettings extends Omit; activeDescendantControlRef: React.RefObject} { +): { + containerRef: React.RefObject + activeDescendantControlRef: React.RefObject +} { const containerRef = useProvidedRefOrCreate(settings.containerRef) const useActiveDescendant = !!settings.activeDescendantFocus const passedActiveDescendantRef = diff --git a/packages/react/src/hooks/useMenuInitialFocus.ts b/packages/react/src/hooks/useMenuInitialFocus.ts index 3897796d8a0..20e0af08292 100644 --- a/packages/react/src/hooks/useMenuInitialFocus.ts +++ b/packages/react/src/hooks/useMenuInitialFocus.ts @@ -3,8 +3,8 @@ import {iterateFocusableElements} from '@primer/behaviors/utils' export const useMenuInitialFocus = ( open: boolean, - containerRef?: React.RefObject, - anchorRef?: React.RefObject, + containerRef?: React.RefObject, + anchorRef?: React.RefObject, ) => { /** * We need to pick the first element to focus based on how the menu was opened, diff --git a/packages/react/src/hooks/useMenuKeyboardNavigation.ts b/packages/react/src/hooks/useMenuKeyboardNavigation.ts index 96150189354..16192f2e228 100644 --- a/packages/react/src/hooks/useMenuKeyboardNavigation.ts +++ b/packages/react/src/hooks/useMenuKeyboardNavigation.ts @@ -14,8 +14,8 @@ import type {MenuCloseHandler} from '../ActionMenu' export const useMenuKeyboardNavigation = ( open: boolean, onClose: MenuCloseHandler | undefined, - containerRef?: React.RefObject, - anchorRef?: React.RefObject, + containerRef?: React.RefObject, + anchorRef?: React.RefObject, isSubmenu: boolean = false, ) => { useMenuInitialFocus(open, containerRef, anchorRef) @@ -32,8 +32,8 @@ export const useMenuKeyboardNavigation = ( const useCloseMenuOnTab = ( open: boolean, onClose: MenuCloseHandler | undefined, - containerRef?: React.RefObject, - anchorRef?: React.RefObject, + containerRef?: React.RefObject, + anchorRef?: React.RefObject, ) => { React.useEffect(() => { const container = containerRef?.current @@ -59,7 +59,7 @@ const useCloseSubmenuOnArrow = ( open: boolean, isSubmenu: boolean, onClose: MenuCloseHandler | undefined, - containerRef?: React.RefObject, + containerRef?: React.RefObject, ) => { React.useEffect(() => { const container = containerRef?.current @@ -81,8 +81,8 @@ const useCloseSubmenuOnArrow = ( */ const useMoveFocusToMenuItem = ( open: boolean, - containerRef?: React.RefObject, - anchorRef?: React.RefObject, + containerRef?: React.RefObject, + anchorRef?: React.RefObject, ) => { React.useEffect(() => { const container = containerRef?.current diff --git a/packages/react/src/hooks/useMnemonics.ts b/packages/react/src/hooks/useMnemonics.ts index 7c417a3c267..7f79e67001d 100644 --- a/packages/react/src/hooks/useMnemonics.ts +++ b/packages/react/src/hooks/useMnemonics.ts @@ -8,7 +8,7 @@ import {useProvidedRefOrCreate} from './useProvidedRefOrCreate' * typically appearing in a menu title, menu item, or the text of a button. */ -export const useMnemonics = (open: boolean, providedRef?: React.RefObject) => { +export const useMnemonics = (open: boolean, providedRef?: React.RefObject) => { const containerRef = useProvidedRefOrCreate(providedRef) React.useEffect( diff --git a/packages/react/src/hooks/useOnOutsideClick.tsx b/packages/react/src/hooks/useOnOutsideClick.tsx index 36dab73bdf9..7bbf341aa71 100644 --- a/packages/react/src/hooks/useOnOutsideClick.tsx +++ b/packages/react/src/hooks/useOnOutsideClick.tsx @@ -5,8 +5,8 @@ export type TouchOrMouseEvent = MouseEvent | TouchEvent type TouchOrMouseEventCallback = (event: TouchOrMouseEvent) => boolean | undefined export type UseOnOutsideClickSettings = { - containerRef: React.RefObject | React.RefObject - ignoreClickRefs?: React.RefObject[] + containerRef: React.RefObject | React.RefObject + ignoreClickRefs?: React.RefObject[] onClickOutside: (e: TouchOrMouseEvent) => void } diff --git a/packages/react/src/hooks/useOpenAndCloseFocus.ts b/packages/react/src/hooks/useOpenAndCloseFocus.ts index 06cccfe0f2f..fd804b30b7b 100644 --- a/packages/react/src/hooks/useOpenAndCloseFocus.ts +++ b/packages/react/src/hooks/useOpenAndCloseFocus.ts @@ -3,9 +3,9 @@ import {useEffect} from 'react' import {iterateFocusableElements} from '@primer/behaviors/utils' export type UseOpenAndCloseFocusSettings = { - initialFocusRef?: React.RefObject - containerRef: React.RefObject - returnFocusRef: React.RefObject + initialFocusRef?: React.RefObject + containerRef: React.RefObject + returnFocusRef: React.RefObject preventFocusOnOpen?: boolean } diff --git a/packages/react/src/hooks/useOverlay.tsx b/packages/react/src/hooks/useOverlay.tsx index 41fb3fc73a2..4e61ed4954b 100644 --- a/packages/react/src/hooks/useOverlay.tsx +++ b/packages/react/src/hooks/useOverlay.tsx @@ -5,17 +5,17 @@ import {useOnEscapePress} from './useOnEscapePress' import {useProvidedRefOrCreate} from './useProvidedRefOrCreate' export type UseOverlaySettings = { - ignoreClickRefs?: React.RefObject[] - initialFocusRef?: React.RefObject - returnFocusRef: React.RefObject + ignoreClickRefs?: React.RefObject[] + initialFocusRef?: React.RefObject + returnFocusRef: React.RefObject onEscape: (e: KeyboardEvent) => void onClickOutside: (e: TouchOrMouseEvent) => void - overlayRef?: React.RefObject + overlayRef?: React.RefObject preventFocusOnOpen?: boolean } export type OverlayReturnProps = { - ref: React.RefObject + ref: React.RefObject } export const useOverlay = ({ @@ -27,7 +27,7 @@ export const useOverlay = ({ onClickOutside, preventFocusOnOpen, }: UseOverlaySettings): OverlayReturnProps => { - const overlayRef = useProvidedRefOrCreate(_overlayRef) + const overlayRef = useProvidedRefOrCreate(_overlayRef) useOpenAndCloseFocus({containerRef: overlayRef, returnFocusRef, initialFocusRef, preventFocusOnOpen}) useOnOutsideClick({containerRef: overlayRef, ignoreClickRefs, onClickOutside}) diff --git a/packages/react/src/hooks/useProvidedRefOrCreate.ts b/packages/react/src/hooks/useProvidedRefOrCreate.ts index b9fa481232d..bfd209cbde2 100644 --- a/packages/react/src/hooks/useProvidedRefOrCreate.ts +++ b/packages/react/src/hooks/useProvidedRefOrCreate.ts @@ -8,7 +8,7 @@ import React from 'react' * @param providedRef The ref to use - if undefined, will use the ref from a call to React.useRef * @type TRef The type of the RefObject which should be created. */ -export function useProvidedRefOrCreate(providedRef?: React.RefObject): React.RefObject { +export function useProvidedRefOrCreate(providedRef?: React.RefObject): React.RefObject { const createdRef = React.useRef(null) return providedRef ?? createdRef } diff --git a/packages/react/src/hooks/useResizeObserver.ts b/packages/react/src/hooks/useResizeObserver.ts index c170fa5478e..704673af082 100644 --- a/packages/react/src/hooks/useResizeObserver.ts +++ b/packages/react/src/hooks/useResizeObserver.ts @@ -11,7 +11,7 @@ export interface ResizeObserverEntry { export function useResizeObserver( callback: ResizeObserverCallback, - target?: RefObject, + target?: RefObject, depsArray: unknown[] = [], ) { const [targetClientRect, setTargetClientRect] = useState(null) diff --git a/packages/react/src/hooks/useScrollFlash.ts b/packages/react/src/hooks/useScrollFlash.ts index ad8e211d42d..a22658826a6 100644 --- a/packages/react/src/hooks/useScrollFlash.ts +++ b/packages/react/src/hooks/useScrollFlash.ts @@ -4,7 +4,7 @@ import {useEffect} from 'react' * This hook will flash the scrollbars for a ref of a container that has scrollable overflow * @param scrollContainerRef The ref of the scrollable content */ -export default function useScrollFlash(scrollContainerRef: React.RefObject) { +export default function useScrollFlash(scrollContainerRef: React.RefObject) { // https://adxlv.computer/projects/flash-scrollers/ useEffect(() => { const scrollContainer = scrollContainerRef.current From 6e1451cd0d058a4c66c16303b93f2789f24b46f6 Mon Sep 17 00:00:00 2001 From: Pavithra Kodmad Date: Wed, 26 Nov 2025 12:15:25 +1100 Subject: [PATCH 2/4] Create three-years-film.md --- .changeset/three-years-film.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/three-years-film.md diff --git a/.changeset/three-years-film.md b/.changeset/three-years-film.md new file mode 100644 index 00000000000..a8e411bf247 --- /dev/null +++ b/.changeset/three-years-film.md @@ -0,0 +1,5 @@ +--- +"@primer/react": patch +--- + +chore - Fix type compatibility with react 19 refs From 318b54c86034088f69114d16c837318b3728d79b Mon Sep 17 00:00:00 2001 From: Pavithra Kodmad Date: Wed, 26 Nov 2025 22:28:14 +1100 Subject: [PATCH 3/4] Add type compat for dialog and hooks --- packages/react/src/deprecated/DialogV1/Dialog.tsx | 4 ++-- .../src/experimental/SelectPanel2/SelectPanel.tsx | 2 +- packages/react/src/hooks/useDialog.ts | 10 +++++----- packages/react/src/hooks/useRefObjectAsForwardedRef.ts | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/react/src/deprecated/DialogV1/Dialog.tsx b/packages/react/src/deprecated/DialogV1/Dialog.tsx index b39af5aa2da..caad7a4ab2c 100644 --- a/packages/react/src/deprecated/DialogV1/Dialog.tsx +++ b/packages/react/src/deprecated/DialogV1/Dialog.tsx @@ -35,8 +35,8 @@ function DialogHeader({children, className, as: Component = 'div', ...rest}: Dia type InternalDialogProps = { isOpen?: boolean onDismiss?: () => void - initialFocusRef?: React.RefObject - returnFocusRef?: React.RefObject + initialFocusRef?: React.RefObject + returnFocusRef?: React.RefObject as?: React.ElementType } & StyledDialogBaseProps & HTMLAttributes diff --git a/packages/react/src/experimental/SelectPanel2/SelectPanel.tsx b/packages/react/src/experimental/SelectPanel2/SelectPanel.tsx index a8ae8ee2e14..d3b2e7a988d 100644 --- a/packages/react/src/experimental/SelectPanel2/SelectPanel.tsx +++ b/packages/react/src/experimental/SelectPanel2/SelectPanel.tsx @@ -63,7 +63,7 @@ export type SelectPanelProps = { defaultOpen?: boolean open?: boolean - anchorRef?: React.RefObject + anchorRef?: React.RefObject anchoredPositionSettings?: Partial onCancel?: () => void diff --git a/packages/react/src/hooks/useDialog.ts b/packages/react/src/hooks/useDialog.ts index f744d3aa500..4a91b3c56c9 100644 --- a/packages/react/src/hooks/useDialog.ts +++ b/packages/react/src/hooks/useDialog.ts @@ -13,13 +13,13 @@ function focusable(el: Element) { } type UseDialogParameters = { - modalRef: React.RefObject - overlayRef: React.RefObject + modalRef: React.RefObject + overlayRef: React.RefObject isOpen?: boolean onDismiss?: () => void - initialFocusRef?: React.RefObject - closeButtonRef?: React.RefObject - returnFocusRef?: React.RefObject + initialFocusRef?: React.RefObject + closeButtonRef?: React.RefObject + returnFocusRef?: React.RefObject } function useDialog({ diff --git a/packages/react/src/hooks/useRefObjectAsForwardedRef.ts b/packages/react/src/hooks/useRefObjectAsForwardedRef.ts index ccaa0e8e048..11becf147d7 100644 --- a/packages/react/src/hooks/useRefObjectAsForwardedRef.ts +++ b/packages/react/src/hooks/useRefObjectAsForwardedRef.ts @@ -8,6 +8,6 @@ import {useImperativeHandle} from 'react' * * **NOTE**: The `refObject` should be passed to the underlying element, NOT the `forwardedRef`. */ -export function useRefObjectAsForwardedRef(forwardedRef: ForwardedRef, refObject: RefObject): void { +export function useRefObjectAsForwardedRef(forwardedRef: ForwardedRef, refObject: RefObject): void { useImperativeHandle(forwardedRef, () => refObject.current) } From 8283d7babe42617b61fcaf750c55d5643c19129a Mon Sep 17 00:00:00 2001 From: Pavithra Kodmad Date: Thu, 27 Nov 2025 05:53:10 +1100 Subject: [PATCH 4/4] Delete examples/nextjs/src/app/products/page.tsx --- examples/nextjs/src/app/products/page.tsx | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100644 examples/nextjs/src/app/products/page.tsx diff --git a/examples/nextjs/src/app/products/page.tsx b/examples/nextjs/src/app/products/page.tsx deleted file mode 100644 index e67345d472d..00000000000 --- a/examples/nextjs/src/app/products/page.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import React from 'react' -import {Button} from '@primer/react' - -// Minimal products page to satisfy type generation and provide a simple sample. -export default function ProductsPage() { - return ( -
-

Products

-

This is a placeholder Products page for the Next.js example.

- -
- ) -}