Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
"default_labware_offset": "Default Labware Offset",
"default_location_offset_added": "Default location offset added",
"default_location_offset_adjusted": "Default location offset adjusted",
"default_offset_description": "The default offset is used for all placements of the labware unless a manual adjustment is made to specific slot location.",
"detach_probe": "Remove calibration probe",
"ensure_nozzle_position_desktop": "<block>Ensure that the {{tip_type}} is centered above and level with {{item_location}}. If it isn't, use the controls below or your keyboard to jog the pipette until it is properly aligned.</block>",
"ensure_nozzle_position_odd": "<block>Ensure that the {{tip_type}} is centered above and level with {{item_location}}. If it isn't, tap <bold>Move pipette</bold> and then jog the pipette until it is properly aligned.</block>",
Expand Down
22 changes: 20 additions & 2 deletions app/src/molecules/MultiDeckLabelTagBtns/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
ALIGN_CENTER,
BORDERS,
Btn,
COLORS,
CURSOR_DEFAULT,
DIRECTION_COLUMN,
DIRECTION_ROW,
DISPLAY_GRID,
Expand Down Expand Up @@ -69,15 +71,26 @@
{...colThreeSecondaryBtn}
/>
<Btn css={DESKTOP_ONLY_BUTTON} {...colThreeSecondaryBtn}>
<StyledText desktopStyle="captionSemiBold">
<StyledText
desktopStyle="captionSemiBold"

Check warning on line 75 in app/src/molecules/MultiDeckLabelTagBtns/index.tsx

View check run for this annotation

Codecov / codecov/patch

app/src/molecules/MultiDeckLabelTagBtns/index.tsx#L74-L75

Added lines #L74 - L75 were not covered by tests
css={
colThreeSecondaryBtn.ariaDisabled
? DESKTOP_SECONDARY_ARIA_DISABLED
: undefined

Check warning on line 79 in app/src/molecules/MultiDeckLabelTagBtns/index.tsx

View check run for this annotation

Codecov / codecov/patch

app/src/molecules/MultiDeckLabelTagBtns/index.tsx#L77-L79

Added lines #L77 - L79 were not covered by tests
}
>
{colThreeSecondaryBtn.buttonText}
</StyledText>
</Btn>
</>
)}
<>
<SmallButton {...colThreePrimaryBtn} css={ODD_ONLY_BUTTON} />
<SecondaryButton {...colThreePrimaryBtn} css={DESKTOP_ONLY_BUTTON}>
<SecondaryButton
{...colThreePrimaryBtn}
css={DESKTOP_ONLY_BUTTON}
aria-disabled={colThreePrimaryBtn.ariaDisabled}

Check warning on line 92 in app/src/molecules/MultiDeckLabelTagBtns/index.tsx

View check run for this annotation

Codecov / codecov/patch

app/src/molecules/MultiDeckLabelTagBtns/index.tsx#L89-L92

