diff --git a/components/src/organisms/Toolbox/index.tsx b/components/src/organisms/Toolbox/index.tsx
index 566bcf1e4bf..1a6cb435a9e 100644
--- a/components/src/organisms/Toolbox/index.tsx
+++ b/components/src/organisms/Toolbox/index.tsx
@@ -119,6 +119,7 @@ export function Toolbox(props: ToolboxProps): JSX.Element {
+
void
toggleValue: unknown
+ caption?: string
}
export function ToggleExpandStepFormField(
props: ToggleExpandStepFormFieldProps
@@ -34,9 +36,19 @@ export function ToggleExpandStepFormField(
units,
toggleUpdateValue,
toggleValue,
+ caption,
...restProps
} = props
+ const onToggleUpdateValue = (): void => {
+ if (typeof toggleValue === 'boolean') {
+ toggleUpdateValue(!toggleValue)
+ } else if (toggleValue === 'engage' || toggleValue === 'disengage') {
+ const newToggleValue = toggleValue === 'engage' ? 'disengage' : 'engage'
+ toggleUpdateValue(newToggleValue)
+ }
+ }
+
return (
{title}
{
- toggleUpdateValue(!toggleValue)
+ onToggleUpdateValue()
}}
label={isSelected ? onLabel : offLabel}
toggledOn={isSelected}
/>
- {isSelected ? (
-
- ) : null}
+
+ {isSelected ? (
+
+ ) : null}
+ {isSelected && caption != null ? (
+
+ {caption}
+
+ ) : null}
+
)
diff --git a/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/MagnetTools/index.tsx b/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/MagnetTools/index.tsx
index 660343de340..7f7afd9702a 100644
--- a/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/MagnetTools/index.tsx
+++ b/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/MagnetTools/index.tsx
@@ -1,3 +1,95 @@
-export function MagnetTools(): JSX.Element {
- return TODO: wire this up
+import { useSelector } from 'react-redux'
+import { useTranslation } from 'react-i18next'
+import {
+ COLORS,
+ DIRECTION_COLUMN,
+ Divider,
+ Flex,
+ ListItem,
+ SPACING,
+ StyledText,
+} from '@opentrons/components'
+import { MAGNETIC_MODULE_V1 } from '@opentrons/shared-data'
+import {
+ MAX_ENGAGE_HEIGHT_V1,
+ MAX_ENGAGE_HEIGHT_V2,
+ MIN_ENGAGE_HEIGHT_V1,
+ MIN_ENGAGE_HEIGHT_V2,
+} from '../../../../../../constants'
+import {
+ getMagnetLabwareEngageHeight,
+ getMagneticLabwareOptions,
+} from '../../../../../../ui/modules/selectors'
+import { ToggleExpandStepFormField } from '../../../../../../molecules'
+import { getModuleEntities } from '../../../../../../step-forms/selectors'
+
+import type { StepFormProps } from '../../types'
+
+export function MagnetTools(props: StepFormProps): JSX.Element {
+ const { propsForFields, formData } = props
+ const { t } = useTranslation(['application', 'form', 'protocol_steps'])
+ const moduleLabwareOptions = useSelector(getMagneticLabwareOptions)
+ const moduleEntities = useSelector(getModuleEntities)
+ const defaultEngageHeight = useSelector(getMagnetLabwareEngageHeight)
+ const moduleModel = moduleEntities[formData.moduleId].model
+
+ const mmUnits = t('units.millimeter')
+ const isGen1 = moduleModel === MAGNETIC_MODULE_V1
+ const engageHeightMinMax = isGen1
+ ? t('magnet_height_caption', {
+ low: MIN_ENGAGE_HEIGHT_V1,
+ high: MAX_ENGAGE_HEIGHT_V1,
+ })
+ : t('magnet_height_caption', {
+ low: `${MIN_ENGAGE_HEIGHT_V2} ${mmUnits}`,
+ high: `${MAX_ENGAGE_HEIGHT_V2} ${mmUnits}`,
+ })
+ const engageHeightDefault =
+ defaultEngageHeight != null
+ ? isGen1
+ ? t('magnet_recommended', { default: defaultEngageHeight })
+ : t('magnet_recommended', {
+ default: `${defaultEngageHeight} ${mmUnits}`,
+ })
+ : ''
+ const engageHeightCaption = `${engageHeightMinMax} ${engageHeightDefault}`
+
+ return (
+
+
+
+ {t('protocol_steps:module')}
+
+
+
+
+ {moduleLabwareOptions[0].name}
+
+
+
+
+
+
+
+
+
+ )
}
diff --git a/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/MoveLabwareTools/index.tsx b/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/MoveLabwareTools/index.tsx
index 1d654ad0cec..fa71de6a2b4 100644
--- a/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/MoveLabwareTools/index.tsx
+++ b/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/MoveLabwareTools/index.tsx
@@ -40,7 +40,6 @@ export function MoveLabwareTools(props: StepFormProps): JSX.Element {
}
/>
) : null}
-
{
+ const actualFields = await importOriginal()
+ return {
+ ...actualFields,
+ getMagnetLabwareEngageHeight: vi.fn(),
+ getMagneticLabwareOptions: vi.fn(),
+ }
+})
+const render = (props: ComponentProps) => {
+ return renderWithProviders(, {
+ i18nInstance: i18n,
+ })[0]
+}
+
+describe('MagnetTools', () => {
+ let props: React.ComponentProps
+
+ beforeEach(() => {
+ props = {
+ formData: {
+ id: 'magnet',
+ stepType: 'magnet',
+ moduleId: 'magnetId',
+ magnetAction: 'engage',
+ } as any,
+ focusHandlers: {
+ blur: vi.fn(),
+ focus: vi.fn(),
+ dirtyFields: [],
+ focusedField: null,
+ },
+ toolboxStep: 1,
+ propsForFields: {
+ magnetAction: {
+ onFieldFocus: vi.fn(),
+ onFieldBlur: vi.fn(),
+ errorToShow: null,
+ disabled: false,
+ name: 'magnetAction',
+ updateValue: vi.fn(),
+ value: 'engage',
+ },
+ engageHeight: {
+ onFieldFocus: vi.fn(),
+ onFieldBlur: vi.fn(),
+ errorToShow: null,
+ disabled: false,
+ name: 'engage height',
+ updateValue: vi.fn(),
+ value: 10,
+ },
+ },
+ }
+ vi.mocked(getMagneticLabwareOptions).mockReturnValue([
+ { name: 'mock name', value: 'mockValue' },
+ ])
+ vi.mocked(getModuleEntities).mockReturnValue({
+ magnetId: {
+ id: 'magnetId',
+ model: 'magneticModuleV2',
+ type: 'magneticModuleType',
+ },
+ })
+ vi.mocked(getMagnetLabwareEngageHeight).mockReturnValue(null)
+ })
+
+ it('renders the text and a switch button for v2', () => {
+ render(props)
+ screen.getByText('Module')
+ screen.getByText('mock name')
+ screen.getByText('Magnet action')
+ screen.getByLabelText('Engage')
+ const toggleButton = screen.getByRole('switch')
+ screen.getByText('Engage height')
+ screen.getByText('Must be between -2.5 mm to 25 mm.')
+
+ fireEvent.click(toggleButton)
+ expect(props.propsForFields.magnetAction.updateValue).toHaveBeenCalled()
+ })
+ it('renders the input text for v1', () => {
+ vi.mocked(getModuleEntities).mockReturnValue({
+ magnetId: {
+ id: 'magnetId',
+ model: 'magneticModuleV1',
+ type: 'magneticModuleType',
+ },
+ })
+ render(props)
+ screen.getByText('Must be between 0 to 45.')
+ })
+})