fix(catalog): autofocus first EntityContextMenu item

Signed-off-by: logonoff <git@logonoff.co>
This commit is contained in:
logonoff
2025-06-30 15:35:18 -04:00
parent 97b633a98b
commit ce1239e049
3 changed files with 69 additions and 56 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-catalog': patch
---
Auto-focus the first menu item in `EntityContextMenu`, and do not render a divider if an empty array is passed to `UNSTABLE_extraContextMenuItems`.
@@ -103,22 +103,58 @@ export function EntityContextMenu(props: EntityContextMenuProps) {
}
}, [copyState, alertApi, t]);
const extraItems = UNSTABLE_extraContextMenuItems && [
...UNSTABLE_extraContextMenuItems.map(item => (
<MenuItem
key={item.title}
onClick={() => {
onClose();
item.onClick();
}}
>
<ListItemIcon>
<item.Icon fontSize="small" />
</ListItemIcon>
<ListItemText primary={item.title} />
</MenuItem>
)),
<Divider key="the divider is here!" />,
const extraItems = UNSTABLE_extraContextMenuItems?.length
? [
...UNSTABLE_extraContextMenuItems.map(item => (
<MenuItem
key={item.title}
onClick={() => {
onClose();
item.onClick();
}}
>
<ListItemIcon>
<item.Icon fontSize="small" />
</ListItemIcon>
<ListItemText primary={item.title} />
</MenuItem>
)),
<Divider key="the divider is here!" />,
]
: null;
const defaultMenuItems = [
<UnregisterEntity
unregisterEntityOptions={UNSTABLE_contextMenuOptions}
isUnregisterAllowed={isAllowed}
onUnregisterEntity={onUnregisterEntity}
onClose={onClose}
key="unregister-entity"
/>,
<MenuItem
onClick={() => {
onClose();
onInspectEntity();
}}
key="inspect-entity"
>
<ListItemIcon>
<BugReportIcon fontSize="small" />
</ListItemIcon>
<ListItemText primary={t('entityContextMenu.inspectMenuTitle')} />
</MenuItem>,
<MenuItem
onClick={() => {
onClose();
copyToClipboard(window.location.toString());
}}
key="copy-url"
>
<ListItemIcon>
<FileCopyTwoToneIcon fontSize="small" />
</ListItemIcon>
<ListItemText primary={t('entityContextMenu.copyURLMenuTitle')} />
</MenuItem>,
];
return (
@@ -152,40 +188,7 @@ export function EntityContextMenu(props: EntityContextMenuProps) {
<MenuList autoFocusItem={Boolean(anchorEl)}>
{extraItems}
{contextMenuItems === undefined ? (
<>
<UnregisterEntity
unregisterEntityOptions={UNSTABLE_contextMenuOptions}
isUnregisterAllowed={isAllowed}
onUnregisterEntity={onUnregisterEntity}
onClose={onClose}
/>
<MenuItem
onClick={() => {
onClose();
onInspectEntity();
}}
>
<ListItemIcon>
<BugReportIcon fontSize="small" />
</ListItemIcon>
<ListItemText
primary={t('entityContextMenu.inspectMenuTitle')}
/>
</MenuItem>
<MenuItem
onClick={() => {
onClose();
copyToClipboard(window.location.toString());
}}
>
<ListItemIcon>
<FileCopyTwoToneIcon fontSize="small" />
</ListItemIcon>
<ListItemText
primary={t('entityContextMenu.copyURLMenuTitle')}
/>
</MenuItem>
</>
defaultMenuItems
) : (
<EntityContextMenuProvider onMenuClose={onClose}>
{contextMenuItems}
@@ -20,6 +20,7 @@ import MenuItem from '@material-ui/core/MenuItem';
import CancelIcon from '@material-ui/icons/Cancel';
import { catalogTranslationRef } from '../../alpha/translation';
import { useTranslationRef } from '@backstage/core-plugin-api/alpha';
import { forwardRef } from 'react';
type VisibleType = 'visible' | 'hidden' | 'disable';
@@ -34,7 +35,11 @@ interface UnregisterEntityProps {
onClose: () => void;
}
export function UnregisterEntity(props: UnregisterEntityProps) {
// TODO: When Backstage supports only React 19+, remove the forwardRef
export const UnregisterEntity = forwardRef<
HTMLLIElement,
UnregisterEntityProps
>((props, ref) => {
const {
unregisterEntityOptions,
isUnregisterAllowed,
@@ -53,16 +58,16 @@ export function UnregisterEntity(props: UnregisterEntityProps) {
: unregisterEntityOptions?.disableUnregister === 'disable')) ??
false;
let unregisterButton = <></>;
if (unregisterEntityOptions?.disableUnregister !== 'hidden') {
unregisterButton = (
return (
<MenuItem
ref={ref}
onClick={() => {
onClose();
onUnregisterEntity();
}}
disabled={isDisabled}
{...props}
>
<ListItemIcon>
<CancelIcon fontSize="small" />
@@ -72,5 +77,5 @@ export function UnregisterEntity(props: UnregisterEntityProps) {
);
}
return <>{unregisterButton}</>;
}
return null;
});