diff --git a/protocol-designer/src/assets/localization/en/form.json b/protocol-designer/src/assets/localization/en/form.json
index 98a1e328809..f6dcb7d5e37 100644
--- a/protocol-designer/src/assets/localization/en/form.json
+++ b/protocol-designer/src/assets/localization/en/form.json
@@ -23,7 +23,11 @@
"liquid_placement": {
"liquid": "Liquid",
"volume": "Volume",
- "volume_exceeded": "Warning: exceeded max volume per well: {{volume}}µL"
+ "errors": {
+ "liquid_required": "Define a liquid",
+ "volume_exceeded": "Warning: exceeded max volume per well: {{volume}}µL",
+ "volume_required": "Define a volume"
+ }
},
"pipette_mount_label": {
"left": "(L)",
diff --git a/protocol-designer/src/organisms/AssignLiquidsModal/LiquidCard.tsx b/protocol-designer/src/organisms/AssignLiquidsModal/LiquidCard.tsx
index 4f33b968db4..215e1575060 100644
--- a/protocol-designer/src/organisms/AssignLiquidsModal/LiquidCard.tsx
+++ b/protocol-designer/src/organisms/AssignLiquidsModal/LiquidCard.tsx
@@ -12,7 +12,7 @@ import {
Flex,
Icon,
LiquidIcon,
- ListItem,
+ ListButton,
SPACING,
StyledText,
TEXT_DECORATION_UNDERLINE,
@@ -98,7 +98,15 @@ export function LiquidCard(props: LiquidCardProps): JSX.Element {
}
return (
-
+ {
+ setIsExpanded(prev => !prev)
+ }}
+ padding="0"
+ >
- {
- setIsExpanded(prev => !prev)
- }}
- >
+
{isExpanded ? (
-
-
-
- {t('well')}
-
-
-
- {t('microliters')}
+ <>
+
+
+
+
+ {t('well')}
+
+
+ {t('microliters')}
+
+
-
-
- {info.liquidIndex != null
- ? fullWellsByLiquid[info.liquidIndex]
- .sort((a, b) =>
- orderedWells.indexOf(b) > orderedWells.indexOf(a) ? -1 : 1
- )
- .map((wellName, wellliquidIndex) => {
- const volume =
- wellContents != null
- ? wellContents[wellName].ingreds[liquidIndex].volume
- : 0
- return (
- <>
-
- {wellliquidIndex <
- fullWellsByLiquid[liquidIndex].length - 1 ? (
-
- ) : null}
- >
+
+ {info.liquidIndex != null
+ ? fullWellsByLiquid[info.liquidIndex]
+ .sort((a, b) =>
+ orderedWells.indexOf(b) > orderedWells.indexOf(a) ? -1 : 1
)
- })
- : null}
-
+ .map((wellName, wellliquidIndex) => {
+ const volume =
+ wellContents != null
+ ? wellContents[wellName].ingreds[liquidIndex].volume
+ : 0
+ return (
+ <>
+
+ {wellliquidIndex <
+ fullWellsByLiquid[liquidIndex].length - 1 ? (
+
+ ) : null}
+ >
+ )
+ })
+ : null}
+
+ >
) : null}
-
+
)
}
diff --git a/protocol-designer/src/organisms/AssignLiquidsModal/LiquidToolbox.tsx b/protocol-designer/src/organisms/AssignLiquidsModal/LiquidToolbox.tsx
index 269d78d5c05..5ec1618e72c 100644
--- a/protocol-designer/src/organisms/AssignLiquidsModal/LiquidToolbox.tsx
+++ b/protocol-designer/src/organisms/AssignLiquidsModal/LiquidToolbox.tsx
@@ -106,11 +106,12 @@ export function LiquidToolbox(props: LiquidToolboxProps): JSX.Element {
control,
setValue,
reset,
- formState: { touchedFields },
+ formState,
} = useForm({
defaultValues: getInitialValues(),
})
+ const { errors } = formState
const selectedLiquidId = watch('selectedLiquidId')
const volume = watch('volume')
@@ -184,15 +185,22 @@ export function LiquidToolbox(props: LiquidToolboxProps): JSX.Element {
reset()
}
- let volumeErrors: string | null = null
- if (Boolean(touchedFields.volume)) {
- if (volume == null || volume === '0') {
- volumeErrors = t('generic.error.more_than_zero')
- } else if (parseInt(volume) > selectedWellsMaxVolume) {
- volumeErrors = t('form:liquid_placement.volume_exceeded', {
+ const validateVolume = (
+ volume: string | null | undefined
+ ): string | undefined => {
+ if (volume == null || volume === '') {
+ return t('form:liquid_placement.errors.volume_required')
+ }
+ const volumeNumber = parseFloat(volume)
+ if (volumeNumber === 0) {
+ return t('form:generic.error.more_than_zero')
+ }
+ if (volumeNumber > selectedWellsMaxVolume) {
+ return t('form:liquid_placement.errors.volume_exceeded', {
volume: selectedWellsMaxVolume,
})
}
+ return undefined
}
let wellContents: ContentsByWell | null = null
@@ -301,7 +309,12 @@ export function LiquidToolbox(props: LiquidToolboxProps): JSX.Element {
name="selectedLiquidId"
control={control}
rules={{
- required: true,
+ required: {
+ value: true,
+ message: t(
+ 'form:liquid_placement.errors.liquid_required'
+ ),
+ },
}}
render={({ field }) => {
const fullOptions: DropdownOption[] = liquidSelectionOptions.map(
@@ -337,6 +350,7 @@ export function LiquidToolbox(props: LiquidToolboxProps): JSX.Element {
}}
onClick={field.onChange}
menuPlacement="bottom"
+ error={errors.selectedLiquidId?.message}
/>
)
}}
@@ -354,14 +368,14 @@ export function LiquidToolbox(props: LiquidToolboxProps): JSX.Element {
name="volume"
control={control}
rules={{
- required: true,
+ validate: validateVolume,
}}
render={({ field }) => (
@@ -377,18 +391,7 @@ export function LiquidToolbox(props: LiquidToolboxProps): JSX.Element {
{t('shared:cancel')}
-
- {t('save')}
-
+ {t('save')}