🐜 fix: Forward Ref to MCPSubMenu and ArtifactsSubMenu (#8696)

ToolsDropdown uses a menu library that passes refs to submenu items. Function components can't receive refs by default though, so we get  "Function components cannot be given refs" warnings in the console. React.forwardRef() allows them to properly handle ref forwarding by wrapping the component and attaching the ref to the outer div element.
This commit is contained in:
Dustin Healy 2025-07-28 09:26:11 -07:00 committed by GitHub
parent 0ef3fefaec
commit 4639dc3255
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 232 additions and 223 deletions

View file

@ -15,7 +15,9 @@ interface ArtifactsSubMenuProps {
handleCustomToggle: () => void;
}
const ArtifactsSubMenu = ({
const ArtifactsSubMenu = React.forwardRef<HTMLDivElement, ArtifactsSubMenuProps>(
(
{
isArtifactsPinned,
setIsArtifactsPinned,
artifactsMode,
@ -23,7 +25,9 @@ const ArtifactsSubMenu = ({
handleShadcnToggle,
handleCustomToggle,
...props
}: ArtifactsSubMenuProps) => {
},
ref,
) => {
const localize = useLocalize();
const menuStore = Ariakit.useMenuStore({
@ -37,6 +41,7 @@ const ArtifactsSubMenu = ({
const isCustomEnabled = artifactsMode === ArtifactModes.CUSTOM;
return (
<div ref={ref}>
<Ariakit.MenuProvider store={menuStore}>
<Ariakit.MenuItem
{...props}
@ -141,7 +146,11 @@ const ArtifactsSubMenu = ({
</Ariakit.Menu>
)}
</Ariakit.MenuProvider>
</div>
);
};
},
);
ArtifactsSubMenu.displayName = 'ArtifactsSubMenu';
export default React.memo(ArtifactsSubMenu);

View file

@ -11,7 +11,8 @@ interface MCPSubMenuProps {
placeholder?: string;
}
const MCPSubMenu = ({ placeholder, ...props }: MCPSubMenuProps) => {
const MCPSubMenu = React.forwardRef<HTMLDivElement, MCPSubMenuProps>(
({ placeholder, ...props }, ref) => {
const {
configuredServers,
mcpValues,
@ -37,7 +38,7 @@ const MCPSubMenu = ({ placeholder, ...props }: MCPSubMenuProps) => {
const configDialogProps = getConfigDialogProps();
return (
<>
<div ref={ref}>
<Ariakit.MenuProvider store={menuStore}>
<Ariakit.MenuItem
{...props}
@ -103,14 +104,10 @@ const MCPSubMenu = ({ placeholder, ...props }: MCPSubMenuProps) => {
'w-full min-w-0 justify-between text-sm',
)}
>
<button
type="button"
className="flex flex-grow items-center gap-2 rounded bg-transparent p-0 text-left transition-colors focus:outline-none"
tabIndex={0}
>
<div className="flex flex-grow items-center gap-2">
<Ariakit.MenuItemCheck checked={isSelected} />
<span>{serverName}</span>
</button>
</div>
{statusIcon && <div className="ml-2 flex items-center">{statusIcon}</div>}
</Ariakit.MenuItem>
);
@ -118,8 +115,11 @@ const MCPSubMenu = ({ placeholder, ...props }: MCPSubMenuProps) => {
</Ariakit.Menu>
</Ariakit.MenuProvider>
{configDialogProps && <MCPConfigDialog {...configDialogProps} />}
</>
</div>
);
};
},
);
MCPSubMenu.displayName = 'MCPSubMenu';
export default React.memo(MCPSubMenu);