Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(components, protocol-designer): menuList and MenuItem cleanup for helix #17257

Open
wants to merge 5 commits into
base: edge
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions components/src/atoms/MenuList/MenuItem.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
import { STYLE_PROPS } from '../../primitives'
import { VIEWPORT } from '../../ui-style-constants'
import { MenuItem as MenuItemComponent } from './MenuItem'

import type { Meta, StoryObj } from '@storybook/react'

const meta: Meta<typeof MenuItemComponent> = {
title: 'Library/Atoms/MenuItem',
title: 'Helix/Atoms/MenuItem',
component: MenuItemComponent,
parameters: VIEWPORT.touchScreenViewport,
argTypes: {
// Disable all StyleProps
...Object.fromEntries(
[...STYLE_PROPS, 'as', 'ref', 'theme', 'forwardedAs'].map(prop => [
prop,
{ table: { disable: true } },
])
),
},
}
export default meta

Expand All @@ -16,5 +25,6 @@ export const MenuItem: Story = {
args: {
children: 'Example menu btn',
disabled: false,
isAlert: false,
},
}
7 changes: 6 additions & 1 deletion components/src/atoms/MenuList/MenuItem.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import styled from 'styled-components'
import { COLORS } from '../../helix-design-system'
import { BORDERS, COLORS } from '../../helix-design-system'
import { RESPONSIVENESS, SPACING, TYPOGRAPHY } from '../../ui-style-constants'
import { ALIGN_CENTER } from '../../styles'
import type { StyleProps } from '../../primitives'
Expand Down Expand Up @@ -28,6 +28,11 @@ export const MenuItem = styled.button<ButtonProps>`
color: ${COLORS.grey40};
}

&:focus-visible {
outline: 3px ${BORDERS.styleSolid} ${COLORS.blue50};
outline-offset: 2px;
}

@media ${RESPONSIVENESS.touchscreenMediaQuerySpecs} {
align-items: ${ALIGN_CENTER};
text-align: ${TYPOGRAPHY.textAlignCenter};
Expand Down
26 changes: 19 additions & 7 deletions components/src/atoms/MenuList/MenuList.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,27 @@
import { action } from '@storybook/addon-actions'
import { Flex, STYLE_PROPS } from '../../primitives'
import { DIRECTION_COLUMN } from '../../styles'
import { MenuList as MenuListComponent } from './index'
import { MenuItem } from './MenuItem'

import type { Meta, StoryObj } from '@storybook/react'

const menuBtn = 'example menu btn'
const menuBtn = 'Example menu btn'

const meta: Meta<typeof MenuListComponent> = {
title: 'Library/Atoms/MenuList',
title: 'Helix/Atoms/MenuList',
component: MenuListComponent,
args: {
onClick: action('clicked'),
argTypes: {
// Disable all StyleProps
...Object.fromEntries(
[
...STYLE_PROPS,
'as',
'ref',
'theme',
'forwardedAs',
'className',
].map(prop => [prop, { table: { disable: true } }])
),
},
}

Expand All @@ -21,11 +32,12 @@ type Story = StoryObj<typeof MenuListComponent>
export const MenuList: Story = {
args: {
children: (
<>
<Flex flexDirection={DIRECTION_COLUMN}>
<MenuItem>{menuBtn}</MenuItem>
<MenuItem>{menuBtn}</MenuItem>
<MenuItem>{menuBtn}</MenuItem>
</>
</Flex>
),
isOnDevice: false,
},
}
78 changes: 48 additions & 30 deletions components/src/atoms/MenuList/index.tsx
Original file line number Diff line number Diff line change
@@ -1,50 +1,68 @@
import { forwardRef } from 'react'
import { BORDERS, COLORS } from '../../helix-design-system'
import {
DIRECTION_COLUMN,
FLEX_MAX_CONTENT,
JUSTIFY_CENTER,
POSITION_ABSOLUTE,
} from '../../styles'
import { Flex } from '../../primitives'
import { SPACING } from '../../ui-style-constants'
import { ModalShell } from '../../modals'
import type { ForwardedRef, MouseEventHandler, ReactNode } from 'react'
import type { StyleProps } from '../../primitives'

import type { MouseEventHandler, ReactNode } from 'react'

interface MenuListProps {
interface MenuListProps extends StyleProps {
children: ReactNode
isOnDevice?: boolean
onClick?: MouseEventHandler
/** Optional ref - used in PD for overflowY */
ref?: ForwardedRef<HTMLInputElement>
}

export const MenuList = (props: MenuListProps): JSX.Element | null => {
const { children, isOnDevice = false, onClick = null } = props
return isOnDevice && onClick != null ? (
<ModalShell
borderRadius={BORDERS.borderRadius16}
width="max-content"
onOutsideClick={onClick}
>
export const MenuList = forwardRef<HTMLDivElement, MenuListProps>(
(props, ref): JSX.Element => {
const {
children,
isOnDevice = false,
onClick,
top = '2.6rem',
right = `calc(50% + ${SPACING.spacing4})`,
jerader marked this conversation as resolved.
Show resolved Hide resolved
width = FLEX_MAX_CONTENT,
zIndex = 10,
...restProps
} = props
return isOnDevice ? (
<ModalShell
borderRadius={BORDERS.borderRadius16}
width={FLEX_MAX_CONTENT}
onOutsideClick={onClick}
>
<Flex
boxShadow={BORDERS.shadowSmall}
flexDirection={DIRECTION_COLUMN}
justifyContent={JUSTIFY_CENTER}
>
{children}
</Flex>
</ModalShell>
) : (
<Flex
boxShadow={BORDERS.shadowSmall}
borderRadius={BORDERS.borderRadius8}
zIndex={zIndex}
boxShadow="0px 1px 3px rgba(0, 0, 0, 0.2)"
position={POSITION_ABSOLUTE}
backgroundColor={COLORS.white}
top={top}
right={right}
flexDirection={DIRECTION_COLUMN}
justifyContent={JUSTIFY_CENTER}
width={width}
onClick={onClick}
ref={ref}
{...restProps}
>
{children}
</Flex>
</ModalShell>
) : (
<Flex
borderRadius="4px 4px 0px 0px"
zIndex={10}
boxShadow="0px 1px 3px rgba(0, 0, 0, 0.2)"
position={POSITION_ABSOLUTE}
backgroundColor={COLORS.white}
top="2.6rem"
right={`calc(50% + ${SPACING.spacing4})`}
flexDirection={DIRECTION_COLUMN}
width="max-content"
>
{children}
</Flex>
)
}
)
}
)
2 changes: 1 addition & 1 deletion components/src/primitives/style-props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ const POSITION_PROPS = [

const TRANSITION_PROPS = ['transition'] as const

const STYLE_PROPS = [
export const STYLE_PROPS = [
...COLOR_PROPS,
...TYPOGRAPHY_PROPS,
...SPACING_PROPS,
Expand Down
12 changes: 3 additions & 9 deletions protocol-designer/src/pages/Designer/LiquidsOverflowMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { useDispatch, useSelector } from 'react-redux'
import { useLocation } from 'react-router-dom'
import {
ALIGN_CENTER,
BORDERS,
COLORS,
CURSOR_POINTER,
DIRECTION_COLUMN,
Expand All @@ -13,8 +12,8 @@ import {
Icon,
LiquidIcon,
MenuItem,
MenuList,
OVERFLOW_AUTO,
POSITION_ABSOLUTE,
SPACING,
StyledText,
TYPOGRAPHY,
Expand Down Expand Up @@ -42,17 +41,12 @@ export function LiquidsOverflowMenu(
const { t } = useTranslation(['starting_deck_state'])
const liquids = useSelector(labwareIngredSelectors.allIngredientNamesIds)
const dispatch: ThunkDispatch<any> = useDispatch()

return (
<Flex
position={POSITION_ABSOLUTE}
<MenuList
zIndex={12}
right={location.pathname === '/liquids' ? SPACING.spacing12 : '3.125rem'}
top={`calc(${NAV_HEIGHT} - 6px)`}
ref={overflowWrapperRef}
borderRadius={BORDERS.borderRadius8}
boxShadow="0px 1px 3px rgba(0, 0, 0, 0.2)"
backgroundColor={COLORS.white}
flexDirection={DIRECTION_COLUMN}
onClick={(e: MouseEvent) => {
e.preventDefault()
Expand Down Expand Up @@ -113,6 +107,6 @@ export function LiquidsOverflowMenu(
</StyledText>
</Flex>
</MenuItem>
</Flex>
</MenuList>
)
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,7 @@
import { useTranslation } from 'react-i18next'
import { useDispatch, useSelector } from 'react-redux'

import {
BORDERS,
COLORS,
DIRECTION_COLUMN,
Divider,
Flex,
MenuItem,
NO_WRAP,
POSITION_ABSOLUTE,
} from '@opentrons/components'
import { Divider, MenuItem, MenuList, NO_WRAP } from '@opentrons/components'
import { analyticsEvent } from '../../../../analytics/actions'
import { actions as stepsActions } from '../../../../ui/steps'
import {
Expand All @@ -26,7 +17,12 @@ import {
getUnsavedForm,
} from '../../../../step-forms/selectors'

import type { Dispatch, MutableRefObject, SetStateAction } from 'react'
import type {
Dispatch,
MouseEvent,
MutableRefObject,
SetStateAction,
} from 'react'
import type { ThunkDispatch } from 'redux-thunk'
import type { BaseState } from '../../../../types'
import type { StepIdType } from '../../../../form-types'
Expand Down Expand Up @@ -97,17 +93,13 @@ export function StepOverflowMenu(props: StepOverflowMenuProps): JSX.Element {

return (
<>
<Flex
ref={menuRootRef}
<MenuList
zIndex={12}
ref={menuRootRef}
top={top}
left="18.75rem"
position={POSITION_ABSOLUTE}
right={undefined}
jerader marked this conversation as resolved.
Show resolved Hide resolved
whiteSpace={NO_WRAP}
borderRadius={BORDERS.borderRadius8}
boxShadow="0px 1px 3px rgba(0, 0, 0, 0.2)"
backgroundColor={COLORS.white}
flexDirection={DIRECTION_COLUMN}
onClick={(e: MouseEvent) => {
e.preventDefault()
e.stopPropagation()
Expand Down Expand Up @@ -173,7 +165,7 @@ export function StepOverflowMenu(props: StepOverflowMenuProps): JSX.Element {
</MenuItem>
</>
)}
</Flex>
</MenuList>
</>
)
}
Loading