diff --git a/packages/react-component-library/src/components/ContextMenu/ContextMenu.stories.tsx b/packages/react-component-library/src/components/ContextMenu/ContextMenu.stories.tsx index f336ad3966..8b3bfc3874 100644 --- a/packages/react-component-library/src/components/ContextMenu/ContextMenu.stories.tsx +++ b/packages/react-component-library/src/components/ContextMenu/ContextMenu.stories.tsx @@ -57,3 +57,44 @@ export const Default = () => { } Default.storyName = 'Default' + +export const NoIcons = () => { + const ref = useRef() + + return ( + <> +
+ Right click me! +
+ + + Edit} /> + Delete} /> + Action} /> + + Add} /> + + Do something else} + /> + + + This is too much text to put into a context menu item + + )} + /> + + + ) +} + +NoIcons.storyName = 'No icons' diff --git a/packages/react-component-library/src/components/ContextMenu/ContextMenu.test.tsx b/packages/react-component-library/src/components/ContextMenu/ContextMenu.test.tsx index 922f6775b9..7423d0406e 100644 --- a/packages/react-component-library/src/components/ContextMenu/ContextMenu.test.tsx +++ b/packages/react-component-library/src/components/ContextMenu/ContextMenu.test.tsx @@ -2,6 +2,7 @@ import React, { useRef } from 'react' import '@testing-library/jest-dom/extend-expect' import { RenderResult, render, fireEvent, act } from '@testing-library/react' import { IconSettings } from '@royalnavy/icon-library' +import 'jest-styled-components' import { ContextMenu, ContextMenuItem, ContextMenuDivider } from '.' import { Link } from '../Link' @@ -18,7 +19,7 @@ describe('ContextMenu', () => { let wrapper: RenderResult let onClickSpy: (e: React.MouseEvent) => void - describe('With links and closed', () => { + describe('With links, no icons and closed', () => { beforeEach(() => { const ContextExample = () => { const ref = useRef() @@ -46,7 +47,7 @@ describe('ContextMenu', () => { }) }) - describe('With links and open', () => { + describe('With links, no icons and and open', () => { beforeEach(() => { const ContextExample = () => { const ref = useRef() @@ -71,6 +72,12 @@ describe('ContextMenu', () => { fireEvent.contextMenu(wrapper.getByText('Right click me!')) }) + it('should add margin to items', () => { + wrapper.getAllByTestId('context-menu-item-text').forEach((item) => { + expect(item).toHaveStyleRule('margin-left', '1.25rem') + }) + }) + it('is rendered to the DOM', () => { expect(wrapper.queryByTestId('context-menu')).toBeInTheDocument() }) @@ -149,6 +156,12 @@ describe('ContextMenu', () => { fireEvent.contextMenu(wrapper.getByText('Right click me!')) }) + it('should not add margin to items', () => { + wrapper.getAllByTestId('context-menu-item-text').forEach((item) => { + expect(item).not.toHaveStyleRule('margin-left', '1.25rem') + }) + }) + it('renders the icons', () => { expect( wrapper.queryByTestId('context-menu-item-icon') diff --git a/packages/react-component-library/src/components/ContextMenu/ContextMenu.tsx b/packages/react-component-library/src/components/ContextMenu/ContextMenu.tsx index e6a127c0e8..79c9b4d11f 100644 --- a/packages/react-component-library/src/components/ContextMenu/ContextMenu.tsx +++ b/packages/react-component-library/src/components/ContextMenu/ContextMenu.tsx @@ -1,9 +1,10 @@ import React from 'react' -import styled from 'styled-components' +import styled, { css } from 'styled-components' import { selectors } from '@royalnavy/design-tokens' import { ComponentWithClass } from '../../common/ComponentWithClass' import { useRightClick } from '../../hooks/useRightClick' +import { StyledText } from './ContextMenuItem' interface ContextMenuProps extends ComponentWithClass { attachedToRef?: React.RefObject @@ -12,6 +13,7 @@ interface ContextMenuProps extends ComponentWithClass { interface StyledContextMenuProps { top: number left: number + $hasIcons: boolean } const { color, spacing } = selectors @@ -28,6 +30,14 @@ const StyledContextMenu = styled.ol` border-radius: 4px; border: 1px solid ${color('neutral', '200')}; box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.12), 0 1px 3px 0 rgba(0, 0, 0, 0.04); + + ${({ $hasIcons }) => + !$hasIcons && + css` + ${StyledText} { + margin-left: 0; + } + `} ` export const ContextMenu: React.FC = ({ @@ -37,6 +47,10 @@ export const ContextMenu: React.FC = ({ }) => { const { position, isOpen } = useRightClick(attachedToRef) + const hasIcons = !!React.Children.toArray(children).filter( + (child: React.ReactNode) => (child as React.ReactElement)?.props?.icon + ).length + return ( <> {isOpen && ( @@ -44,6 +58,7 @@ export const ContextMenu: React.FC = ({ className={className} top={position.y} left={position.x} + $hasIcons={hasIcons} data-testid="context-menu" > {children} diff --git a/packages/react-component-library/src/components/ContextMenu/ContextMenuItem.tsx b/packages/react-component-library/src/components/ContextMenu/ContextMenuItem.tsx index 0003f4e1f2..ed4c74c331 100644 --- a/packages/react-component-library/src/components/ContextMenu/ContextMenuItem.tsx +++ b/packages/react-component-library/src/components/ContextMenu/ContextMenuItem.tsx @@ -14,8 +14,9 @@ interface StyledTextProps { const { color, fontSize, spacing } = selectors -const StyledContextMenuItem = styled.li` +export const StyledContextMenuItem = styled.li` border-radius: 2px; + > * { text-overflow: ellipsis; display: flex; @@ -32,7 +33,7 @@ const StyledContextMenuItem = styled.li` } ` -const StyledIcon = styled.div` +export const StyledIcon = styled.div` display: inline-flex; align-items: center; margin-right: ${spacing('2')}; @@ -42,7 +43,7 @@ const StyledIcon = styled.div` } ` -const StyledText = styled.div` +export const StyledText = styled.div` color: ${color('neutral', '400')}; font-weight: 600; font-size: ${fontSize('base')}; @@ -68,7 +69,9 @@ export const ContextMenuItem: React.FC = ({ children: ( <> {icon && {icon}} - {linkElement.props.children} + + {linkElement.props.children} + ), })