Added lines #L89 - L92 were not covered by tests
>
<StyledText desktopStyle="captionSemiBold">
{colThreePrimaryBtn.buttonText}
</StyledText>
Expand Down Expand Up @@ -182,3 +195,8 @@
display: none;
}
`

const DESKTOP_SECONDARY_ARIA_DISABLED = css`
color: ${COLORS.grey40};
cursor: ${CURSOR_DEFAULT};
`

Check warning on line 202 in app/src/molecules/MultiDeckLabelTagBtns/index.tsx

View check run for this annotation

Codecov / codecov/patch

app/src/molecules/MultiDeckLabelTagBtns/index.tsx#L199-L202

Added lines #L199 - L202 were not covered by tests
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,7 @@
const { data: lwOffsetsData } = useNotifySearchLabwareOffsets(
searchLwOffsetsParams,
{
enabled:
searchLwOffsetsParams.filters.length > 0 &&
robotType === FLEX_ROBOT_TYPE &&
runStatus === RUN_STATUS_IDLE,
enabled: runStatus === RUN_STATUS_IDLE && robotType === FLEX_ROBOT_TYPE,

Check warning on line 71 in app/src/organisms/LabwarePositionCheck/LPCFlows/hooks/useLPCLabwareInfo/index.ts

View check run for this annotation

Codecov / codecov/patch

app/src/organisms/LabwarePositionCheck/LPCFlows/hooks/useLPCLabwareInfo/index.ts#L71

Added line #L71 was not covered by tests
refetchInterval: REFETCH_OFFSET_SEARCH_MS,
}
)
Expand Down
8 changes: 7 additions & 1 deletion app/src/organisms/LabwarePositionCheck/LPCWizardFlex.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@
import { LPCRobotInMotion } from './LPCRobotInMotion'
import { LPCFatalError } from './LPCFatalError'
import { LPCProbeNotAttached } from './LPCProbeNotAttached'
import { useLPCCommands } from '/app/organisms/LabwarePositionCheck/hooks'
import {
useInfoBanners,
useLPCCommands,
} from '/app/organisms/LabwarePositionCheck/hooks'
import {
closeLPC,
proceedStep as proceedStepDispatch,
Expand Down Expand Up @@ -40,6 +43,7 @@
const LPCHandlerUtils = useLPCCommands({
...props,
})
const bannerUtils = useInfoBanners()

Check warning on line 46 in app/src/organisms/LabwarePositionCheck/LPCWizardFlex.tsx

View check run for this annotation

Codecov / codecov/patch

app/src/organisms/LabwarePositionCheck/LPCWizardFlex.tsx#L46

Added line #L46 was not covered by tests

// Clean up state on LPC close.
useEffect(() => {
Expand All @@ -53,6 +57,7 @@
LPCHandlerUtils,
proceedStep,
goBackLastStep,
bannerUtils,

Check warning on line 60 in app/src/organisms/LabwarePositionCheck/LPCWizardFlex.tsx

View check run for this annotation

Codecov / codecov/patch

app/src/organisms/LabwarePositionCheck/LPCWizardFlex.tsx#L60

Added line #L60 was not covered by tests
})

return (
Expand All @@ -61,6 +66,7 @@
proceedStep={proceedStep}
goBackLastStep={goBackLastStep}
commandUtils={{ ...LPCHandlerUtils, headerCommands }}
bannerUtils={bannerUtils}

Check warning on line 69 in app/src/organisms/LabwarePositionCheck/LPCWizardFlex.tsx

View check run for this annotation

Codecov / codecov/patch

app/src/organisms/LabwarePositionCheck/LPCWizardFlex.tsx#L69

Added line #L69 was not covered by tests
/>
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,7 @@
commandUtils: {} as any,
proceedStep: vi.fn(),
goBackLastStep: vi.fn(),
bannerUtils: {
defaultOffsetInfoBanner: { toggleBanner: vi.fn(), showBanner: false },
},

Check warning on line 12 in app/src/organisms/LabwarePositionCheck/__fixtures__/mockLPCContentProps.ts

View check run for this annotation

Codecov / codecov/patch

app/src/organisms/LabwarePositionCheck/__fixtures__/mockLPCContentProps.ts#L10-L12

Added lines #L10 - L12 were not covered by tests
}
1 change: 1 addition & 0 deletions app/src/organisms/LabwarePositionCheck/hooks/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from './useLPCCommands'
export * from './useLPCSnackbars'
export * from './useInfoBanners'

Check warning on line 3 in app/src/organisms/LabwarePositionCheck/hooks/index.ts

View check run for this annotation

Codecov / codecov/patch

app/src/organisms/LabwarePositionCheck/hooks/index.ts#L3

Added line #L3 was not covered by tests
31 changes: 31 additions & 0 deletions app/src/organisms/LabwarePositionCheck/hooks/useInfoBanners.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { useState } from 'react'

Check warning on line 1 in app/src/organisms/LabwarePositionCheck/hooks/useInfoBanners.ts

View check run for this annotation

Codecov / codecov/patch

app/src/organisms/LabwarePositionCheck/hooks/useInfoBanners.ts#L1

Added line #L1 was not covered by tests

interface BannerProps {
showBanner: boolean
toggleBanner: () => void
}

export interface UseInfoBannersResult {
defaultOffsetInfoBanner: BannerProps
}

// TODO(jh, 03-28-25): This could live in redux.

// Holds state & functionality for managing banners that require persistent state for this LPC session only.
export function useInfoBanners(): UseInfoBannersResult {
const [
showDefaultOffsetInfoBanner,
setShowDefaultOffsetInfoBanner,
] = useState(true)

Check warning on line 19 in app/src/organisms/LabwarePositionCheck/hooks/useInfoBanners.ts

View check run for this annotation

Codecov / codecov/patch

app/src/organisms/LabwarePositionCheck/hooks/useInfoBanners.ts#L15-L19

Added lines #L15 - L19 were not covered by tests

const toggleDefaultOffsetInfoBanner = (): void => {
setShowDefaultOffsetInfoBanner(!showDefaultOffsetInfoBanner)
}

Check warning on line 23 in app/src/organisms/LabwarePositionCheck/hooks/useInfoBanners.ts

View check run for this annotation

Codecov / codecov/patch

app/src/organisms/LabwarePositionCheck/hooks/useInfoBanners.ts#L21-L23

Added lines #L21 - L23 were not covered by tests

return {
defaultOffsetInfoBanner: {
toggleBanner: toggleDefaultOffsetInfoBanner,
showBanner: showDefaultOffsetInfoBanner,
},
}
}

Check warning on line 31 in app/src/organisms/LabwarePositionCheck/hooks/useInfoBanners.ts

View check run for this annotation

Codecov / codecov/patch

app/src/organisms/LabwarePositionCheck/hooks/useInfoBanners.ts#L25-L31

Added lines #L25 - L31 were not covered by tests
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ describe('useLPCHeaderCommands', () => {
proceedStep: mockProceedStep,
goBackLastStep: vi.fn(),
runId: mockRunId,
bannerUtils: {
defaultOffsetInfoBanner: { showBanner: false, toggleBanner: vi.fn() },
},
}

store = createStore(vi.fn(), {})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,18 +107,26 @@ describe('LPCLabwareDetails', () => {
let props: ComponentProps<typeof LPCLabwareDetails>
let mockDispatch: Mock
let mockSaveWorkingOffsets: Mock
let mockToggleInfoBanner: Mock

beforeEach(() => {
mockDispatch = vi.fn()
vi.mocked(useDispatch).mockReturnValue(mockDispatch)
mockSaveWorkingOffsets = vi.fn(() => Promise.resolve('mock-data'))
mockToggleInfoBanner = vi.fn()

props = {
...mockLPCContentProps,
commandUtils: {
saveWorkingOffsets: mockSaveWorkingOffsets,
isSavingWorkingOffsetsLoading: false,
} as any,
bannerUtils: {
defaultOffsetInfoBanner: {
toggleBanner: mockToggleInfoBanner,
showBanner: false,
},
},
}

vi.mocked(getIsOnDevice).mockReturnValue(false)
Expand Down Expand Up @@ -213,4 +221,24 @@ describe('LPCLabwareDetails', () => {
'Hardcoded offsets must be changed in your Python protocol'
)
})

it('should render the info banner when show banner is true and allow for the user to dismiss it', () => {
vi.mocked(getIsOnDevice).mockReturnValue(true)

render({
...props,
bannerUtils: {
defaultOffsetInfoBanner: {
toggleBanner: mockToggleInfoBanner,
showBanner: true,
},
},
})

const notification = screen.getByTestId('inline-notification')
expect(notification).toBeInTheDocument()
expect(notification.getAttribute('data-heading')).toBe(
'The default offset is used for all placements of the labware unless a manual adjustment is made to specific slot location.'
)
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,11 @@

function LPCLabwareDetailsContent(props: LPCWizardContentProps): JSX.Element {
const { t } = useTranslation('labware_position_check')
const { runId } = props
const { runId, bannerUtils } = props
const {
showBanner: showInfoBanner,
toggleBanner: toggleInfoBanner,
} = bannerUtils.defaultOffsetInfoBanner

Check warning on line 108 in app/src/organisms/LabwarePositionCheck/steps/HandleLabware/LPCLabwareDetails/index.tsx

View check run for this annotation

Codecov / codecov/patch

app/src/organisms/LabwarePositionCheck/steps/HandleLabware/LPCLabwareDetails/index.tsx#L104-L108

Added lines #L104 - L108 were not covered by tests

const selectedLwInfo = useSelector(selectSelectedLwOverview(runId))
const isOnDevice = useSelector(getIsOnDevice)
Expand Down Expand Up @@ -150,6 +154,13 @@
}
/>
)}
{showInfoBanner && (
<InlineNotification
type="neutral"
heading={t('default_offset_description')}
onCloseClick={toggleInfoBanner}

Check warning on line 161 in app/src/organisms/LabwarePositionCheck/steps/HandleLabware/LPCLabwareDetails/index.tsx

View check run for this annotation

Codecov / codecov/patch

app/src/organisms/LabwarePositionCheck/steps/HandleLabware/LPCLabwareDetails/index.tsx#L157-L161

Added lines #L157 - L161 were not covered by tests
/>
)}
<DefaultLocationOffset {...props} />
<LocationSpecificOffsetsContainer {...props} />
{/* Accommodate scrolling on the ODD. */}
Expand Down
6 changes: 5 additions & 1 deletion app/src/organisms/LabwarePositionCheck/types/content.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import type { UseLPCCommandsResult } from '/app/organisms/LabwarePositionCheck/hooks'
import type {
UseInfoBannersResult,
UseLPCCommandsResult,
} from '/app/organisms/LabwarePositionCheck/hooks'
import type { LPCWizardFlexProps } from '/app/organisms/LabwarePositionCheck/LPCWizardFlex'
import type { LPCStep } from '/app/redux/protocol-runs'
import type { UseLPCHeaderCommandsResult } from '/app/organisms/LabwarePositionCheck/hooks/useLPCCommands/useLPCHeaderCommands'
Expand All @@ -9,4 +12,5 @@ export type LPCWizardContentProps = Pick<LPCWizardFlexProps, 'runId'> & {
commandUtils: UseLPCCommandsResult & {
headerCommands: UseLPCHeaderCommandsResult
}
bannerUtils: UseInfoBannersResult
}
58 changes: 42 additions & 16 deletions components/src/atoms/buttons/SecondaryButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,24 @@ import type { StyleProps } from '../../index'
interface SecondaryButtonProps extends StyleProps {
/** button action is dangerous and may have non-reversible side-effects for user */
isDangerous?: boolean
'aria-disabled'?: boolean
}
export const SecondaryButton = styled.button.withConfig<SecondaryButtonProps>({
shouldForwardProp: p => isntStyleProp(p) && p !== 'isDangerous',
shouldForwardProp: p =>
isntStyleProp(p) && p !== 'isDangerous' && p !== 'aria-disabled',
})<SecondaryButtonProps>`
appearance: none;
cursor: ${CURSOR_POINTER};
color: ${props => (props.isDangerous ? COLORS.red50 : COLORS.blue50)};
cursor: ${props =>
props['aria-disabled'] ? CURSOR_DEFAULT : CURSOR_POINTER};
color: ${props => {
if (props['aria-disabled']) return COLORS.grey40
return props.isDangerous ? COLORS.red50 : COLORS.blue50
}};
border: ${BORDERS.lineBorder};
border-color: ${props => (props.isDangerous ? COLORS.red50 : 'initial')};
border-color: ${props => {
if (props['aria-disabled']) return COLORS.grey30
return props.isDangerous ? COLORS.red50 : 'initial'
}};
border-radius: ${BORDERS.borderRadius8};
padding: ${SPACING.spacing8} ${SPACING.spacing16};
text-transform: ${TYPOGRAPHY.textTransformNone};
Expand All @@ -26,28 +35,45 @@ export const SecondaryButton = styled.button.withConfig<SecondaryButtonProps>({

&:hover,
&:focus {
box-shadow: 0px 3px 6px 0px rgba(0, 0, 0, 0.23);
box-shadow: ${props =>
props['aria-disabled'] ? 'none' : '0px 3px 6px 0px rgba(0, 0, 0, 0.23)'};
}

&:hover {
color: ${props => (props.isDangerous ? COLORS.red50 : COLORS.blue60)};
border-color: ${props =>
props.isDangerous ? COLORS.red50 : COLORS.blue55};
box-shadow: 0 0 0;
color: ${props => {
if (props['aria-disabled']) return COLORS.grey40
return props.isDangerous ? COLORS.red50 : COLORS.blue60
}};
border-color: ${props => {
if (props['aria-disabled']) return COLORS.grey30
return props.isDangerous ? COLORS.red50 : COLORS.blue55
}};
box-shadow: ${props => (props['aria-disabled'] ? 'none' : '0 0 0')};
}

&:focus-visible {
color: ${props => (props.isDangerous ? COLORS.red60 : COLORS.blue60)};
border-color: ${props =>
props.isDangerous ? COLORS.red50 : COLORS.blue60};
box-shadow: 0 0 0 3px ${COLORS.yellow50};
color: ${props => {
if (props['aria-disabled']) return COLORS.grey40
return props.isDangerous ? COLORS.red60 : COLORS.blue60
}};
border-color: ${props => {
if (props['aria-disabled']) return COLORS.grey30
return props.isDangerous ? COLORS.red50 : COLORS.blue60
}};
box-shadow: ${props =>
props['aria-disabled'] ? 'none' : `0 0 0 3px ${COLORS.yellow50}`};
}

&:active {
box-shadow: none;
color: ${props => (props.isDangerous ? COLORS.red60 : COLORS.blue55)};
border-color: ${props =>
props.isDangerous ? COLORS.red60 : COLORS.blue55};
color: ${props => {
if (props['aria-disabled']) return COLORS.grey40
return props.isDangerous ? COLORS.red60 : COLORS.blue55
}};
border-color: ${props => {
if (props['aria-disabled']) return COLORS.grey30
return props.isDangerous ? COLORS.red60 : COLORS.blue55
}};
}

&:disabled,
Expand Down
2 changes: 1 addition & 1 deletion protocol-designer/cypress/support/MixSteps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ enum MixLocators {
AspWellOrder = '[data-testid="WellsOrderField_ListButton_aspirate"]',
ResetToDefault = 'button:contains("Reset to default")',
PrimaryOrderDropdown = 'div[tabindex="0"].sc-bqWxrE jKLbYH iFjNDq',
CancelAspSettings = '[class="SecondaryButton-sc-1opt1t9-0 kjpcRL"]',
CancelAspSettings = 'button:contains("Done")',
MixTipPos = '[data-testid="PositionField_ListButton_mix"]',
XpositionInput = '[data-testid="TipPositionModal_x_custom_input"]',
YpositionInput = '[id="TipPositionModal_y_custom_input"]',
Expand Down
Loading