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

fix(protocol-designer): Fix deck view size issues in pd #16616

Merged
merged 14 commits into from
Oct 31, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@ interface RobotCoordinateSpaceWithRefProps
extends React.ComponentProps<typeof Svg> {
viewBox?: string | null
deckDef?: DeckDefinition
zoomed?: boolean
children?: (props: RobotCoordinateSpaceWithRefRenderProps) => React.ReactNode
}

export function RobotCoordinateSpaceWithRef(
props: RobotCoordinateSpaceWithRefProps
): JSX.Element | null {
const { children, deckDef, viewBox, ...restProps } = props
const { children, deckDef, viewBox, zoomed = false, ...restProps } = props
const wrapperRef = React.useRef<SVGSVGElement>(null)

if (deckDef == null && viewBox == null) return null
Expand All @@ -31,13 +32,20 @@ export function RobotCoordinateSpaceWithRef(
(acc, deckSlot) => ({ ...acc, [deckSlot.id]: deckSlot }),
{}
)
wholeDeckViewBox = `${viewBoxOriginX} ${viewBoxOriginY} ${deckXDimension} ${deckYDimension}`

// Add padding to prevent clipping and better center the content
const PADDING = deckDef.otId === 'ot2_standard' ? 5 : 20
wholeDeckViewBox = `${viewBoxOriginX - PADDING} ${
viewBoxOriginY + PADDING
} ${deckXDimension + PADDING * 2} ${deckYDimension + PADDING * 2}`
}
return (
<Svg
viewBox={viewBox || wholeDeckViewBox}
viewBox={zoomed ? viewBox : wholeDeckViewBox}
ref={wrapperRef}
transform="scale(1, -1)"
width="100%"
height="100%"
{...restProps}
>
{children?.({ deckSlotsById })}
Expand Down
1 change: 1 addition & 0 deletions protocol-designer/src/atoms/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,5 @@ export const LINE_CLAMP_TEXT_STYLE = (
text-overflow: ellipsis;
word-wrap: break-word;
-webkit-line-clamp: ${lineClamp};
word-break: break-all; // for a non word case like aaaaaaaa
`
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
import { selectors as labwareIngredSelectors } from '../../labware-ingred/selectors'
import { getLabwareEntities } from '../../step-forms/selectors'
import * as wellContentsSelectors from '../../top-selectors/well-contents'
import { LINE_CLAMP_TEXT_STYLE } from '../../atoms'

import type { LiquidInfo } from './LiquidToolbox'

Expand Down Expand Up @@ -80,8 +81,16 @@ export function LiquidCard(props: LiquidCardProps): JSX.Element {
>
<LiquidIcon color={color ?? ''} size="medium" />
<Flex flexDirection={DIRECTION_COLUMN} width="12.375rem">
<StyledText desktopStyle="bodyDefaultSemiBold">{name}</StyledText>
<StyledText desktopStyle="bodyDefaultRegular">
<StyledText
desktopStyle="bodyDefaultSemiBold"
css={LINE_CLAMP_TEXT_STYLE(3)}
>
{name}
</StyledText>
<StyledText
desktopStyle="bodyDefaultRegular"
css={LINE_CLAMP_TEXT_STYLE(3)}
>
{info.liquidIndex != null
? liquidsWithDescriptions[info.liquidIndex].description
: null}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { describe, it, expect } from 'vitest'
import { checkColor } from '../utils'

describe('checkColor', () => {
it('should return true for very dark colors', () => {
expect(checkColor('#000000')).toBe(true)
expect(checkColor('#0a0a0a')).toBe(true)
})

it('should return true for very light colors', () => {
expect(checkColor('#ffffff')).toBe(true)
expect(checkColor('#f5f5f5')).toBe(true)
})

it('should return false for colors with medium luminance', () => {
expect(checkColor('#808080')).toBe(false)
expect(checkColor('#ff0000')).toBe(false)
expect(checkColor('#00ff00')).toBe(false)
expect(checkColor('#0000ff')).toBe(false)
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import { selectors as labwareIngredSelectors } from '../../labware-ingred/select
import { swatchColors } from '../../components/swatchColors'
import { checkColor } from './utils'
import { HandleEnter } from '../../atoms/HandleEnter'
import { LINE_CLAMP_TEXT_STYLE } from '../../atoms'

import type { ColorResult, RGBColor } from 'react-color'
import type { ThunkDispatch } from 'redux-thunk'
Expand Down Expand Up @@ -173,7 +174,10 @@ export function DefineLiquidsModal(
selectedIngredFields != null ? (
<Flex gridGap={SPACING.spacing8}>
<LiquidIcon color={initialValues.displayColor} />
<StyledText desktopStyle="bodyLargeSemiBold">
<StyledText
desktopStyle="bodyLargeSemiBold"
css={LINE_CLAMP_TEXT_STYLE(1)}
>
{initialValues.name}
</StyledText>
</Flex>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { describe, it, expect } from 'vitest'
import { FLEX_ROBOT_TYPE, OT2_ROBOT_TYPE } from '@opentrons/shared-data'
import { getXPosition } from '../utils'

describe('getXPosition', () => {
it('should return the right position 600 for FLEX robot type and slot 3', () => {
expect(getXPosition('3', FLEX_ROBOT_TYPE, false)).toBe('600')
})

it('should return the right position 700 for FLEX robot type and slot 4', () => {
expect(getXPosition('4', FLEX_ROBOT_TYPE, true)).toBe('700')
})

it('should return the left position for FLEX robot type and slot 1', () => {
expect(getXPosition('1', FLEX_ROBOT_TYPE, false)).toBe('-400')
})

it('should return the right position for OT2 robot type and slot 6', () => {
expect(getXPosition('6', OT2_ROBOT_TYPE, false)).toBe('500')
})

it('should return the left position for OT2 robot type and slot 2', () => {
expect(getXPosition('2', OT2_ROBOT_TYPE, false)).toBe('-300')
})
})
12 changes: 9 additions & 3 deletions protocol-designer/src/organisms/SlotDetailsContainer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,17 @@ import { useTranslation } from 'react-i18next'
import { getModuleDisplayName } from '@opentrons/shared-data'
import { RobotCoordsForeignObject } from '@opentrons/components'
import * as wellContentsSelectors from '../../top-selectors/well-contents'
import { getAdditionalEquipmentEntities } from '../../step-forms/selectors'
import { selectors } from '../../labware-ingred/selectors'
import { selectors as uiLabwareSelectors } from '../../ui/labware'
import { getDeckSetupForActiveItem } from '../../top-selectors/labware-locations'
import { SlotInformation } from '../../organisms/SlotInformation'
import { getYPosition } from './utils'
import { getXPosition } from './utils'

import type { DeckSlotId, RobotType } from '@opentrons/shared-data'
import type { ContentsByWell } from '../../labware-ingred/types'

const SLOT_DETAIL_Y_POSITION = '-10'
interface SlotDetailContainerProps {
robotType: RobotType
slot: DeckSlotId | null
Expand All @@ -31,6 +33,10 @@ export function SlotDetailsContainer(
)
const nickNames = useSelector(uiLabwareSelectors.getLabwareNicknamesById)
const allIngredNamesIds = useSelector(selectors.allIngredientNamesIds)
const additionalEquipment = useSelector(getAdditionalEquipmentEntities)
const hasStagingArea = Object.values(additionalEquipment).some(
item => item.name === 'stagingArea'
)

if (slot == null || (slot === 'offDeck' && offDeckLabwareId == null)) {
return null
Expand Down Expand Up @@ -106,8 +112,8 @@ export function SlotDetailsContainer(
<RobotCoordsForeignObject
width="15.8125rem"
height="26.75rem"
x="-400"
y={getYPosition({ robotType, slot })}
x={getXPosition(slot, robotType, hasStagingArea)}
y={SLOT_DETAIL_Y_POSITION}
>
<SlotInformation
location={slot}
Expand Down
28 changes: 28 additions & 0 deletions protocol-designer/src/organisms/SlotDetailsContainer/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,31 @@ export const getYPosition = ({ robotType, slot }: YPositionProps): string => {
}
}
}

export const getXPosition = (
slot: string,
robotType: RobotType,
hasStagingArea: boolean
): string => {
const POSITION_MAP = {
FLEX: {
right: (slot: string) => (hasStagingArea ? '700' : '600'),
left: '-400',
regex: /[34]/,
},
OT2: {
right: '500',
left: '-300',
regex: /[369]/,
},
}

const { right, left, regex } =
robotType === FLEX_ROBOT_TYPE ? POSITION_MAP.FLEX : POSITION_MAP.OT2

return regex.test(slot)
? typeof right === 'function'
? right(slot)
: right
: left
}
12 changes: 11 additions & 1 deletion protocol-designer/src/organisms/SlotInformation/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import {
TYPOGRAPHY,
} from '@opentrons/components'
import { FLEX_ROBOT_TYPE } from '@opentrons/shared-data'
import { LINE_CLAMP_TEXT_STYLE } from '../../atoms'

import type { FC } from 'react'
import type { RobotType } from '@opentrons/shared-data'

Expand Down Expand Up @@ -53,7 +55,15 @@ export const SlotInformation: FC<SlotInformationProps> = ({
<ListItem type="noActive" width="max-content">
<ListItemDescriptor
type="default"
content={<StyledText>{liquids.join(', ')}</StyledText>}
content={
<StyledText
desktopStyle="bodyDefaultRegular"
textAlign={TYPOGRAPHY.textAlignRight}
css={LINE_CLAMP_TEXT_STYLE(2)}
>
{liquids.join(', ')}
</StyledText>
}
description={t('liquid')}
/>
</ListItem>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ export function DeckSetupContainer(props: DeckSetupTabType): JSX.Element {
backgroundColor={COLORS.white}
borderRadius={BORDERS.borderRadius12}
width="100%"
height={zoomIn.slot != null ? '75vh' : '65vh'}
height={zoomIn.slot != null ? '75vh' : '70vh'}
flexDirection={DIRECTION_COLUMN}
padding={SPACING.spacing40}
>
Expand All @@ -187,11 +187,12 @@ export function DeckSetupContainer(props: DeckSetupTabType): JSX.Element {
justifyContent={JUSTIFY_CENTER}
>
<RobotCoordinateSpaceWithRef
height={zoomIn.slot != null ? '100%' : '80%'}
height={zoomIn.slot != null ? '100%' : '95%'}
width="100%"
deckDef={deckDef}
viewBox={viewBox}
outline="auto"
zoomed={zoomIn.slot != null}
>
{() => (
<>
Expand Down
17 changes: 13 additions & 4 deletions protocol-designer/src/pages/Designer/LiquidsOverflowMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@ import {
Flex,
Icon,
LiquidIcon,
NO_WRAP,
POSITION_ABSOLUTE,
SPACING,
StyledText,
TYPOGRAPHY,
} from '@opentrons/components'
import { LINE_CLAMP_TEXT_STYLE } from '../../atoms'
import { selectors as labwareIngredSelectors } from '../../labware-ingred/selectors'
import * as labwareIngredActions from '../../labware-ingred/actions'
import type { ThunkDispatch } from '../../types'
Expand Down Expand Up @@ -46,7 +47,6 @@ export function LiquidsOverflowMenu(
zIndex={5}
right={location.pathname === '/liquids' ? SPACING.spacing12 : '3.125rem'}
top={`calc(${NAV_HEIGHT} - 6px)`}
whiteSpace={NO_WRAP}
ref={overflowWrapperRef}
borderRadius={BORDERS.borderRadius8}
boxShadow="0px 1px 3px rgba(0, 0, 0, 0.2)"
Expand All @@ -56,6 +56,7 @@ export function LiquidsOverflowMenu(
e.preventDefault()
e.stopPropagation()
}}
width="9.375rem"
>
{liquids.map(({ name, displayColor, ingredientId }) => {
return (
Expand All @@ -70,7 +71,15 @@ export function LiquidsOverflowMenu(
>
<Flex alignItems={ALIGN_CENTER} gridGap={SPACING.spacing8}>
<LiquidIcon color={displayColor ?? ''} />
<StyledText desktopStyle="bodyDefaultRegular">{name}</StyledText>
<StyledText
desktopStyle="bodyDefaultRegular"
css={`
${LINE_CLAMP_TEXT_STYLE(3)}
text-align: ${TYPOGRAPHY.textAlignLeft}
`}
>
{name}
</StyledText>
</Flex>
</MenuButton>
)
Expand All @@ -87,7 +96,7 @@ export function LiquidsOverflowMenu(
}}
key="defineLiquid"
>
<Flex alignItems={ALIGN_CENTER} gridGap={SPACING.spacing4}>
<Flex alignItems={ALIGN_CENTER} gridGap={SPACING.spacing8}>
<Icon name="plus" size="1rem" />
<StyledText desktopStyle="bodyDefaultRegular">
{t('define_liquid')}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -234,10 +234,7 @@ export function StepFormToolbox(props: StepFormToolboxProps): JSX.Element {
<Icon size="1rem" name={icon} minWidth="1rem" />
<StyledText
desktopStyle="bodyLargeSemiBold"
css={`
${LINE_CLAMP_TEXT_STYLE(2)}
word-break: break-all
`}
css={LINE_CLAMP_TEXT_STYLE(2)}
>
{capitalizeFirstLetter(String(formData.stepName))}
</StyledText>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -227,10 +227,7 @@ export function StepContainer(props: StepContainerProps): JSX.Element {
)}
<StyledText
desktopStyle="bodyDefaultRegular"
css={`
${LINE_CLAMP_TEXT_STYLE(1)}
word-break: break-all
`}
css={LINE_CLAMP_TEXT_STYLE(1)}
>
{capitalizeFirstLetterAfterNumber(title)}
</StyledText>
Expand Down
2 changes: 1 addition & 1 deletion protocol-designer/src/pages/Designer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ export function Designer(): JSX.Element {
padding={zoomIn.slot != null ? '0' : SPACING.spacing80}
height="calc(100vh - 64px)"
>
<Flex flexDirection={DIRECTION_COLUMN} gridGap={SPACING.spacing24}>
<Flex flexDirection={DIRECTION_COLUMN}>
{zoomIn.slot == null ? (
<Flex alignSelf={ALIGN_END}>
<ToggleGroup
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
RobotCoordinateSpaceWithRef,
SingleSlotFixture,
SlotLabels,
SPACING,
StagingAreaFixture,
WasteChuteFixture,
WasteChuteStagingAreaFixture,
Expand Down Expand Up @@ -99,11 +100,14 @@ export function DeckThumbnail(props: DeckThumbnailProps): JSX.Element {
width="100%"
alignItems={ALIGN_CENTER}
justifyContent={JUSTIFY_CENTER}
backgroundColor={COLORS.grey10}
backgroundColor={
robotType === OT2_ROBOT_TYPE ? COLORS.white : COLORS.grey10
}
borderRadius={BORDERS.borderRadius8}
paddingY={SPACING.spacing24}
>
<RobotCoordinateSpaceWithRef
height="80%"
height="100%"
width="100%"
deckDef={deckDef}
viewBox={`${deckDef.cornerOffsetFromOrigin[0]} ${
Expand Down
Loading