Skip to content

Commit 315a366

Browse files
authored
refactor(components, protocol-designer): update Toolbox implementations (#17050)
Refactors Toolbox and updates its implementations across PD app to more closely mirror designs. Importantly, sets DeckSetupTools implementation to absolute to accommodate full-screen zoom on selected slot/cutout.
1 parent f75132e commit 315a366

File tree

10 files changed

+85
-47
lines changed

10 files changed

+85
-47
lines changed

components/src/organisms/Toolbox/index.tsx

Lines changed: 11 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,31 +5,27 @@ import {
55
DIRECTION_COLUMN,
66
JUSTIFY_SPACE_BETWEEN,
77
NO_WRAP,
8-
POSITION_FIXED,
8+
POSITION_RELATIVE,
99
} from '../../styles'
1010
import { BORDERS, COLORS } from '../../helix-design-system'
1111
import { SPACING } from '../../ui-style-constants'
1212
import { PrimaryButton } from '../../atoms'
1313
import { textDecorationUnderline } from '../../ui-style-constants/typography'
14+
import type { StyleProps } from '../../primitives'
1415

15-
export interface ToolboxProps {
16+
export interface ToolboxProps extends StyleProps {
1617
title: JSX.Element
1718
children: React.ReactNode
1819
disableCloseButton?: boolean
19-
width?: string
20-
height?: string
2120
confirmButtonText?: string
2221
onConfirmClick?: () => void
2322
confirmButton?: JSX.Element
2423
onCloseClick?: () => void
2524
closeButton?: JSX.Element
26-
side?: 'left' | 'right'
27-
horizontalSide?: 'top' | 'bottom'
2825
titlePadding?: string
2926
childrenPadding?: string
3027
subHeader?: JSX.Element | null
3128
secondaryHeaderButton?: JSX.Element
32-
position?: string
3329
}
3430

3531
export function Toolbox(props: ToolboxProps): JSX.Element {
@@ -43,14 +39,13 @@ export function Toolbox(props: ToolboxProps): JSX.Element {
4339
height = '100%',
4440
disableCloseButton = false,
4541
width = '19.5rem',
46-
side = 'right',
47-
horizontalSide = 'bottom',
4842
confirmButton,
4943
titlePadding = SPACING.spacing16,
5044
childrenPadding = SPACING.spacing16,
5145
subHeader,
5246
secondaryHeaderButton,
53-
position = POSITION_FIXED,
47+
position = POSITION_RELATIVE,
48+
...styleProps
5449
} = props
5550

5651
const slideOutRef = useRef<HTMLDivElement>(null)
@@ -69,26 +64,17 @@ export function Toolbox(props: ToolboxProps): JSX.Element {
6964
handleScroll()
7065
}, [slideOutRef])
7166

72-
const positionStyles =
73-
position === POSITION_FIXED
74-
? {
75-
...(side === 'right' && { right: '0' }),
76-
...(side === 'left' && { left: '0' }),
77-
...(horizontalSide === 'bottom' && { bottom: '0' }),
78-
...(horizontalSide === 'top' && { top: '5rem' }),
79-
zIndex: 10,
80-
}
81-
: {}
8267
return (
8368
<Flex
8469
cursor="auto"
8570
backgroundColor={COLORS.white}
8671
boxShadow="0px 3px 6px rgba(0, 0, 0, 0.23)"
8772
height={height}
88-
{...positionStyles}
89-
borderRadius={BORDERS.borderRadius8}
9073
width={width}
74+
position={position}
75+
borderRadius={BORDERS.borderRadius8}
9176
flex="0"
77+
{...styleProps}
9278
>
9379
<Flex
9480
width={width}
@@ -101,15 +87,15 @@ export function Toolbox(props: ToolboxProps): JSX.Element {
10187
flexDirection={DIRECTION_COLUMN}
10288
borderBottom={`1px solid ${COLORS.grey30}`}
10389
>
104-
{subHeader != null ? subHeader : null}
90+
{subHeader ?? null}
10591
<Flex
10692
justifyContent={JUSTIFY_SPACE_BETWEEN}
10793
alignItems={ALIGN_CENTER}
10894
gridGap={SPACING.spacing12}
10995
>
11096
{title}
11197
<Flex gridGap={SPACING.spacing4}>
112-
{secondaryHeaderButton != null ? secondaryHeaderButton : null}
98+
{secondaryHeaderButton ?? null}
11399
{onCloseClick != null && closeButton != null ? (
114100
<Btn
115101
disabled={disableCloseButton}
@@ -151,7 +137,7 @@ export function Toolbox(props: ToolboxProps): JSX.Element {
151137
{confirmButtonText}
152138
</PrimaryButton>
153139
) : null}
154-
{confirmButton != null ? confirmButton : null}
140+
{confirmButton ?? null}
155141
</Box>
156142
) : null}
157143
</Flex>

protocol-designer/src/organisms/AssignLiquidsModal/LiquidToolbox.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ export function LiquidToolbox(props: LiquidToolboxProps): JSX.Element {
239239
onClose()
240240
}}
241241
onCloseClick={handleClearSelectedWells}
242-
height="calc(100vh - 64px)"
242+
height="100%"
243243
closeButton={
244244
<StyledText desktopStyle="bodyDefaultRegular">
245245
{t('clear_wells')}

protocol-designer/src/organisms/AssignLiquidsModal/index.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import { getSelectedWells } from '../../well-selection/selectors'
2121
import { SelectableLabware } from '../Labware/SelectableLabware'
2222
import { wellFillFromWellContents } from '../LabwareOnDeck/utils'
2323
import { deselectWells, selectWells } from '../../well-selection/actions'
24+
import { PROTOCOL_NAV_BAR_HEIGHT_REM } from '../ProtocolNavBar'
2425
import { LiquidToolbox } from './LiquidToolbox'
2526

2627
import type { WellGroup } from '@opentrons/components'
@@ -51,18 +52,19 @@ export function AssignLiquidsModal(): JSX.Element | null {
5152

5253
return (
5354
<Flex
55+
height={`calc(100vh - ${PROTOCOL_NAV_BAR_HEIGHT_REM}rem)`}
5456
justifyContent={JUSTIFY_SPACE_BETWEEN}
5557
backgroundColor={COLORS.grey10}
58+
padding={SPACING.spacing12}
59+
gridGap={SPACING.spacing12}
5660
>
5761
<Flex
62+
width="100%"
5863
justifyContent={JUSTIFY_CENTER}
59-
width="80%"
6064
alignItems={ALIGN_CENTER}
61-
height="calc(100vh - 64px)"
6265
>
6366
<Box
64-
width="80vh"
65-
height="max-content"
67+
width="50vw"
6668
padding={SPACING.spacing60}
6769
backgroundColor={COLORS.white}
6870
borderRadius={BORDERS.borderRadius12}

protocol-designer/src/organisms/ProtocolNavBar/index.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ import { LiquidButton } from './LiquidButton'
2424

2525
import type { StyleProps, TabProps } from '@opentrons/components'
2626

27+
export const PROTOCOL_NAV_BAR_HEIGHT_REM = 4
28+
2729
interface ProtocolNavBarProps {
2830
hasZoomInSlot?: boolean
2931
tabs?: TabProps[]
@@ -98,6 +100,7 @@ export function ProtocolNavBar({
98100
const NavContainer = styled(Flex)<{ showShadow: boolean }>`
99101
z-index: ${props => (props.showShadow === true ? 11 : 0)};
100102
padding: ${SPACING.spacing12};
103+
height: ${PROTOCOL_NAV_BAR_HEIGHT_REM}rem;
101104
width: 100%;
102105
justify-content: ${JUSTIFY_SPACE_BETWEEN};
103106
align-items: ${ALIGN_CENTER};

protocol-designer/src/pages/Designer/DeckSetup/DeckSetupContainer.tsx

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { useMemo, useState, Fragment } from 'react'
22
import { useDispatch, useSelector } from 'react-redux'
3+
import round from 'lodash/round'
34
import {
45
ALIGN_CENTER,
56
BORDERS,
@@ -35,13 +36,13 @@ import { SlotDetailsContainer } from '../../../organisms'
3536
import { selectZoomedIntoSlot } from '../../../labware-ingred/actions'
3637
import { selectors } from '../../../labware-ingred/selectors'
3738
import { DeckSetupDetails } from './DeckSetupDetails'
39+
import { DECK_SETUP_TOOLS_WIDTH_REM, DeckSetupTools } from './DeckSetupTools'
3840
import {
3941
animateZoom,
4042
getCutoutIdForAddressableArea,
4143
useDeckSetupWindowBreakPoint,
4244
zoomInOnCoordinate,
4345
} from './utils'
44-
import { DeckSetupTools } from './DeckSetupTools'
4546

4647
import type { StagingAreaLocation, TrashCutoutId } from '@opentrons/components'
4748
import type {
@@ -122,19 +123,37 @@ export function DeckSetupContainer(props: DeckSetupTabType): JSX.Element {
122123
const hasWasteChute =
123124
wasteChuteFixtures.length > 0 || wasteChuteStagingAreaFixtures.length > 0
124125

126+
const windowInnerWidthRem = window.innerWidth / 16
127+
const deckMapRatio = round(
128+
(windowInnerWidthRem - DECK_SETUP_TOOLS_WIDTH_REM) / windowInnerWidthRem,
129+
2
130+
)
131+
125132
const viewBoxX = deckDef.cornerOffsetFromOrigin[0]
126133
const viewBoxY = hasWasteChute
127134
? deckDef.cornerOffsetFromOrigin[1] -
128135
WASTE_CHUTE_SPACE -
129136
DETAILS_HOVER_SPACE
130137
: deckDef.cornerOffsetFromOrigin[1]
131-
const viewBoxWidth = deckDef.dimensions[0]
138+
const viewBoxWidth = deckDef.dimensions[0] / deckMapRatio
132139
const viewBoxHeight = deckDef.dimensions[1] + DETAILS_HOVER_SPACE
133140

134141
const initialViewBox = `${viewBoxX} ${viewBoxY} ${viewBoxWidth} ${viewBoxHeight}`
135142

136143
const [viewBox, setViewBox] = useState<string>(initialViewBox)
137144

145+
const isZoomed = Object.values(zoomIn).some(val => val != null)
146+
const viewBoxNumerical = viewBox?.split(' ').map(val => Number(val)) ?? []
147+
const viewBoxAdjustedNumerical = [
148+
...viewBoxNumerical.slice(0, 2),
149+
(viewBoxNumerical[2] - viewBoxNumerical[0]) / deckMapRatio +
150+
viewBoxNumerical[0],
151+
viewBoxNumerical[3],
152+
]
153+
const viewBoxAdjusted = viewBoxAdjustedNumerical.reduce((acc, num, i) => {
154+
return i < viewBoxNumerical.length - 1 ? acc + `${num} ` : acc + `${num}`
155+
}, '')
156+
138157
const [hoveredLabware, setHoveredLabware] = useState<string | null>(null)
139158
const [hoveredModule, setHoveredModule] = useState<ModuleModel | null>(null)
140159
const [hoveredFixture, setHoveredFixture] = useState<Fixture | null>(null)
@@ -202,7 +221,7 @@ export function DeckSetupContainer(props: DeckSetupTabType): JSX.Element {
202221
width="100%"
203222
height={tab === 'protocolSteps' ? '65.75vh' : '100%'}
204223
flexDirection={DIRECTION_COLUMN}
205-
padding={SPACING.spacing24}
224+
padding={isZoomed ? '0' : SPACING.spacing24}
206225
>
207226
<Flex
208227
width="100%"
@@ -227,7 +246,7 @@ export function DeckSetupContainer(props: DeckSetupTabType): JSX.Element {
227246
}
228247
minWidth={tab === 'protocolSteps' ? 'auto' : '30rem'}
229248
deckDef={deckDef}
230-
viewBox={viewBox}
249+
viewBox={viewBoxAdjusted}
231250
outline="auto"
232251
zoomed={zoomIn.slot != null}
233252
borderRadius={BORDERS.borderRadius12}

protocol-designer/src/pages/Designer/DeckSetup/DeckSetupTools.tsx

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
Flex,
1010
Icon,
1111
ModuleIcon,
12+
POSITION_FIXED,
1213
RadioButton,
1314
SPACING,
1415
StyledText,
@@ -51,7 +52,10 @@ import { selectors } from '../../../labware-ingred/selectors'
5152
import { useKitchen } from '../../../organisms/Kitchen/hooks'
5253
import { getDismissedHints } from '../../../tutorial/selectors'
5354
import { createContainerAboveModule } from '../../../step-forms/actions/thunks'
54-
import { ConfirmDeleteStagingAreaModal } from '../../../organisms'
55+
import {
56+
ConfirmDeleteStagingAreaModal,
57+
PROTOCOL_NAV_BAR_HEIGHT_REM,
58+
} from '../../../organisms'
5559
import { BUTTON_LINK_STYLE } from '../../../atoms'
5660
import { getSlotInformation } from '../utils'
5761
import { ALL_ORDERED_CATEGORIES, FIXTURES, MOAM_MODELS } from './constants'
@@ -70,12 +74,19 @@ interface DeckSetupToolsProps {
7074
setHoveredModule: (model: ModuleModel | null) => void
7175
setHoveredFixture: (fixture: Fixture | null) => void
7276
} | null
77+
position?: string
7378
}
7479

7580
export type CategoryExpand = Record<string, boolean>
81+
export const DECK_SETUP_TOOLS_WIDTH_REM = 21.875
7682

7783
export function DeckSetupTools(props: DeckSetupToolsProps): JSX.Element | null {
78-
const { onCloseClick, setHoveredLabware, onDeckProps } = props
84+
const {
85+
onCloseClick,
86+
setHoveredLabware,
87+
onDeckProps,
88+
position = POSITION_FIXED,
89+
} = props
7990
const { t, i18n } = useTranslation(['starting_deck_state', 'shared'])
8091
const { makeSnackbar } = useKitchen()
8192
const selectedSlotInfo = useSelector(selectors.getZoomedInSlotInfo)
@@ -329,10 +340,7 @@ export function DeckSetupTools(props: DeckSetupToolsProps): JSX.Element | null {
329340
dispatch(
330341
createContainer({
331342
slot,
332-
labwareDefURI:
333-
selectedNestedLabwareDefUri == null
334-
? selectedLabwareDefUri
335-
: selectedNestedLabwareDefUri,
343+
labwareDefURI: selectedNestedLabwareDefUri ?? selectedLabwareDefUri,
336344
adapterUnderLabwareDefURI:
337345
selectedNestedLabwareDefUri == null
338346
? undefined
@@ -358,6 +366,13 @@ export function DeckSetupTools(props: DeckSetupToolsProps): JSX.Element | null {
358366
dispatch(selectZoomedIntoSlot({ slot: null, cutout: null }))
359367
onCloseClick()
360368
}
369+
const positionStyles =
370+
position === POSITION_FIXED
371+
? {
372+
right: SPACING.spacing12,
373+
top: `calc(${PROTOCOL_NAV_BAR_HEIGHT_REM}rem + ${SPACING.spacing12})`,
374+
}
375+
: {}
361376
return (
362377
<>
363378
{showDeleteLabwareModal != null ? (
@@ -382,8 +397,10 @@ export function DeckSetupTools(props: DeckSetupToolsProps): JSX.Element | null {
382397
) : null}
383398
{changeModuleWarning}
384399
<Toolbox
385-
height="calc(100vh - 64px)"
386-
width="23.375rem"
400+
height={`calc(100vh - ${PROTOCOL_NAV_BAR_HEIGHT_REM}rem - 2 * ${SPACING.spacing12})`}
401+
width={`${DECK_SETUP_TOOLS_WIDTH_REM}rem`}
402+
position={position}
403+
{...positionStyles}
387404
title={
388405
<Flex gridGap={SPACING.spacing8} alignItems={ALIGN_CENTER}>
389406
<DeckInfoLabel

protocol-designer/src/pages/Designer/Offdeck/OffDeckDetails.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ export function OffDeckDetails(props: OffDeckDetailsProps): JSX.Element {
6262
<Flex
6363
backgroundColor={COLORS.white}
6464
borderRadius={BORDERS.borderRadius8}
65-
width={containerWidth}
65+
width="100%"
6666
height="65vh"
6767
padding={padding}
6868
gridGap={SPACING.spacing24}
@@ -85,6 +85,7 @@ export function OffDeckDetails(props: OffDeckDetailsProps): JSX.Element {
8585
backgroundColor={COLORS.grey20}
8686
overflowY={OVERFLOW_AUTO}
8787
flexDirection={DIRECTION_COLUMN}
88+
flex="0 0 auto"
8889
>
8990
<Flex
9091
justifyContent={JUSTIFY_CENTER}

protocol-designer/src/pages/Designer/Offdeck/Offdeck.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
Flex,
1111
JUSTIFY_CENTER,
1212
LabwareRender,
13+
POSITION_RELATIVE,
1314
RobotCoordsForeignDiv,
1415
RobotWorkSpace,
1516
SPACING,
@@ -112,7 +113,12 @@ export function OffDeck(props: DeckSetupTabType): JSX.Element {
112113
return (
113114
<Flex width="100%">
114115
{selectedSlot.slot === 'offDeck' ? (
115-
<Flex alignItems={ALIGN_CENTER} width="100%">
116+
<Flex
117+
alignItems={ALIGN_CENTER}
118+
width="100%"
119+
padding={SPACING.spacing12}
120+
gridGap={SPACING.spacing12}
121+
>
116122
<Flex justifyContent={JUSTIFY_CENTER} width="100%">
117123
<Flex
118124
width="39.4275rem"
@@ -150,6 +156,7 @@ export function OffDeck(props: DeckSetupTabType): JSX.Element {
150156
</Flex>
151157
</Flex>
152158
<DeckSetupTools
159+
position={POSITION_RELATIVE}
153160
onDeckProps={null}
154161
setHoveredLabware={setHoveredLabware}
155162
onCloseClick={() => {

protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepFormToolbox.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import {
1717
TYPOGRAPHY,
1818
} from '@opentrons/components'
1919
import { stepIconsByType } from '../../../../form-types'
20-
import { FormAlerts } from '../../../../organisms'
20+
import { FormAlerts, PROTOCOL_NAV_BAR_HEIGHT_REM } from '../../../../organisms'
2121
import { useKitchen } from '../../../../organisms/Kitchen/hooks'
2222
import { RenameStepModal } from '../../../../organisms/RenameStepModal'
2323
import { getFormWarningsForSelectedStep } from '../../../../dismiss/selectors'
@@ -272,7 +272,8 @@ export function StepFormToolbox(props: StepFormToolboxProps): JSX.Element {
272272
/>
273273
) : null}
274274
<Toolbox
275-
height="calc(100vh - 6rem)"
275+
height="100%"
276+
maxHeight={`calc(100vh - ${PROTOCOL_NAV_BAR_HEIGHT_REM}rem - 2 * ${SPACING.spacing12})`}
276277
position={POSITION_RELATIVE}
277278
subHeader={
278279
isMultiStepToolbox ? (

0 commit comments

Comments
 (0)