[Security Solution][Endpoint] Fixes for ArtifactEntryCard Effected Policies popup menu (#118259) (#118541)

* new ContextMenuWithRouterSupport prop `fixedWidth`
* ArtifactCard - make effectScope popup menu fixed width
* Restrict the max width `hoverInfo` can take up in ContextMenuItemNavByRouter to 50%
* add test case for menu 'fixedWidth' prop

Co-authored-by: Paul Tavares <56442535+paul-tavares@users.noreply.github.com>
This commit is contained in:
Kibana Machine 2021-11-15 11:32:20 -05:00 committed by GitHub
parent 30b67553a8
commit 448788d1a8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 48 additions and 16 deletions

View file

@ -107,6 +107,7 @@ export const WithContextMenu = memo<WithContextMenuProps>(
return (
<ContextMenuWithRouterSupport
maxHeight="235px"
fixedWidth={true}
panelPaddingSize="none"
items={policies}
anchorPosition={policies.length > 1 ? 'rightCenter' : 'rightUp'}

View file

@ -5,7 +5,7 @@
* 2.0.
*/
import React, { memo } from 'react';
import React, { memo, useMemo } from 'react';
import {
EuiContextMenuItem,
EuiContextMenuItemProps,
@ -36,6 +36,7 @@ export interface ContextMenuItemNavByRouterProps extends EuiContextMenuItemProps
const StyledEuiContextMenuItem = styled(EuiContextMenuItem)`
.additional-info {
display: none;
max-width: 50%;
}
&:hover {
.additional-info {
@ -69,6 +70,18 @@ export const ContextMenuItemNavByRouter = memo<ContextMenuItemNavByRouterProps>(
onClick,
});
const getTestId = useTestIdGenerator(otherMenuItemProps['data-test-subj']);
const hoverComponentInstance = useMemo(() => {
// If the `hoverInfo` is not an object (ex. text, number), then auto-add the text truncation className.
// Adding this when the `hoverInfo` is a react component could cause issue, thus in htose cases, we
// assume the componet will handle how the data is truncated (if applicable)
const cssClassNames = `additional-info ${
'object' !== typeof hoverInfo ? 'eui-textTruncate' : ''
}`;
return hoverInfo ? (
<StyledEuiFlexItem className={cssClassNames}>{hoverInfo}</StyledEuiFlexItem>
) : null;
}, [hoverInfo]);
return (
<StyledEuiContextMenuItem
@ -88,16 +101,12 @@ export const ContextMenuItemNavByRouter = memo<ContextMenuItemNavByRouterProps>(
>
{children}
</div>
{hoverInfo && (
<StyledEuiFlexItem className="additional-info">{hoverInfo}</StyledEuiFlexItem>
)}
{hoverComponentInstance}
</>
) : (
<>
<EuiFlexItem>{children}</EuiFlexItem>
{hoverInfo && (
<StyledEuiFlexItem className="additional-info">{hoverInfo}</StyledEuiFlexItem>
)}
{hoverComponentInstance}
</>
)}
</EuiFlexGroup>

View file

@ -118,6 +118,17 @@ describe('When using the ContextMenuWithRouterSupport component', () => {
expect(renderResult.getByTestId('testMenu-item-2-truncateWrapper')).not.toBeNull();
});
it('should render popup menu with a fixed width that matches the `maxWidth` value', () => {
render({ maxWidth: '300px', fixedWidth: true });
clickMenuTriggerButton();
const contextMenuPanelStyles = getContextMenuPanel()!
.querySelector('.euiContextMenuPanel')!
.getAttribute('style');
expect(contextMenuPanelStyles).toMatch(/width:\W*300px/);
expect(contextMenuPanelStyles).not.toMatch(/max-width:\W*300px/);
});
it('should navigate using the router when item is clicked', () => {
render();
clickMenuTriggerButton();

View file

@ -32,6 +32,11 @@ export interface ContextMenuWithRouterSupportProps
* overwritten to `true`. Setting this prop's value to `undefined` will suppress the default behaviour.
*/
maxWidth?: CSSProperties['maxWidth'];
/**
* If `true`, then the menu will have a fixed width and will not be adjusted if the content it holds
* is shorter than `maxWidth` prop value.
*/
fixedWidth?: boolean;
/**
* The max height for the popup menu. Default is `255px`.
*/
@ -57,6 +62,7 @@ export const ContextMenuWithRouterSupport = memo<ContextMenuWithRouterSupportPro
anchorPosition,
maxWidth = '32ch',
maxHeight = '255px',
fixedWidth = false,
title,
loading = false,
hoverInfo,
@ -101,26 +107,31 @@ export const ContextMenuWithRouterSupport = memo<ContextMenuWithRouterSupportPro
});
}, [getTestId, handleCloseMenu, items, maxWidth, loading, hoverInfo]);
type AdditionalPanelProps = Partial<EuiContextMenuPanelProps & HTMLAttributes<HTMLDivElement>>;
type AdditionalPanelProps = Partial<
Omit<EuiContextMenuPanelProps & HTMLAttributes<HTMLDivElement>, 'style'>
> & {
style: Required<HTMLAttributes<HTMLDivElement>>['style'];
};
const additionalContextMenuPanelProps = useMemo<AdditionalPanelProps>(() => {
const newAdditionalProps: AdditionalPanelProps = {
className: 'eui-yScroll',
style: {},
};
if (maxWidth) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
newAdditionalProps.style!.maxWidth = maxWidth;
if (maxWidth && !fixedWidth) {
newAdditionalProps.style.maxWidth = maxWidth;
}
if (maxHeight) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
newAdditionalProps.style!.overflowY = 'scroll';
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
newAdditionalProps.style!.maxHeight = maxHeight;
newAdditionalProps.style.maxHeight = maxHeight;
}
if (fixedWidth) {
newAdditionalProps.style.width = maxWidth ?? '32ch';
}
return newAdditionalProps;
}, [maxWidth, maxHeight]);
}, [maxWidth, fixedWidth, maxHeight]);
return (
<EuiPopover