From b882d615a76f3d719a4f734b4f08be3ec7e3acab Mon Sep 17 00:00:00 2001 From: Jamey Huffnagle Date: Thu, 14 Mar 2024 13:32:26 -0400 Subject: [PATCH 1/5] refactor(app): Border radius helix migration - find and replace (#14659) Closes EXEC-323, EXEC-324, EXEC-325, EXEC-326, EXEC-327, EXEC-328 --- .../DesignTokens/Colors/Colors.stories.tsx | 2 +- app/src/atoms/Banner/index.tsx | 2 +- app/src/atoms/Chip/__tests__/Chip.test.tsx | 16 ++++---- app/src/atoms/Chip/index.tsx | 10 ++--- app/src/atoms/InlineNotification/index.tsx | 2 +- app/src/atoms/InstrumentContainer/index.tsx | 2 +- .../ListItem/__tests__/ListItem.test.tsx | 8 ++-- app/src/atoms/ListItem/index.tsx | 2 +- app/src/atoms/MenuList/DropdownMenu.tsx | 4 +- app/src/atoms/MenuList/index.tsx | 2 +- app/src/atoms/SelectField/Select.tsx | 2 +- app/src/atoms/Skeleton/index.tsx | 2 +- app/src/atoms/Snackbar/index.tsx | 2 +- app/src/atoms/StatusLabel/index.tsx | 2 +- app/src/atoms/Toast/index.tsx | 4 +- .../atoms/buttons/FloatingActionButton.tsx | 2 +- app/src/atoms/buttons/LargeButton.tsx | 2 +- app/src/atoms/buttons/MediumButton.tsx | 4 +- app/src/atoms/buttons/QuaternaryButton.tsx | 2 +- app/src/atoms/buttons/RadioButton.tsx | 2 +- app/src/atoms/buttons/SmallButton.tsx | 4 +- app/src/atoms/buttons/SubmitPrimaryButton.tsx | 2 +- app/src/atoms/buttons/TabbedButton.tsx | 2 +- app/src/atoms/buttons/TertiaryButton.tsx | 2 +- .../__tests__/FloatingActionButton.test.tsx | 2 +- .../buttons/__tests__/MediumButton.test.tsx | 2 +- .../__tests__/QuaternaryButton.test.tsx | 2 +- .../buttons/__tests__/SmallButton.test.tsx | 4 +- .../__tests__/SubmitPrimaryButton.test.tsx | 2 +- .../buttons/__tests__/TabbedButton.test.tsx | 4 +- .../buttons/__tests__/TertiaryButton.test.tsx | 2 +- app/src/molecules/CardButton/index.tsx | 2 +- app/src/molecules/InfoMessage/index.tsx | 2 +- .../molecules/InstrumentCard/MenuOverlay.tsx | 2 +- app/src/molecules/InstrumentCard/index.tsx | 2 +- .../JogControls/ControlContainer.tsx | 2 +- .../JogControls/DirectionControl.tsx | 4 +- .../molecules/JogControls/StepSizeControl.tsx | 2 +- .../JogControls/TouchControlButton.tsx | 2 +- .../LegacyModal/LegacyModalShell.tsx | 4 +- .../MiniCard/__tests__/MiniCard.test.tsx | 6 +-- app/src/molecules/MiniCard/index.tsx | 2 +- app/src/molecules/Modal/Modal.stories.tsx | 2 +- app/src/molecules/Modal/Modal.tsx | 6 +-- app/src/molecules/Modal/ModalHeader.tsx | 2 +- app/src/molecules/NavTab/index.tsx | 10 ++++- .../PythonLabwareOffsetSnippet/index.tsx | 2 +- .../molecules/ToggleGroup/useToggleGroup.tsx | 6 +-- app/src/molecules/UploadInput/index.tsx | 2 +- app/src/molecules/WizardHeader/index.tsx | 4 +- .../WizardRequiredEquipmentList/index.tsx | 2 +- .../organisms/CalibrationStatusCard/index.tsx | 2 +- .../ResultsSummary/CalibrationResult.tsx | 2 +- .../ChooseProtocolSlideout/index.tsx | 12 +++++- .../organisms/ChooseRobotSlideout/index.tsx | 12 +++++- .../AddFixtureModal.tsx | 4 +- .../DeviceDetailsDeckConfiguration/index.tsx | 2 +- .../organisms/Devices/PipetteCard/index.tsx | 2 +- .../Devices/ProtocolRun/ProtocolRunHeader.tsx | 2 +- .../Devices/ProtocolRun/RunFailedModal.tsx | 2 +- .../ProtocolRun/SetupCalibrationItem.tsx | 2 +- .../SetupLabware/LabwareListItem.tsx | 2 +- .../SetupLiquids/LiquidDetailCard.tsx | 32 ++++++++++----- .../SetupLiquids/SetupLiquidsList.tsx | 16 ++++++-- .../LocationConflictModal.tsx | 4 +- .../SetupModuleAndDeck/NotConfiguredModal.tsx | 2 +- .../SetupModuleAndDeck/SetupFixtureList.tsx | 2 +- .../SetupModuleAndDeck/SetupModulesList.tsx | 2 +- .../organisms/Devices/RecentProtocolRuns.tsx | 2 +- .../Devices/RobotOverviewOverflowMenu.tsx | 2 +- .../DeviceResetSlideout.tsx | 2 +- .../RobotUpdateProgressModal.tsx | 2 +- .../UpdateBuildroot/UpdateRobotModal.tsx | 2 +- .../DropTipWizard/BeforeBeginning.tsx | 4 +- app/src/organisms/DropTipWizard/index.tsx | 2 +- .../UpdateInProgressModal.tsx | 2 +- .../UpdateResultsModal.tsx | 2 +- .../organisms/FirmwareUpdateModal/index.tsx | 2 +- .../organisms/GripperWizardFlows/index.tsx | 2 +- app/src/organisms/InstrumentInfo/index.tsx | 2 +- .../InstrumentMountItem/LabeledMount.tsx | 2 +- .../ProtocolInstrumentMountItem.tsx | 2 +- .../MoveLabwareInterventionContent.tsx | 4 +- .../PauseInterventionContent.tsx | 4 +- app/src/organisms/InterventionModal/index.tsx | 6 +-- app/src/organisms/LabwareOffsetTabs/index.tsx | 6 +-- .../LabwarePositionCheck/FatalErrorModal.tsx | 2 +- .../LabwarePositionCheck/LiveOffsetValue.tsx | 2 +- .../LabwarePositionCheck/ResultsSummary.tsx | 8 ++-- .../ModuleCard/TestShakeSlideout.tsx | 2 +- app/src/organisms/ModuleCard/index.tsx | 2 +- .../NetworkSettings/ConnectingNetwork.tsx | 2 +- .../NetworkSettings/DisplaySearchNetwork.tsx | 2 +- .../NetworkSettings/DisplayWifiList.tsx | 4 +- .../NetworkSettings/FailedToConnect.tsx | 2 +- .../organisms/NetworkSettings/SetWifiCred.tsx | 2 +- .../organisms/NetworkSettings/SetWifiSsid.tsx | 2 +- .../NetworkSettings/WifiConnectionDetails.tsx | 2 +- .../ProtocolDetailsSkeleton.tsx | 16 ++++---- .../ProtocolSetup/ProtocolSetupSkeleton.tsx | 6 +-- .../RobotDashboard/EmptyRecentRun.tsx | 2 +- .../RobotDashboard/RecentRunProtocolCard.tsx | 4 +- .../RobotDashboard/ServerInitializing.tsx | 2 +- .../RunningProtocol/CancelingRunModal.tsx | 2 +- .../CurrentRunningProtocolCommand.tsx | 2 +- .../RunningProtocol/RunFailedModal.tsx | 2 +- .../RunningProtocolCommandList.tsx | 2 +- .../organisms/OpenDoorAlertModal/index.tsx | 2 +- .../PipetteWizardFlows/ChoosePipette.tsx | 4 +- .../ProtocolDetails/ProtocolStats.tsx | 2 +- app/src/organisms/ProtocolDetails/index.tsx | 14 +++---- .../organisms/ProtocolSetupLabware/index.tsx | 4 +- .../ProtocolSetupLiquids/LiquidDetails.tsx | 10 ++--- .../organisms/ProtocolSetupLiquids/index.tsx | 6 +-- .../FixtureTable.tsx | 2 +- .../ModuleTable.tsx | 2 +- .../SetupInstructionsModal.tsx | 2 +- .../ProtocolsLanding/ProtocolCard.tsx | 2 +- .../ProtocolsLanding/ProtocolList.tsx | 4 +- .../RobotSettingsDashboard/DeviceReset.tsx | 2 +- .../EthernetConnectionDetails.tsx | 2 +- .../NetworkSettings/NetworkDetailsModal.tsx | 2 +- .../NetworkSettings/WifiConnectionDetails.tsx | 2 +- .../NetworkSettings/index.tsx | 2 +- .../RobotSystemVersion.tsx | 2 +- .../RobotSettingsDashboard/TextSize.tsx | 2 +- .../TouchscreenBrightness.tsx | 2 +- .../RobotSettingsDashboard/UpdateChannel.tsx | 2 +- app/src/organisms/RunPreview/index.tsx | 2 +- app/src/organisms/RunProgressMeter/index.tsx | 4 +- .../organisms/TakeoverModal/TakeoverModal.tsx | 2 +- app/src/organisms/TaskList/index.tsx | 4 +- app/src/organisms/UpdateAppModal/index.tsx | 4 +- .../UpdateRobotSoftware/CheckUpdates.tsx | 2 +- .../CompleteUpdateSoftware.tsx | 2 +- .../ErrorUpdateSoftware.tsx | 2 +- .../UpdateRobotSoftware/NoUpdateFound.tsx | 2 +- .../UpdateRobotSoftware/UpdateSoftware.tsx | 2 +- app/src/pages/AppSettings/index.tsx | 2 +- .../DisplayConnectionStatus.tsx | 2 +- app/src/pages/ConnectViaUSB/index.tsx | 4 +- .../Devices/ProtocolRunDetails/index.tsx | 8 ++-- app/src/pages/Devices/RobotSettings/index.tsx | 2 +- app/src/pages/EmergencyStop/index.tsx | 2 +- .../PipetteRecalibrationODDWarning.tsx | 2 +- app/src/pages/Labware/index.tsx | 4 +- .../pages/ProtocolDashboard/NoProtocols.tsx | 2 +- .../ProtocolDashboard/PinnedProtocol.tsx | 2 +- .../pages/ProtocolDashboard/ProtocolCard.tsx | 2 +- .../pages/ProtocolDetails/EmptySection.tsx | 2 +- app/src/pages/ProtocolDetails/Hardware.tsx | 8 ++-- app/src/pages/ProtocolDetails/Labware.tsx | 8 ++-- app/src/pages/ProtocolDetails/Liquids.tsx | 14 +++---- app/src/pages/ProtocolDetails/index.tsx | 2 +- app/src/pages/ProtocolSetup/index.tsx | 2 +- .../RobotSettingButton.tsx | 2 +- .../RobotSettingsList.tsx | 4 +- .../src/atoms/buttons/AlertPrimaryButton.tsx | 6 +-- .../src/atoms/buttons/PrimaryButton.tsx | 6 +-- .../src/atoms/buttons/SecondaryButton.tsx | 8 ++-- .../__tests__/AlertPrimaryButton.test.tsx | 6 +-- .../buttons/__tests__/PrimaryButton.test.tsx | 6 +-- .../__tests__/SecondaryButton.test.tsx | 6 +-- .../src/hardware-sim/Deck/FlexTrash.tsx | 6 +-- .../DeckConfigurator/EmptyConfigFixture.tsx | 6 +-- .../DeckConfigurator/constants.ts | 6 +-- .../Module/Thermocycler/index.tsx | 3 +- components/src/helix-design-system/borders.ts | 31 ++++++++++++++ components/src/helix-design-system/index.ts | 1 + components/src/icons/IconList.stories.tsx | 2 +- components/src/index.ts | 2 - components/src/modals/ModalShell.tsx | 6 +-- .../__tests__/LocationIcon.test.tsx | 8 ++-- .../src/molecules/LocationIcon/index.tsx | 6 +-- components/src/molecules/RoundTab.tsx | 6 +-- components/src/tooltips/Tooltip.tsx | 5 +-- components/src/ui-style-constants/borders.ts | 40 ------------------- components/src/ui-style-constants/index.ts | 1 - .../LabwareOverlays/EditLabwareOffDeck.tsx | 2 +- .../src/components/OffDeckLabwareSlideout.tsx | 2 +- .../CreateFileWizard/EquipmentOption.tsx | 4 +- .../modals/CreateFileWizard/MetadataTile.tsx | 2 +- .../CreateFileWizard/PipetteTipsTile.tsx | 4 +- .../modals/CreateFileWizard/RobotTypeTile.tsx | 4 +- .../src/components/modules/FlexSlotMap.tsx | 2 +- 185 files changed, 390 insertions(+), 359 deletions(-) create mode 100644 components/src/helix-design-system/borders.ts delete mode 100644 components/src/ui-style-constants/borders.ts diff --git a/app/src/DesignTokens/Colors/Colors.stories.tsx b/app/src/DesignTokens/Colors/Colors.stories.tsx index b1a1bef3c15..cb35bbea9ec 100644 --- a/app/src/DesignTokens/Colors/Colors.stories.tsx +++ b/app/src/DesignTokens/Colors/Colors.stories.tsx @@ -74,7 +74,7 @@ const Template: Story = args => { gridGap={SPACING.spacing4} width="20rem" height="6rem" - borderRadius={BORDERS.borderRadiusSize2} + borderRadius={BORDERS.borderRadius8} onClick={() => handleClick(color[0])} style={{ cursor: 'pointer' }} border={`2px solid ${COLORS.black90}`} diff --git a/app/src/atoms/Banner/index.tsx b/app/src/atoms/Banner/index.tsx index 8b875572253..a6b9b2e8a69 100644 --- a/app/src/atoms/Banner/index.tsx +++ b/app/src/atoms/Banner/index.tsx @@ -105,7 +105,7 @@ export function Banner(props: BannerProps): JSX.Element { font-size: 1.25rem; font-weight: ${TYPOGRAPHY.fontWeightSemiBold}; background-color: ${COLORS.yellow35}; - border-radius: ${BORDERS.borderRadiusSize3}; + border-radius: ${BORDERS.borderRadius12}; line-height: 1.5rem; } ` diff --git a/app/src/atoms/Chip/__tests__/Chip.test.tsx b/app/src/atoms/Chip/__tests__/Chip.test.tsx index 041e4c5afa4..a10a92e62ab 100644 --- a/app/src/atoms/Chip/__tests__/Chip.test.tsx +++ b/app/src/atoms/Chip/__tests__/Chip.test.tsx @@ -36,7 +36,7 @@ describe('Chip', () => { const chip = screen.getByTestId('Chip_success') const chipText = screen.getByText('mockSuccess') expect(chip).toHaveStyle(`background-color: ${COLORS.green35}`) - expect(chip).toHaveStyle(`border-radius: ${BORDERS.borderRadiusSize5}`) + expect(chip).toHaveStyle(`border-radius: ${BORDERS.borderRadius40}`) expect(chipText).toHaveStyle(`color: ${COLORS.green60}`) const icon = screen.getByLabelText('icon_mockSuccess') expect(icon).toHaveStyle(`color: ${COLORS.green60}`) @@ -52,7 +52,7 @@ describe('Chip', () => { const chip = screen.getByTestId('Chip_success') const chipText = screen.getByText('mockSuccess') expect(chip).toHaveStyle(`background-color: ${COLORS.transparent}`) - expect(chip).toHaveStyle(`border-radius: ${BORDERS.borderRadiusSize5}`) + expect(chip).toHaveStyle(`border-radius: ${BORDERS.borderRadius40}`) expect(chipText).toHaveStyle(`color: ${COLORS.green60}`) const icon = screen.getByLabelText('icon_mockSuccess') expect(icon).toHaveStyle(`color: ${COLORS.green60}`) @@ -67,7 +67,7 @@ describe('Chip', () => { const chip = screen.getByTestId('Chip_warning') const chipText = screen.getByText('mockWarning') expect(chip).toHaveStyle(`background-color: ${COLORS.yellow35}`) - expect(chip).toHaveStyle(`border-radius: ${BORDERS.borderRadiusSize5}`) + expect(chip).toHaveStyle(`border-radius: ${BORDERS.borderRadius40}`) expect(chipText).toHaveStyle(`color: ${COLORS.yellow60}`) const icon = screen.getByLabelText('icon_mockWarning') expect(icon).toHaveStyle(`color: ${COLORS.yellow60}`) @@ -83,7 +83,7 @@ describe('Chip', () => { const chip = screen.getByTestId('Chip_warning') const chipText = screen.getByText('mockWarning') expect(chip).toHaveStyle(`background-color: ${COLORS.transparent}`) - expect(chip).toHaveStyle(`border-radius: ${BORDERS.borderRadiusSize5}`) + expect(chip).toHaveStyle(`border-radius: ${BORDERS.borderRadius40}`) expect(chipText).toHaveStyle(`color: ${COLORS.yellow60}`) const icon = screen.getByLabelText('icon_mockWarning') expect(icon).toHaveStyle(`color: ${COLORS.yellow60}`) @@ -100,7 +100,7 @@ describe('Chip', () => { expect(chip).toHaveStyle( `background-color: ${COLORS.black90}${COLORS.opacity20HexCode}` ) - expect(chip).toHaveStyle(`border-radius: ${BORDERS.borderRadiusSize5}`) + expect(chip).toHaveStyle(`border-radius: ${BORDERS.borderRadius40}`) expect(chipText).toHaveStyle(`color: ${COLORS.grey60}`) const icon = screen.getByLabelText('icon_mockNeutral') expect(icon).toHaveStyle(`color: ${COLORS.grey60}`) @@ -116,7 +116,7 @@ describe('Chip', () => { const chip = screen.getByTestId('Chip_neutral') const chipText = screen.getByText('mockNeutral') expect(chip).toHaveStyle(`background-color: ${COLORS.transparent}`) - expect(chip).toHaveStyle(`border-radius: ${BORDERS.borderRadiusSize5}`) + expect(chip).toHaveStyle(`border-radius: ${BORDERS.borderRadius40}`) expect(chipText).toHaveStyle(`color: ${COLORS.grey60}`) const icon = screen.getByLabelText('icon_mockNeutral') expect(icon).toHaveStyle(`color: ${COLORS.grey60}`) @@ -131,7 +131,7 @@ describe('Chip', () => { const chip = screen.getByTestId('Chip_error') const chipText = screen.getByText('mockError') expect(chip).toHaveStyle(`background-color: ${COLORS.red35}`) - expect(chip).toHaveStyle(`border-radius: ${BORDERS.borderRadiusSize5}`) + expect(chip).toHaveStyle(`border-radius: ${BORDERS.borderRadius40}`) expect(chipText).toHaveStyle(`color: ${COLORS.red60}`) const icon = screen.getByLabelText('icon_mockError') expect(icon).toHaveStyle(`color: ${COLORS.red60}`) @@ -147,7 +147,7 @@ describe('Chip', () => { const chip = screen.getByTestId('Chip_error') const chipText = screen.getByText('mockError') expect(chip).toHaveStyle(`background-color: ${COLORS.transparent}`) - expect(chip).toHaveStyle(`border-radius: ${BORDERS.borderRadiusSize5}`) + expect(chip).toHaveStyle(`border-radius: ${BORDERS.borderRadius40}`) expect(chipText).toHaveStyle(`color: ${COLORS.red60}`) const icon = screen.getByLabelText('icon_mockError') expect(icon).toHaveStyle(`color: ${COLORS.red60}`) diff --git a/app/src/atoms/Chip/index.tsx b/app/src/atoms/Chip/index.tsx index 5a6f16a0418..d63c6c15a31 100644 --- a/app/src/atoms/Chip/index.tsx +++ b/app/src/atoms/Chip/index.tsx @@ -40,31 +40,31 @@ const CHIP_PROPS_BY_TYPE: Record< > = { basic: { backgroundColor: `${COLORS.black90}${COLORS.opacity20HexCode}`, - borderRadius: BORDERS.borderRadiusSize1, + borderRadius: BORDERS.borderRadius4, textColor: COLORS.grey60, }, error: { backgroundColor: COLORS.red35, - borderRadius: BORDERS.borderRadiusSize5, + borderRadius: BORDERS.borderRadius40, iconColor: COLORS.red60, textColor: COLORS.red60, }, neutral: { backgroundColor: `${COLORS.black90}${COLORS.opacity20HexCode}`, - borderRadius: BORDERS.borderRadiusSize5, + borderRadius: BORDERS.borderRadius40, iconColor: COLORS.grey60, textColor: COLORS.grey60, }, success: { backgroundColor: COLORS.green35, - borderRadius: BORDERS.borderRadiusSize5, + borderRadius: BORDERS.borderRadius40, iconColor: COLORS.green60, iconName: 'ot-check', textColor: COLORS.green60, }, warning: { backgroundColor: COLORS.yellow35, - borderRadius: BORDERS.borderRadiusSize5, + borderRadius: BORDERS.borderRadius40, iconColor: COLORS.yellow60, textColor: COLORS.yellow60, }, diff --git a/app/src/atoms/InlineNotification/index.tsx b/app/src/atoms/InlineNotification/index.tsx index 03294967bae..05887d2fe55 100644 --- a/app/src/atoms/InlineNotification/index.tsx +++ b/app/src/atoms/InlineNotification/index.tsx @@ -72,7 +72,7 @@ export function InlineNotification( { expect(listItem).toHaveStyle( `padding: ${SPACING.spacing16} ${SPACING.spacing24}` ) - expect(listItem).toHaveStyle(`borderRadius: ${BORDERS.borderRadiusSize3}`) + expect(listItem).toHaveStyle(`borderRadius: ${BORDERS.borderRadius12}`) }) it('should render correct style - noActive', () => { props.type = 'noActive' @@ -39,7 +39,7 @@ describe('ListItem', () => { expect(listItem).toHaveStyle( `padding: ${SPACING.spacing16} ${SPACING.spacing24}` ) - expect(listItem).toHaveStyle(`borderRadius: ${BORDERS.borderRadiusSize3}`) + expect(listItem).toHaveStyle(`borderRadius: ${BORDERS.borderRadius12}`) }) it('should render correct style - success', () => { props.type = 'success' @@ -50,7 +50,7 @@ describe('ListItem', () => { expect(listItem).toHaveStyle( `padding: ${SPACING.spacing16} ${SPACING.spacing24}` ) - expect(listItem).toHaveStyle(`borderRadius: ${BORDERS.borderRadiusSize3}`) + expect(listItem).toHaveStyle(`borderRadius: ${BORDERS.borderRadius12}`) }) it('should render correct style - warning', () => { props.type = 'warning' @@ -61,6 +61,6 @@ describe('ListItem', () => { expect(listItem).toHaveStyle( `padding: ${SPACING.spacing16} ${SPACING.spacing24}` ) - expect(listItem).toHaveStyle(`borderRadius: ${BORDERS.borderRadiusSize3}`) + expect(listItem).toHaveStyle(`borderRadius: ${BORDERS.borderRadius12}`) }) }) diff --git a/app/src/atoms/ListItem/index.tsx b/app/src/atoms/ListItem/index.tsx index 741ce9233c1..8df8ed82938 100644 --- a/app/src/atoms/ListItem/index.tsx +++ b/app/src/atoms/ListItem/index.tsx @@ -42,7 +42,7 @@ export function ListItem(props: ListItemProps): JSX.Element { height="max-content" padding={`${SPACING.spacing16} ${SPACING.spacing24}`} backgroundColor={listItemProps.backgroundColor} - borderRadius={BORDERS.borderRadiusSize3} + borderRadius={BORDERS.borderRadius12} {...styleProps} > {children} diff --git a/app/src/atoms/MenuList/DropdownMenu.tsx b/app/src/atoms/MenuList/DropdownMenu.tsx index 5c1fb657cec..47c6c09e28f 100644 --- a/app/src/atoms/MenuList/DropdownMenu.tsx +++ b/app/src/atoms/MenuList/DropdownMenu.tsx @@ -48,7 +48,7 @@ export function DropdownMenu(props: DropdownMenuProps): JSX.Element { width="9.125rem" onClick={toggleSetShowDropdownMenu} border={BORDERS.lineBorder} - borderRadius={BORDERS.radiusRoundEdge} + borderRadius={BORDERS.borderRadiusFull} padding={SPACING.spacing8} backgroundColor={COLORS.white} css={css` @@ -65,7 +65,7 @@ export function DropdownMenu(props: DropdownMenuProps): JSX.Element { { const { children, isOnDevice = false, onClick = null } = props return isOnDevice && onClick != null ? ( diff --git a/app/src/atoms/SelectField/Select.tsx b/app/src/atoms/SelectField/Select.tsx index 4ac553344d8..92192c264bb 100644 --- a/app/src/atoms/SelectField/Select.tsx +++ b/app/src/atoms/SelectField/Select.tsx @@ -41,7 +41,7 @@ export function Select(props: SelectComponentProps): JSX.Element { clearIndicator: NO_STYLE_FN, control: (styles: CSSObjectWithLabel) => ({ ...styles, - borderRadius: BORDERS.radiusRoundEdge, + borderRadius: BORDERS.borderRadiusFull, border: BORDERS.lineBorder, width: props.width != null ? props.width : 'auto', height: SPACING.spacing16, diff --git a/app/src/atoms/Skeleton/index.tsx b/app/src/atoms/Skeleton/index.tsx index 69890ee621f..7a006ece04c 100644 --- a/app/src/atoms/Skeleton/index.tsx +++ b/app/src/atoms/Skeleton/index.tsx @@ -12,7 +12,7 @@ interface SkeletonProps { export const Skeleton = (props: SkeletonProps): JSX.Element => { const { width, height, backgroundSize, borderRadius } = props const SKELETON_STYLE = css` - border-radius: ${borderRadius ?? BORDERS.radiusSoftCorners}; + border-radius: ${borderRadius ?? BORDERS.borderRadius4}; animation: shimmer 2s infinite linear; background: linear-gradient( to right, diff --git a/app/src/atoms/Snackbar/index.tsx b/app/src/atoms/Snackbar/index.tsx index 3282de66e52..bc7706225a9 100644 --- a/app/src/atoms/Snackbar/index.tsx +++ b/app/src/atoms/Snackbar/index.tsx @@ -77,7 +77,7 @@ export function Snackbar(props: SnackbarProps): JSX.Element { { { const SUBMIT_INPUT_STYLE = css` background-color: ${COLORS.blue50}; - border-radius: ${BORDERS.radiusSoftCorners}; + border-radius: ${BORDERS.borderRadius4}; padding: ${SPACING.spacing8} ${SPACING.spacing16}; color: ${COLORS.white}; ${TYPOGRAPHY.pSemiBold} diff --git a/app/src/atoms/buttons/TabbedButton.tsx b/app/src/atoms/buttons/TabbedButton.tsx index 224f0f52e2a..6d4d8f7b967 100644 --- a/app/src/atoms/buttons/TabbedButton.tsx +++ b/app/src/atoms/buttons/TabbedButton.tsx @@ -45,7 +45,7 @@ interface TabbedButtonProps extends React.ComponentProps { export const TabbedButton = styled(Btn)` ${props => css` - border-radius: ${BORDERS.borderRadiusSize4}; + border-radius: ${BORDERS.borderRadius16}; box-shadow: none; font-size: ${TYPOGRAPHY.fontSize22}; font-weight: ${TYPOGRAPHY.fontWeightSemiBold}; diff --git a/app/src/atoms/buttons/TertiaryButton.tsx b/app/src/atoms/buttons/TertiaryButton.tsx index a6ab30fb0ed..a44cdd3d61a 100644 --- a/app/src/atoms/buttons/TertiaryButton.tsx +++ b/app/src/atoms/buttons/TertiaryButton.tsx @@ -10,7 +10,7 @@ import { export const TertiaryButton = styled(NewPrimaryBtn)` background-color: ${COLORS.blue50}; - border-radius: ${BORDERS.radiusRoundEdge}; + border-radius: ${BORDERS.borderRadiusFull}; box-shadow: none; color: ${COLORS.white}; overflow: no-wrap; diff --git a/app/src/atoms/buttons/__tests__/FloatingActionButton.test.tsx b/app/src/atoms/buttons/__tests__/FloatingActionButton.test.tsx index d8f27ce0e0b..7e62b0f8662 100644 --- a/app/src/atoms/buttons/__tests__/FloatingActionButton.test.tsx +++ b/app/src/atoms/buttons/__tests__/FloatingActionButton.test.tsx @@ -34,7 +34,7 @@ describe('FloatingActionButton', () => { expect(button).toHaveStyle(`font-size: ${TYPOGRAPHY.fontSize28}`) expect(button).toHaveStyle(`font-weight: ${TYPOGRAPHY.fontWeightSemiBold}`) expect(button).toHaveStyle(`line-height: ${TYPOGRAPHY.lineHeight36}`) - expect(button).toHaveStyle(`border-radius: ${BORDERS.borderRadiusSize5}`) + expect(button).toHaveStyle(`border-radius: ${BORDERS.borderRadius40}`) expect(button).toHaveStyle( `text-transform: ${TYPOGRAPHY.textTransformNone}` ) diff --git a/app/src/atoms/buttons/__tests__/MediumButton.test.tsx b/app/src/atoms/buttons/__tests__/MediumButton.test.tsx index 456da8768b8..f4d23ea3a32 100644 --- a/app/src/atoms/buttons/__tests__/MediumButton.test.tsx +++ b/app/src/atoms/buttons/__tests__/MediumButton.test.tsx @@ -93,7 +93,7 @@ describe('MediumButton', () => { } render(props) expect(screen.getByRole('button')).toHaveStyle( - `border-radius: ${BORDERS.borderRadiusSize5}` + `border-radius: ${BORDERS.borderRadius40}` ) }) }) diff --git a/app/src/atoms/buttons/__tests__/QuaternaryButton.test.tsx b/app/src/atoms/buttons/__tests__/QuaternaryButton.test.tsx index 116dc1c287d..978f46e3c08 100644 --- a/app/src/atoms/buttons/__tests__/QuaternaryButton.test.tsx +++ b/app/src/atoms/buttons/__tests__/QuaternaryButton.test.tsx @@ -24,7 +24,7 @@ describe('QuaternaryButton', () => { render(props) const button = screen.getByText('secondary tertiary button') expect(button).toHaveStyle(`background-color: ${COLORS.white}`) - expect(button).toHaveStyle(`border-radius: ${BORDERS.radiusRoundEdge}`) + expect(button).toHaveStyle(`border-radius: ${BORDERS.borderRadiusFull}`) expect(button).toHaveStyle('box-shadow: 0 0 0') expect(button).toHaveStyle(`color: ${COLORS.blue50}`) expect(button).toHaveStyle( diff --git a/app/src/atoms/buttons/__tests__/SmallButton.test.tsx b/app/src/atoms/buttons/__tests__/SmallButton.test.tsx index b86a4939d74..2aa55acef6e 100644 --- a/app/src/atoms/buttons/__tests__/SmallButton.test.tsx +++ b/app/src/atoms/buttons/__tests__/SmallButton.test.tsx @@ -28,7 +28,7 @@ describe('SmallButton', () => { `background-color: ${COLORS.blue60}` ) expect(screen.getByRole('button')).toHaveStyle( - `border-radius: ${BORDERS.borderRadiusSize4}` + `border-radius: ${BORDERS.borderRadius16}` ) }) it('renders the alert button', () => { @@ -82,7 +82,7 @@ describe('SmallButton', () => { } render(props) expect(screen.getByRole('button')).toHaveStyle( - `border-radius: ${BORDERS.borderRadiusSize5}` + `border-radius: ${BORDERS.borderRadius40}` ) }) it('renders an icon with start placement', () => { diff --git a/app/src/atoms/buttons/__tests__/SubmitPrimaryButton.test.tsx b/app/src/atoms/buttons/__tests__/SubmitPrimaryButton.test.tsx index 3a3d9a68435..333a42c0d79 100644 --- a/app/src/atoms/buttons/__tests__/SubmitPrimaryButton.test.tsx +++ b/app/src/atoms/buttons/__tests__/SubmitPrimaryButton.test.tsx @@ -29,7 +29,7 @@ describe('SubmitPrimaryButton', () => { render(props) const button = screen.getByText('submit primary button') expect(button).toHaveStyle(`background-color: ${COLORS.blue60}`) - expect(button).toHaveStyle(`border-radius: ${BORDERS.radiusSoftCorners}`) + expect(button).toHaveStyle(`border-radius: ${BORDERS.borderRadius4}`) expect(button).toHaveStyle( `padding: ${SPACING.spacing8} ${SPACING.spacing16}` ) diff --git a/app/src/atoms/buttons/__tests__/TabbedButton.test.tsx b/app/src/atoms/buttons/__tests__/TabbedButton.test.tsx index c58596b2971..893b71ab904 100644 --- a/app/src/atoms/buttons/__tests__/TabbedButton.test.tsx +++ b/app/src/atoms/buttons/__tests__/TabbedButton.test.tsx @@ -30,7 +30,7 @@ describe('Unselected TabbedButton', () => { expect(button).toHaveStyle(`font-size: ${TYPOGRAPHY.fontSize22}`) expect(button).toHaveStyle(`font-weight: ${TYPOGRAPHY.fontWeightSemiBold}`) expect(button).toHaveStyle(`line-height: ${TYPOGRAPHY.lineHeight28}`) - expect(button).toHaveStyle(`border-radius: ${BORDERS.borderRadiusSize4}`) + expect(button).toHaveStyle(`border-radius: ${BORDERS.borderRadius16}`) expect(button).toHaveStyle( `text-transform: ${TYPOGRAPHY.textTransformNone}` ) @@ -75,7 +75,7 @@ describe('Selected TabbedButton', () => { expect(button).toHaveStyle(`font-size: ${TYPOGRAPHY.fontSize22}`) expect(button).toHaveStyle(`font-weight: ${TYPOGRAPHY.fontWeightSemiBold}`) expect(button).toHaveStyle(`line-height: ${TYPOGRAPHY.lineHeight28}`) - expect(button).toHaveStyle(`border-radius: ${BORDERS.borderRadiusSize4}`) + expect(button).toHaveStyle(`border-radius: ${BORDERS.borderRadius16}`) expect(button).toHaveStyle( `text-transform: ${TYPOGRAPHY.textTransformNone}` ) diff --git a/app/src/atoms/buttons/__tests__/TertiaryButton.test.tsx b/app/src/atoms/buttons/__tests__/TertiaryButton.test.tsx index 488d5fa1aec..4c0b2b97a1e 100644 --- a/app/src/atoms/buttons/__tests__/TertiaryButton.test.tsx +++ b/app/src/atoms/buttons/__tests__/TertiaryButton.test.tsx @@ -29,7 +29,7 @@ describe('TertiaryButton', () => { expect(button).toHaveStyle(`font-size: ${TYPOGRAPHY.fontSizeLabel}`) expect(button).toHaveStyle(`font-weight: ${TYPOGRAPHY.fontWeightSemiBold}`) expect(button).toHaveStyle(`line-height: ${TYPOGRAPHY.lineHeight12}`) - expect(button).toHaveStyle(`border-radius: ${BORDERS.radiusRoundEdge}`) + expect(button).toHaveStyle(`border-radius: ${BORDERS.borderRadiusFull}`) expect(button).toHaveStyle( `text-transform: ${TYPOGRAPHY.textTransformNone}` ) diff --git a/app/src/molecules/CardButton/index.tsx b/app/src/molecules/CardButton/index.tsx index ece8c803f8a..8a86d4de651 100644 --- a/app/src/molecules/CardButton/index.tsx +++ b/app/src/molecules/CardButton/index.tsx @@ -22,7 +22,7 @@ const CARD_BUTTON_STYLE = css` display: flex; flex-direction: ${DIRECTION_COLUMN}; align-items: ${ALIGN_CENTER}; - border-radius: ${BORDERS.borderRadiusSize5}; + border-radius: ${BORDERS.borderRadius40}; padding: ${SPACING.spacing32}; box-shadow: none; diff --git a/app/src/molecules/InfoMessage/index.tsx b/app/src/molecules/InfoMessage/index.tsx index dd576483c29..0d3c7174557 100644 --- a/app/src/molecules/InfoMessage/index.tsx +++ b/app/src/molecules/InfoMessage/index.tsx @@ -26,7 +26,7 @@ export function InfoMessage({ title, body }: InfoMessageProps): JSX.Element { backgroundColor={COLORS.blue30} flexDirection={DIRECTION_ROW} alignItems={body != null ? ALIGN_FLEX_START : ALIGN_CENTER} - borderRadius={BORDERS.radiusSoftCorners} + borderRadius={BORDERS.borderRadius4} gridGap={SPACING.spacing8} padding={SPACING.spacing16} data-testid={`InfoMessage_${title}`} diff --git a/app/src/molecules/InstrumentCard/MenuOverlay.tsx b/app/src/molecules/InstrumentCard/MenuOverlay.tsx index 6c1f5a37143..33b9e5eb13e 100644 --- a/app/src/molecules/InstrumentCard/MenuOverlay.tsx +++ b/app/src/molecules/InstrumentCard/MenuOverlay.tsx @@ -32,7 +32,7 @@ export function MenuOverlay(props: MenuOverlayProps): JSX.Element { return ( diff --git a/app/src/molecules/JogControls/StepSizeControl.tsx b/app/src/molecules/JogControls/StepSizeControl.tsx index b5f30c0a0cb..d53ae5de06d 100644 --- a/app/src/molecules/JogControls/StepSizeControl.tsx +++ b/app/src/molecules/JogControls/StepSizeControl.tsx @@ -174,7 +174,7 @@ export function TouchStepSizeControl(props: StepSizeControlProps): JSX.Element { flex="3" flexDirection={DIRECTION_COLUMN} border={`1px solid ${COLORS.grey50}`} - borderRadius={BORDERS.borderRadiusSize4} + borderRadius={BORDERS.borderRadius16} padding={SPACING.spacing16} gridGap={SPACING.spacing16} > diff --git a/app/src/molecules/JogControls/TouchControlButton.tsx b/app/src/molecules/JogControls/TouchControlButton.tsx index 10422172381..0ad85f1de7d 100644 --- a/app/src/molecules/JogControls/TouchControlButton.tsx +++ b/app/src/molecules/JogControls/TouchControlButton.tsx @@ -7,7 +7,7 @@ export const TouchControlButton = styled.button<{ selected: boolean }>` background-color: ${({ selected }) => selected ? COLORS.blue50 : COLORS.blue35}; cursor: default; - border-radius: ${BORDERS.borderRadiusSize4}; + border-radius: ${BORDERS.borderRadius16}; box-shadow: none; padding: ${SPACING.spacing8} ${SPACING.spacing20}; diff --git a/app/src/molecules/LegacyModal/LegacyModalShell.tsx b/app/src/molecules/LegacyModal/LegacyModalShell.tsx index c97ab700582..61933b0b9c6 100644 --- a/app/src/molecules/LegacyModal/LegacyModalShell.tsx +++ b/app/src/molecules/LegacyModal/LegacyModalShell.tsx @@ -107,12 +107,12 @@ const ModalArea = styled.div< overflow-y: ${OVERFLOW_AUTO}; max-height: 100%; width: 100%; - border-radius: ${BORDERS.radiusSoftCorners}; + border-radius: ${BORDERS.borderRadius4}; box-shadow: ${BORDERS.smallDropShadow}; height: ${({ isFullPage }) => (isFullPage ? '100%' : 'auto')}; background-color: ${COLORS.white}; @media ${RESPONSIVENESS.touchscreenMediaQuerySpecs} { - border-radius: ${BORDERS.borderRadiusSize4}; + border-radius: ${BORDERS.borderRadius16}; } ${styleProps}; ` diff --git a/app/src/molecules/MiniCard/__tests__/MiniCard.test.tsx b/app/src/molecules/MiniCard/__tests__/MiniCard.test.tsx index c1538b3fd46..5c980a5b77a 100644 --- a/app/src/molecules/MiniCard/__tests__/MiniCard.test.tsx +++ b/app/src/molecules/MiniCard/__tests__/MiniCard.test.tsx @@ -27,7 +27,7 @@ describe('MiniCard', () => { const miniCard = screen.getByText('mock mini card') expect(miniCard).toHaveStyle(`background-color: ${COLORS.grey10}`) expect(miniCard).toHaveStyle(`border: 1px solid ${COLORS.grey35}`) - expect(miniCard).toHaveStyle(`border-radius: ${BORDERS.radiusSoftCorners}`) + expect(miniCard).toHaveStyle(`border-radius: ${BORDERS.borderRadius4}`) expect(miniCard).toHaveStyle(`padding: ${SPACING.spacing8}`) expect(miniCard).toHaveStyle(`width: 100%`) expect(miniCard).toHaveStyle(`cursor: pointer`) @@ -39,7 +39,7 @@ describe('MiniCard', () => { const miniCard = screen.getByText('mock mini card') expect(miniCard).toHaveStyle(`background-color: ${COLORS.blue10}`) expect(miniCard).toHaveStyle(`border: 1px solid ${COLORS.blue50}`) - expect(miniCard).toHaveStyle(`border-radius: ${BORDERS.radiusSoftCorners}`) + expect(miniCard).toHaveStyle(`border-radius: ${BORDERS.borderRadius4}`) expect(miniCard).toHaveStyle(`padding: ${SPACING.spacing8}`) expect(miniCard).toHaveStyle(`width: 100%`) expect(miniCard).toHaveStyle(`cursor: pointer`) @@ -52,7 +52,7 @@ describe('MiniCard', () => { const miniCard = screen.getByText('mock mini card') expect(miniCard).toHaveStyle(`background-color: ${COLORS.red20}`) expect(miniCard).toHaveStyle(`border: 1px solid ${COLORS.red50}`) - expect(miniCard).toHaveStyle(`border-radius: ${BORDERS.radiusSoftCorners}`) + expect(miniCard).toHaveStyle(`border-radius: ${BORDERS.borderRadius4}`) expect(miniCard).toHaveStyle(`padding: ${SPACING.spacing8}`) expect(miniCard).toHaveStyle(`width: 100%`) expect(miniCard).toHaveStyle(`cursor: pointer`) diff --git a/app/src/molecules/MiniCard/index.tsx b/app/src/molecules/MiniCard/index.tsx index 1b7dd584f6a..f3f4c99cd56 100644 --- a/app/src/molecules/MiniCard/index.tsx +++ b/app/src/molecules/MiniCard/index.tsx @@ -14,7 +14,7 @@ interface MiniCardProps extends StyleProps { const unselectedOptionStyles = css` background-color: ${COLORS.white}; border: 1px solid ${COLORS.grey30}; - border-radius: ${BORDERS.radiusSoftCorners}; + border-radius: ${BORDERS.borderRadius4}; padding: ${SPACING.spacing8}; width: 100%; cursor: pointer; diff --git a/app/src/molecules/Modal/Modal.stories.tsx b/app/src/molecules/Modal/Modal.stories.tsx index 7060d710fdb..e29a6197224 100644 --- a/app/src/molecules/Modal/Modal.stories.tsx +++ b/app/src/molecules/Modal/Modal.stories.tsx @@ -30,7 +30,7 @@ Default.args = { }, children: ( diff --git a/app/src/molecules/Modal/Modal.tsx b/app/src/molecules/Modal/Modal.tsx index 42c803049d7..f51293c015d 100644 --- a/app/src/molecules/Modal/Modal.tsx +++ b/app/src/molecules/Modal/Modal.tsx @@ -61,7 +61,7 @@ export function Modal(props: ModalProps): JSX.Element { width={modalWidth} height="max-content" maxHeight="36.875rem" - borderRadius={BORDERS.borderRadiusSize3} + borderRadius={BORDERS.borderRadius12} boxShadow={BORDERS.shadowSmall} margin={SPACING.spacing32} flexDirection={DIRECTION_COLUMN} @@ -80,8 +80,8 @@ export function Modal(props: ModalProps): JSX.Element { paddingTop={header != null ? '0rem' : SPACING.spacing32} borderRadius={ header != null - ? `0px 0px ${BORDERS.borderRadiusSize3} ${BORDERS.borderRadiusSize3}` - : BORDERS.borderRadiusSize3 + ? `0px 0px ${BORDERS.borderRadius12} ${BORDERS.borderRadius12}` + : BORDERS.borderRadius12 } maxHeight="30.625rem" {...styleProps} diff --git a/app/src/molecules/Modal/ModalHeader.tsx b/app/src/molecules/Modal/ModalHeader.tsx index b62e592d537..7d73adc3468 100644 --- a/app/src/molecules/Modal/ModalHeader.tsx +++ b/app/src/molecules/Modal/ModalHeader.tsx @@ -32,7 +32,7 @@ export function ModalHeader(props: ModalHeaderBaseProps): JSX.Element { flexDirection={DIRECTION_ROW} justifyContent={JUSTIFY_SPACE_BETWEEN} alignItems={ALIGN_CENTER} - borderRadius={`${BORDERS.borderRadiusSize3} ${BORDERS.borderRadiusSize3} 0px 0px`} + borderRadius={`${BORDERS.borderRadius12} ${BORDERS.borderRadius12} 0px 0px`} {...styleProps} > diff --git a/app/src/molecules/NavTab/index.tsx b/app/src/molecules/NavTab/index.tsx index 75dea82b9c1..97d6e4a9f12 100644 --- a/app/src/molecules/NavTab/index.tsx +++ b/app/src/molecules/NavTab/index.tsx @@ -1,9 +1,15 @@ import * as React from 'react' +import styled, { css } from 'styled-components' import { NavLink } from 'react-router-dom' -import styled from 'styled-components' import { BORDERS, COLORS, SPACING, TYPOGRAPHY } from '@opentrons/components' +export const TAB_BORDER_STYLE = css` + border-bottom-style: ${BORDERS.styleSolid}; + border-bottom-width: 2px; + border-bottom-color: ${COLORS.purple50}; +` + interface NavTabProps { to: string tabName: string @@ -17,7 +23,7 @@ const StyledNavLink = styled(NavLink)>` &.active { color: ${COLORS.black90}; - ${BORDERS.tabBorder} + ${TAB_BORDER_STYLE} } ` const DisabledNavLink = styled.span` diff --git a/app/src/molecules/PythonLabwareOffsetSnippet/index.tsx b/app/src/molecules/PythonLabwareOffsetSnippet/index.tsx index 9844e1cc416..00862359a37 100644 --- a/app/src/molecules/PythonLabwareOffsetSnippet/index.tsx +++ b/app/src/molecules/PythonLabwareOffsetSnippet/index.tsx @@ -13,7 +13,7 @@ const JsonTextArea = styled.textarea` min-height: 28vh; width: 100%; background-color: ${COLORS.grey30}; - border-radius: ${BORDERS.radiusSoftCorners}; + border-radius: ${BORDERS.borderRadius4}; padding: ${SPACING.spacing8}; margin: ${SPACING.spacing16} 0; font-size: ${TYPOGRAPHY.fontSizeCaption}; diff --git a/app/src/molecules/ToggleGroup/useToggleGroup.tsx b/app/src/molecules/ToggleGroup/useToggleGroup.tsx index 841e471dd0c..107f3a67449 100644 --- a/app/src/molecules/ToggleGroup/useToggleGroup.tsx +++ b/app/src/molecules/ToggleGroup/useToggleGroup.tsx @@ -10,7 +10,7 @@ import { import { useTrackEvent } from '../../redux/analytics' const BUTTON_GROUP_STYLES = css` - border-radius: ${BORDERS.radiusSoftCorners}; + border-radius: ${BORDERS.borderRadius4}; margin-top: -1px; width: fit-content; @@ -47,12 +47,12 @@ const BUTTON_GROUP_STYLES = css` } button:first-child { - border-radius: ${BORDERS.radiusSoftCorners} 0 0 ${BORDERS.radiusSoftCorners}; + border-radius: ${BORDERS.borderRadius4} 0 0 ${BORDERS.borderRadius4}; border-right: none; } button:last-child { - border-radius: 0 ${BORDERS.radiusSoftCorners} ${BORDERS.radiusSoftCorners} 0; + border-radius: 0 ${BORDERS.borderRadius4} ${BORDERS.borderRadius4} 0; border-left: none; } ` diff --git a/app/src/molecules/UploadInput/index.tsx b/app/src/molecules/UploadInput/index.tsx index d794cc4df76..68be10dc49c 100644 --- a/app/src/molecules/UploadInput/index.tsx +++ b/app/src/molecules/UploadInput/index.tsx @@ -24,7 +24,7 @@ const StyledLabel = styled.label` width: 100%; padding: ${SPACING.spacing32}; border: 2px dashed ${COLORS.grey30}; - border-radius: ${BORDERS.radiusSoftCorners}; + border-radius: ${BORDERS.borderRadius4}; text-align: center; background-color: ${COLORS.white}; diff --git a/app/src/molecules/WizardHeader/index.tsx b/app/src/molecules/WizardHeader/index.tsx index d1f28588988..867a1d2eda6 100644 --- a/app/src/molecules/WizardHeader/index.tsx +++ b/app/src/molecules/WizardHeader/index.tsx @@ -48,7 +48,7 @@ const EXIT_BUTTON_STYLE = css` const BOX_STYLE = css` background-color: ${COLORS.white} @media ${RESPONSIVENESS.touchscreenMediaQuerySpecs} { - border-radius: ${BORDERS.borderRadiusSize4}; + border-radius: ${BORDERS.borderRadius16}; } ` const HEADER_CONTAINER_STYLE = css` @@ -57,7 +57,7 @@ const HEADER_CONTAINER_STYLE = css` padding: ${SPACING.spacing16} ${SPACING.spacing32}; @media ${RESPONSIVENESS.touchscreenMediaQuerySpecs} { padding: 1.75rem ${SPACING.spacing32}; - border-radius: ${BORDERS.borderRadiusSize4}; + border-radius: ${BORDERS.borderRadius16}; } ` const HEADER_TEXT_STYLE = css` diff --git a/app/src/molecules/WizardRequiredEquipmentList/index.tsx b/app/src/molecules/WizardRequiredEquipmentList/index.tsx index 94308b5dc0f..a8d1569f02c 100644 --- a/app/src/molecules/WizardRequiredEquipmentList/index.tsx +++ b/app/src/molecules/WizardRequiredEquipmentList/index.tsx @@ -53,7 +53,7 @@ export function WizardRequiredEquipmentList( {equipmentList.map((requiredEquipmentProps, index) => ( diff --git a/app/src/organisms/CalibrationStatusCard/index.tsx b/app/src/organisms/CalibrationStatusCard/index.tsx index 29e15b64510..db2f2e36076 100644 --- a/app/src/organisms/CalibrationStatusCard/index.tsx +++ b/app/src/organisms/CalibrationStatusCard/index.tsx @@ -62,7 +62,7 @@ export function CalibrationStatusCard({ alignItems={ALIGN_CENTER} justifyContent={JUSTIFY_SPACE_BETWEEN} border={BORDERS.lineBorder} - borderRadius={BORDERS.radiusSoftCorners} + borderRadius={BORDERS.borderRadius4} padding={SPACING.spacing16} > { return filePath.split('/').reverse()[0] } @@ -360,7 +370,7 @@ function StoredProtocolList(props: StoredProtocolListProps): JSX.Element { minHeight="11rem" padding={SPACING.spacing16} css={css` - ${BORDERS.cardOutlineBorder} + ${CARD_OUTLINE_BORDER_STYLE} &:hover { border-color: ${COLORS.grey30}; } diff --git a/app/src/organisms/ChooseRobotSlideout/index.tsx b/app/src/organisms/ChooseRobotSlideout/index.tsx index 152939001c5..fa8d0cb1c3f 100644 --- a/app/src/organisms/ChooseRobotSlideout/index.tsx +++ b/app/src/organisms/ChooseRobotSlideout/index.tsx @@ -46,6 +46,16 @@ import type { State, Dispatch } from '../../redux/types' import type { Robot } from '../../redux/discovery/types' import { useFeatureFlag } from '../../redux/config' +export const CARD_OUTLINE_BORDER_STYLE = css` + border-style: ${BORDERS.styleSolid}; + border-width: 1px; + border-color: ${COLORS.grey30}; + border-radius: ${BORDERS.borderRadius4}; + &:hover { + border-color: ${COLORS.grey55}; + } +` + interface RobotIsBusyAction { type: 'robotIsBusy' robotName: string @@ -210,7 +220,7 @@ export function ChooseRobotSlideout( {!isScanning && healthyReachableRobots.length === 0 ? ( {fixtureDisplayName} @@ -253,7 +253,7 @@ export function AddFixtureModal({ const FIXTURE_BUTTON_STYLE = css` background-color: ${COLORS.grey35}; cursor: default; - border-radius: ${BORDERS.borderRadiusSize3}; + border-radius: ${BORDERS.borderRadius12}; box-shadow: none; &:focus { diff --git a/app/src/organisms/DeviceDetailsDeckConfiguration/index.tsx b/app/src/organisms/DeviceDetailsDeckConfiguration/index.tsx index a3310c0fae5..5e86b338067 100644 --- a/app/src/organisms/DeviceDetailsDeckConfiguration/index.tsx +++ b/app/src/organisms/DeviceDetailsDeckConfiguration/index.tsx @@ -118,7 +118,7 @@ export function DeviceDetailsDeckConfiguration({ { return ( diff --git a/app/src/organisms/Devices/ProtocolRun/ProtocolRunHeader.tsx b/app/src/organisms/Devices/ProtocolRun/ProtocolRunHeader.tsx index 8d7737a3007..11930abee1e 100644 --- a/app/src/organisms/Devices/ProtocolRun/ProtocolRunHeader.tsx +++ b/app/src/organisms/Devices/ProtocolRun/ProtocolRunHeader.tsx @@ -325,7 +325,7 @@ export function ProtocolRunHeader({ setSelectedValue(liquidId)} width="19.875rem" @@ -98,7 +108,7 @@ export function LiquidDetailCard(props: LiquidDetailCardProps): JSX.Element { > {t('protocol_specifies')} @@ -201,7 +201,7 @@ export const LocationConflictModal = ( flexDirection={DIRECTION_ROW} justifyContent={JUSTIFY_SPACE_BETWEEN} alignItems={ALIGN_CENTER} - borderRadius={BORDERS.borderRadiusSize3} + borderRadius={BORDERS.borderRadius12} > {t('currently_configured')} diff --git a/app/src/organisms/Devices/ProtocolRun/SetupModuleAndDeck/NotConfiguredModal.tsx b/app/src/organisms/Devices/ProtocolRun/SetupModuleAndDeck/NotConfiguredModal.tsx index 12988f521b6..54793a4d9f8 100644 --- a/app/src/organisms/Devices/ProtocolRun/SetupModuleAndDeck/NotConfiguredModal.tsx +++ b/app/src/organisms/Devices/ProtocolRun/SetupModuleAndDeck/NotConfiguredModal.tsx @@ -62,7 +62,7 @@ export const NotConfiguredModal = ( diff --git a/app/src/organisms/Devices/ProtocolRun/SetupModuleAndDeck/SetupFixtureList.tsx b/app/src/organisms/Devices/ProtocolRun/SetupModuleAndDeck/SetupFixtureList.tsx index adf3a9575b1..97e4460aae1 100644 --- a/app/src/organisms/Devices/ProtocolRun/SetupModuleAndDeck/SetupFixtureList.tsx +++ b/app/src/organisms/Devices/ProtocolRun/SetupModuleAndDeck/SetupFixtureList.tsx @@ -168,7 +168,7 @@ export function FixtureListItem({ border={BORDERS.styleSolid} borderColor={COLORS.grey30} borderWidth="1px" - borderRadius={BORDERS.radiusSoftCorners} + borderRadius={BORDERS.borderRadius4} padding={SPACING.spacing16} backgroundColor={COLORS.white} > diff --git a/app/src/organisms/Devices/ProtocolRun/SetupModuleAndDeck/SetupModulesList.tsx b/app/src/organisms/Devices/ProtocolRun/SetupModuleAndDeck/SetupModulesList.tsx index 641a22680a8..ea05e8d4550 100644 --- a/app/src/organisms/Devices/ProtocolRun/SetupModuleAndDeck/SetupModulesList.tsx +++ b/app/src/organisms/Devices/ProtocolRun/SetupModuleAndDeck/SetupModulesList.tsx @@ -373,7 +373,7 @@ export function ModulesListItem({ border={BORDERS.styleSolid} borderColor={COLORS.grey30} borderWidth="1px" - borderRadius={BORDERS.radiusSoftCorners} + borderRadius={BORDERS.borderRadius4} padding={SPACING.spacing16} backgroundColor={COLORS.white} > diff --git a/app/src/organisms/Devices/RecentProtocolRuns.tsx b/app/src/organisms/Devices/RecentProtocolRuns.tsx index 558af301aaf..41b5b76877b 100644 --- a/app/src/organisms/Devices/RecentProtocolRuns.tsx +++ b/app/src/organisms/Devices/RecentProtocolRuns.tsx @@ -41,7 +41,7 @@ export function RecentProtocolRuns({ diff --git a/app/src/organisms/Devices/RobotSettings/UpdateBuildroot/RobotUpdateProgressModal.tsx b/app/src/organisms/Devices/RobotSettings/UpdateBuildroot/RobotUpdateProgressModal.tsx index bef8dce44b7..ca2a2cc770f 100644 --- a/app/src/organisms/Devices/RobotSettings/UpdateBuildroot/RobotUpdateProgressModal.tsx +++ b/app/src/organisms/Devices/RobotSettings/UpdateBuildroot/RobotUpdateProgressModal.tsx @@ -41,7 +41,7 @@ import type { RobotInitializationStatus } from '../../../../resources/health/hoo const UPDATE_PROGRESS_BAR_STYLE = css` margin-top: ${SPACING.spacing24}; margin-bottom: ${SPACING.spacing24}; - border-radius: ${BORDERS.borderRadiusSize3}; + border-radius: ${BORDERS.borderRadius12}; background: ${COLORS.grey30}; width: 17.12rem; ` diff --git a/app/src/organisms/Devices/RobotSettings/UpdateBuildroot/UpdateRobotModal.tsx b/app/src/organisms/Devices/RobotSettings/UpdateBuildroot/UpdateRobotModal.tsx index a659259e698..ceb3959f541 100644 --- a/app/src/organisms/Devices/RobotSettings/UpdateBuildroot/UpdateRobotModal.tsx +++ b/app/src/organisms/Devices/RobotSettings/UpdateBuildroot/UpdateRobotModal.tsx @@ -46,7 +46,7 @@ export const FOOTER_BUTTON_STYLE = css` text-transform: lowercase; padding-left: ${SPACING.spacing16}; padding-right: ${SPACING.spacing16}; - border-radius: ${BORDERS.borderRadiusSize1}; + border-radius: ${BORDERS.borderRadius4}; margin-top: ${SPACING.spacing16}; margin-bottom: ${SPACING.spacing16}; diff --git a/app/src/organisms/DropTipWizard/BeforeBeginning.tsx b/app/src/organisms/DropTipWizard/BeforeBeginning.tsx index 8fe2d7970cd..ba7eda1438a 100644 --- a/app/src/organisms/DropTipWizard/BeforeBeginning.tsx +++ b/app/src/organisms/DropTipWizard/BeforeBeginning.tsx @@ -187,7 +187,7 @@ export const BeforeBeginning = ( const UNSELECTED_OPTIONS_STYLE = css` background-color: ${COLORS.white}; border: 1px solid ${COLORS.grey30}; - border-radius: ${BORDERS.radiusSoftCorners}; + border-radius: ${BORDERS.borderRadius4}; height: 12.5625rem; width: 14.5625rem; cursor: pointer; @@ -205,7 +205,7 @@ const UNSELECTED_OPTIONS_STYLE = css` justify-content: ${JUSTIFY_FLEX_START}; background-color: ${COLORS.blue35}; border-width: 0; - border-radius: ${BORDERS.borderRadiusSize4}; + border-radius: ${BORDERS.borderRadius16}; padding: ${SPACING.spacing24}; height: 5.25rem; width: 57.8125rem; diff --git a/app/src/organisms/DropTipWizard/index.tsx b/app/src/organisms/DropTipWizard/index.tsx index 871ea158c0a..a8253dbbf8f 100644 --- a/app/src/organisms/DropTipWizard/index.tsx +++ b/app/src/organisms/DropTipWizard/index.tsx @@ -522,7 +522,7 @@ export const DropTipWizardComponent = ( top="16px" border={BORDERS.lineBorder} boxShadow={BORDERS.shadowSmall} - borderRadius={BORDERS.borderRadiusSize4} + borderRadius={BORDERS.borderRadius16} position={POSITION_ABSOLUTE} backgroundColor={COLORS.white} > diff --git a/app/src/organisms/FirmwareUpdateModal/UpdateInProgressModal.tsx b/app/src/organisms/FirmwareUpdateModal/UpdateInProgressModal.tsx index f674f39c379..8aa9eb8bef0 100644 --- a/app/src/organisms/FirmwareUpdateModal/UpdateInProgressModal.tsx +++ b/app/src/organisms/FirmwareUpdateModal/UpdateInProgressModal.tsx @@ -41,7 +41,7 @@ export function UpdateInProgressModal( height="17.25rem" width="100%" backgroundColor={COLORS.grey35} - borderRadius={BORDERS.borderRadiusSize3} + borderRadius={BORDERS.borderRadius12} flexDirection={DIRECTION_COLUMN} padding={SPACING.spacing32} justifyContent={ALIGN_CENTER} diff --git a/app/src/organisms/FirmwareUpdateModal/UpdateResultsModal.tsx b/app/src/organisms/FirmwareUpdateModal/UpdateResultsModal.tsx index fa2d26dc9ec..0a16da311e3 100644 --- a/app/src/organisms/FirmwareUpdateModal/UpdateResultsModal.tsx +++ b/app/src/organisms/FirmwareUpdateModal/UpdateResultsModal.tsx @@ -76,7 +76,7 @@ export function UpdateResultsModal( height="11.5rem" width="100%" backgroundColor={COLORS.green35} - borderRadius={BORDERS.borderRadiusSize3} + borderRadius={BORDERS.borderRadius12} flexDirection={DIRECTION_COLUMN} color={COLORS.grey60} padding={SPACING.spacing24} diff --git a/app/src/organisms/FirmwareUpdateModal/index.tsx b/app/src/organisms/FirmwareUpdateModal/index.tsx index 0dfe6b1e5f0..ceaf940ea90 100644 --- a/app/src/organisms/FirmwareUpdateModal/index.tsx +++ b/app/src/organisms/FirmwareUpdateModal/index.tsx @@ -56,7 +56,7 @@ const MODAL_STYLE = css` } ` const OUTER_STYLES = css` - border-radius: ${BORDERS.borderRadiusSize4}; + border-radius: ${BORDERS.borderRadius16}; background: ${COLORS.grey30}; width: 13.374rem; ` diff --git a/app/src/organisms/GripperWizardFlows/index.tsx b/app/src/organisms/GripperWizardFlows/index.tsx index 8905b8ada7a..ab1032064f5 100644 --- a/app/src/organisms/GripperWizardFlows/index.tsx +++ b/app/src/organisms/GripperWizardFlows/index.tsx @@ -357,7 +357,7 @@ export const GripperWizard = ( top="16px" border={BORDERS.lineBorder} boxShadow={BORDERS.shadowSmall} - borderRadius={BORDERS.borderRadiusSize4} + borderRadius={BORDERS.borderRadius16} position={POSITION_ABSOLUTE} backgroundColor={COLORS.white} > diff --git a/app/src/organisms/InstrumentInfo/index.tsx b/app/src/organisms/InstrumentInfo/index.tsx index fe341e3c37f..4b15ff0e15a 100644 --- a/app/src/organisms/InstrumentInfo/index.tsx +++ b/app/src/organisms/InstrumentInfo/index.tsx @@ -184,7 +184,7 @@ interface InfoItemProps extends StyleProps { function InfoItem(props: InfoItemProps): JSX.Element { return ( ` flex-direction: ${DIRECTION_COLUMN}; align-items: ${ALIGN_FLEX_START}; padding: ${SPACING.spacing24}; - border-radius: ${BORDERS.borderRadiusSize3}; + border-radius: ${BORDERS.borderRadius12}; background-color: ${({ isAttached }) => isAttached ? COLORS.green35 : COLORS.grey35}; &:active { diff --git a/app/src/organisms/InstrumentMountItem/ProtocolInstrumentMountItem.tsx b/app/src/organisms/InstrumentMountItem/ProtocolInstrumentMountItem.tsx index 6c614404866..246b6e26427 100644 --- a/app/src/organisms/InstrumentMountItem/ProtocolInstrumentMountItem.tsx +++ b/app/src/organisms/InstrumentMountItem/ProtocolInstrumentMountItem.tsx @@ -37,7 +37,7 @@ export const MountItem = styled.div<{ isReady: boolean }>` flex-direction: ${DIRECTION_COLUMN}; align-items: ${ALIGN_FLEX_START}; padding: ${SPACING.spacing16} ${SPACING.spacing24}; - border-radius: ${BORDERS.borderRadiusSize3}; + border-radius: ${BORDERS.borderRadius12}; background-color: ${({ isReady }) => isReady ? COLORS.green35 : COLORS.yellow35}; &:active { diff --git a/app/src/organisms/InterventionModal/MoveLabwareInterventionContent.tsx b/app/src/organisms/InterventionModal/MoveLabwareInterventionContent.tsx index 56479bb7e75..b72fa7eacc5 100644 --- a/app/src/organisms/InterventionModal/MoveLabwareInterventionContent.tsx +++ b/app/src/organisms/InterventionModal/MoveLabwareInterventionContent.tsx @@ -55,10 +55,10 @@ const LABWARE_DESCRIPTION_STYLE = css` grid-gap: ${SPACING.spacing8}; padding: ${SPACING.spacing16}; background-color: ${COLORS.grey20}; - border-radius: ${BORDERS.radiusSoftCorners}; + border-radius: ${BORDERS.borderRadius4}; @media ${RESPONSIVENESS.touchscreenMediaQuerySpecs} { background-color: ${COLORS.grey35}; - border-radius: ${BORDERS.borderRadiusSize3}; + border-radius: ${BORDERS.borderRadius12}; } ` diff --git a/app/src/organisms/InterventionModal/PauseInterventionContent.tsx b/app/src/organisms/InterventionModal/PauseInterventionContent.tsx index e5e35426903..d808fce6d7b 100644 --- a/app/src/organisms/InterventionModal/PauseInterventionContent.tsx +++ b/app/src/organisms/InterventionModal/PauseInterventionContent.tsx @@ -48,13 +48,13 @@ export function PauseInterventionContent({ const PAUSE_HEADER_STYLE = css` align-items: ${ALIGN_CENTER}; background-color: ${COLORS.grey10}; - border-radius: ${BORDERS.radiusSoftCorners}; + border-radius: ${BORDERS.borderRadius4}; grid-gap: ${SPACING.spacing6}; padding: ${SPACING.spacing16}; @media ${RESPONSIVENESS.touchscreenMediaQuerySpecs} { align-self: ${ALIGN_CENTER}; background-color: ${COLORS.grey35}; - border-radius: ${BORDERS.borderRadiusSize3}; + border-radius: ${BORDERS.borderRadius12}; grid-gap: ${SPACING.spacing32}; padding: ${SPACING.spacing24}; min-width: 36.5rem; diff --git a/app/src/organisms/InterventionModal/index.tsx b/app/src/organisms/InterventionModal/index.tsx index c97c3a591f4..b9a6a364b95 100644 --- a/app/src/organisms/InterventionModal/index.tsx +++ b/app/src/organisms/InterventionModal/index.tsx @@ -59,7 +59,7 @@ const MODAL_STYLE = { maxHeight: '100%', width: '47rem', border: `6px ${BORDERS.styleSolid} ${COLORS.blue50}`, - borderRadius: BORDERS.radiusSoftCorners, + borderRadius: BORDERS.borderRadius4, boxShadow: BORDERS.smallDropShadow, } as const @@ -79,8 +79,8 @@ const CONTENT_STYLE = { alignItems: ALIGN_FLEX_START, gridGap: SPACING.spacing24, padding: `${SPACING.spacing32}`, - borderRadius: `0px 0px ${String(BORDERS.radiusSoftCorners)} ${String( - BORDERS.radiusSoftCorners + borderRadius: `0px 0px ${String(BORDERS.borderRadius4)} ${String( + BORDERS.borderRadius4 )}`, } as const diff --git a/app/src/organisms/LabwareOffsetTabs/index.tsx b/app/src/organisms/LabwareOffsetTabs/index.tsx index beb72102901..f133ad52beb 100644 --- a/app/src/organisms/LabwareOffsetTabs/index.tsx +++ b/app/src/organisms/LabwareOffsetTabs/index.tsx @@ -68,9 +68,9 @@ export function LabwareOffsetTabs({ border={BORDERS.lineBorder} // remove left upper corner border radius when first tab is active borderRadius={`${ - currentTab === 'table' ? '0' : BORDERS.radiusSoftCorners - } ${BORDERS.radiusSoftCorners} ${BORDERS.radiusSoftCorners} ${ - BORDERS.radiusSoftCorners + currentTab === 'table' ? '0' : BORDERS.borderRadius4 + } ${BORDERS.borderRadius4} ${BORDERS.borderRadius4} ${ + BORDERS.borderRadius4 }`} paddingX={SPACING.spacing16} > diff --git a/app/src/organisms/LabwarePositionCheck/FatalErrorModal.tsx b/app/src/organisms/LabwarePositionCheck/FatalErrorModal.tsx index d8be65e2051..110b7430799 100644 --- a/app/src/organisms/LabwarePositionCheck/FatalErrorModal.tsx +++ b/app/src/organisms/LabwarePositionCheck/FatalErrorModal.tsx @@ -102,7 +102,7 @@ const ErrorTextArea = styled.textarea` width: 30rem; background-color: #f8f8f8; border: ${BORDERS.lineBorder}; - border-radius: ${BORDERS.radiusSoftCorners}; + border-radius: ${BORDERS.borderRadius4}; padding: ${SPACING.spacing8}; margin: ${SPACING.spacing16} 0; font-size: ${TYPOGRAPHY.fontSizeCaption}; diff --git a/app/src/organisms/LabwarePositionCheck/LiveOffsetValue.tsx b/app/src/organisms/LabwarePositionCheck/LiveOffsetValue.tsx index 3676e0837a7..d2f994af258 100644 --- a/app/src/organisms/LabwarePositionCheck/LiveOffsetValue.tsx +++ b/app/src/organisms/LabwarePositionCheck/LiveOffsetValue.tsx @@ -48,7 +48,7 @@ export function LiveOffsetValue(props: OffsetVectorProps): JSX.Element { diff --git a/app/src/organisms/LabwarePositionCheck/ResultsSummary.tsx b/app/src/organisms/LabwarePositionCheck/ResultsSummary.tsx index 6855b185870..464970c9166 100644 --- a/app/src/organisms/LabwarePositionCheck/ResultsSummary.tsx +++ b/app/src/organisms/LabwarePositionCheck/ResultsSummary.tsx @@ -388,13 +388,13 @@ const TerseTable = styled('table')` margin: ${SPACING.spacing16} 0; text-align: left; tr td:first-child { - border-top-left-radius: ${BORDERS.borderRadiusSize3}; - border-bottom-left-radius: ${BORDERS.borderRadiusSize3}; + border-top-left-radius: ${BORDERS.borderRadius12}; + border-bottom-left-radius: ${BORDERS.borderRadius12}; padding-left: ${SPACING.spacing12}; } tr td:last-child { - border-top-right-radius: ${BORDERS.borderRadiusSize3}; - border-bottom-right-radius: ${BORDERS.borderRadiusSize3}; + border-top-right-radius: ${BORDERS.borderRadius12}; + border-bottom-right-radius: ${BORDERS.borderRadius12}; padding-right: ${SPACING.spacing12}; } ` diff --git a/app/src/organisms/ModuleCard/TestShakeSlideout.tsx b/app/src/organisms/ModuleCard/TestShakeSlideout.tsx index 08d81682e32..55a2d3de4e5 100644 --- a/app/src/organisms/ModuleCard/TestShakeSlideout.tsx +++ b/app/src/organisms/ModuleCard/TestShakeSlideout.tsx @@ -168,7 +168,7 @@ export const TestShakeSlideout = ( ) : null} { return ( diff --git a/app/src/organisms/NetworkSettings/ConnectingNetwork.tsx b/app/src/organisms/NetworkSettings/ConnectingNetwork.tsx index b376826b2aa..5a3e77ad2c6 100644 --- a/app/src/organisms/NetworkSettings/ConnectingNetwork.tsx +++ b/app/src/organisms/NetworkSettings/ConnectingNetwork.tsx @@ -28,7 +28,7 @@ export function ConnectingNetwork({ backgroundColor={COLORS.grey35} flex="1" justifyContent={JUSTIFY_CENTER} - borderRadius={BORDERS.borderRadiusSize3} + borderRadius={BORDERS.borderRadius12} > diff --git a/app/src/organisms/NetworkSettings/DisplayWifiList.tsx b/app/src/organisms/NetworkSettings/DisplayWifiList.tsx index 1ccb4729935..8105f77c940 100644 --- a/app/src/organisms/NetworkSettings/DisplayWifiList.tsx +++ b/app/src/organisms/NetworkSettings/DisplayWifiList.tsx @@ -33,7 +33,7 @@ const NETWORK_ROW_STYLE = css` background-color: ${COLORS.grey35}; margin-bottom: ${SPACING.spacing8}; - border-radius: ${BORDERS.borderRadiusSize4}; + border-radius: ${BORDERS.borderRadius16}; &:hover { border: none; @@ -107,7 +107,7 @@ export function DisplayWifiList({ onClick={handleJoinAnotherNetwork} height="5rem" backgroundColor={COLORS.grey35} - borderRadius={BORDERS.borderRadiusSize4} + borderRadius={BORDERS.borderRadius16} color={COLORS.black90} css={NETWORK_ROW_STYLE} padding={`${SPACING.spacing20} ${SPACING.spacing32}`} diff --git a/app/src/organisms/NetworkSettings/FailedToConnect.tsx b/app/src/organisms/NetworkSettings/FailedToConnect.tsx index a220b4eaecc..b6c0a628bc8 100644 --- a/app/src/organisms/NetworkSettings/FailedToConnect.tsx +++ b/app/src/organisms/NetworkSettings/FailedToConnect.tsx @@ -41,7 +41,7 @@ export function FailedToConnect({ flex="1" backgroundColor={COLORS.red35} justifyContent={JUSTIFY_CENTER} - borderRadius={BORDERS.borderRadiusSize3} + borderRadius={BORDERS.borderRadius12} > diff --git a/app/src/organisms/OnDeviceDisplay/ProtocolDetails/ProtocolDetailsSkeleton.tsx b/app/src/organisms/OnDeviceDisplay/ProtocolDetails/ProtocolDetailsSkeleton.tsx index d1693df1557..aa241725f18 100644 --- a/app/src/organisms/OnDeviceDisplay/ProtocolDetails/ProtocolDetailsSkeleton.tsx +++ b/app/src/organisms/OnDeviceDisplay/ProtocolDetails/ProtocolDetailsSkeleton.tsx @@ -10,7 +10,7 @@ export function ProtocolDetailsHeaderChipSkeleton(): JSX.Element { width="12.17875rem" height="2.75rem" backgroundSize="99rem" - borderRadius={BORDERS.borderRadiusSize3} + borderRadius={BORDERS.borderRadius12} /> ) } @@ -21,7 +21,7 @@ export function ProcotolDetailsHeaderTitleSkeleton(): JSX.Element { width="42rem" height="3rem" backgroundSize="99rem" - borderRadius={BORDERS.borderRadiusSize3} + borderRadius={BORDERS.borderRadius12} /> ) } @@ -34,28 +34,28 @@ export function ProtocolDetailsSectionContentSkeleton(): JSX.Element { width="12rem" height="1.75rem" backgroundSize="99rem" - borderRadius={BORDERS.borderRadiusSize5} + borderRadius={BORDERS.borderRadius40} /> @@ -63,7 +63,7 @@ export function ProtocolDetailsSectionContentSkeleton(): JSX.Element { width="18rem" height="2.25rem" backgroundSize="99rem" - borderRadius={BORDERS.borderRadiusSize3} + borderRadius={BORDERS.borderRadius12} /> diff --git a/app/src/organisms/OnDeviceDisplay/ProtocolSetup/ProtocolSetupSkeleton.tsx b/app/src/organisms/OnDeviceDisplay/ProtocolSetup/ProtocolSetupSkeleton.tsx index cb0b39160dc..23a51d26439 100644 --- a/app/src/organisms/OnDeviceDisplay/ProtocolSetup/ProtocolSetupSkeleton.tsx +++ b/app/src/organisms/OnDeviceDisplay/ProtocolSetup/ProtocolSetupSkeleton.tsx @@ -11,13 +11,13 @@ export function ProtocolSetupTitleSkeleton(): JSX.Element { height="2.25rem" width="11.937rem" backgroundSize="99rem" - borderRadius={BORDERS.borderRadiusSize3} + borderRadius={BORDERS.borderRadius12} /> ) @@ -29,7 +29,7 @@ const SetupSkeleton = (): JSX.Element => { height="5.5rem" width="100%" backgroundSize="99rem" - borderRadius={BORDERS.borderRadiusSize3} + borderRadius={BORDERS.borderRadius12} /> ) } diff --git a/app/src/organisms/OnDeviceDisplay/RobotDashboard/EmptyRecentRun.tsx b/app/src/organisms/OnDeviceDisplay/RobotDashboard/EmptyRecentRun.tsx index 8f07093e973..94531c26476 100644 --- a/app/src/organisms/OnDeviceDisplay/RobotDashboard/EmptyRecentRun.tsx +++ b/app/src/organisms/OnDeviceDisplay/RobotDashboard/EmptyRecentRun.tsx @@ -25,7 +25,7 @@ export function EmptyRecentRun(): JSX.Element { flexDirection={DIRECTION_COLUMN} height="27.25rem" justifyContent={JUSTIFY_CENTER} - borderRadius={BORDERS.borderRadiusSize3} + borderRadius={BORDERS.borderRadius12} > ) : ( diff --git a/app/src/organisms/OnDeviceDisplay/RobotDashboard/ServerInitializing.tsx b/app/src/organisms/OnDeviceDisplay/RobotDashboard/ServerInitializing.tsx index 4f66f4f756e..0d3f8cabf61 100644 --- a/app/src/organisms/OnDeviceDisplay/RobotDashboard/ServerInitializing.tsx +++ b/app/src/organisms/OnDeviceDisplay/RobotDashboard/ServerInitializing.tsx @@ -24,7 +24,7 @@ export function ServerInitializing(): JSX.Element { flexDirection={DIRECTION_COLUMN} height="27.25rem" justifyContent={JUSTIFY_CENTER} - borderRadius={BORDERS.borderRadiusSize3} + borderRadius={BORDERS.borderRadius12} gridGap={SPACING.spacing32} > diff --git a/app/src/organisms/OnDeviceDisplay/RunningProtocol/CancelingRunModal.tsx b/app/src/organisms/OnDeviceDisplay/RunningProtocol/CancelingRunModal.tsx index ee164472ef0..d424bb96b1a 100644 --- a/app/src/organisms/OnDeviceDisplay/RunningProtocol/CancelingRunModal.tsx +++ b/app/src/organisms/OnDeviceDisplay/RunningProtocol/CancelingRunModal.tsx @@ -25,7 +25,7 @@ export function CancelingRunModal(): JSX.Element { justifyContent={JUSTIFY_CENTER} alignItems={ALIGN_CENTER} backgroundColor={COLORS.grey35} - borderRadius={BORDERS.borderRadiusSize3} + borderRadius={BORDERS.borderRadius12} width="41.625rem" height="17.25rem" gridGap={SPACING.spacing24} diff --git a/app/src/organisms/OnDeviceDisplay/RunningProtocol/CurrentRunningProtocolCommand.tsx b/app/src/organisms/OnDeviceDisplay/RunningProtocol/CurrentRunningProtocolCommand.tsx index 21b082a5f99..14a25e0d3f5 100644 --- a/app/src/organisms/OnDeviceDisplay/RunningProtocol/CurrentRunningProtocolCommand.tsx +++ b/app/src/organisms/OnDeviceDisplay/RunningProtocol/CurrentRunningProtocolCommand.tsx @@ -227,7 +227,7 @@ export function CurrentRunningProtocolCommand({ diff --git a/app/src/organisms/OnDeviceDisplay/RunningProtocol/RunFailedModal.tsx b/app/src/organisms/OnDeviceDisplay/RunningProtocol/RunFailedModal.tsx index 15a32b6256f..d90ca63de6b 100644 --- a/app/src/organisms/OnDeviceDisplay/RunningProtocol/RunFailedModal.tsx +++ b/app/src/organisms/OnDeviceDisplay/RunningProtocol/RunFailedModal.tsx @@ -90,7 +90,7 @@ export function RunFailedModal({ gridGap={SPACING.spacing8} maxHeight="11rem" backgroundColor={COLORS.grey35} - borderRadius={BORDERS.borderRadiusSize3} + borderRadius={BORDERS.borderRadius12} padding={`${SPACING.spacing16} ${SPACING.spacing20}`} > diff --git a/app/src/organisms/OnDeviceDisplay/RunningProtocol/RunningProtocolCommandList.tsx b/app/src/organisms/OnDeviceDisplay/RunningProtocol/RunningProtocolCommandList.tsx index 802de64035a..a19fabcb8a8 100644 --- a/app/src/organisms/OnDeviceDisplay/RunningProtocol/RunningProtocolCommandList.tsx +++ b/app/src/organisms/OnDeviceDisplay/RunningProtocol/RunningProtocolCommandList.tsx @@ -232,7 +232,7 @@ export function RunningProtocolCommandList({ fontSize="1.375rem" lineHeight="1.75rem" fontWeight={TYPOGRAPHY.fontWeightRegular} - borderRadius={BORDERS.borderRadiusSize2} + borderRadius={BORDERS.borderRadius8} gridGap="0.875rem" > diff --git a/app/src/organisms/OpenDoorAlertModal/index.tsx b/app/src/organisms/OpenDoorAlertModal/index.tsx index abdb21ba00f..4a4d141911b 100644 --- a/app/src/organisms/OpenDoorAlertModal/index.tsx +++ b/app/src/organisms/OpenDoorAlertModal/index.tsx @@ -22,7 +22,7 @@ export function OpenDoorAlertModal(): JSX.Element { { @@ -632,11 +632,9 @@ export function ProtocolDetails( backgroundColor={COLORS.white} // remove left upper corner border radius when first tab is active borderRadius={`${ - currentTab === 'robot_config' - ? '0' - : BORDERS.radiusSoftCorners - } ${BORDERS.radiusSoftCorners} ${BORDERS.radiusSoftCorners} ${ - BORDERS.radiusSoftCorners + currentTab === 'robot_config' ? '0' : BORDERS.borderRadius4 + } ${BORDERS.borderRadius4} ${BORDERS.borderRadius4} ${ + BORDERS.borderRadius4 }`} padding={`${SPACING.spacing16} ${SPACING.spacing16} 0 ${SPACING.spacing16}`} > diff --git a/app/src/organisms/ProtocolSetupLabware/index.tsx b/app/src/organisms/ProtocolSetupLabware/index.tsx index 6e0ef6d1053..f7bc4ec7469 100644 --- a/app/src/organisms/ProtocolSetupLabware/index.tsx +++ b/app/src/organisms/ProtocolSetupLabware/index.tsx @@ -414,7 +414,7 @@ function LabwareLatch({ diff --git a/app/src/organisms/ProtocolSetupLiquids/LiquidDetails.tsx b/app/src/organisms/ProtocolSetupLiquids/LiquidDetails.tsx index 15185a46308..19f1b13f153 100644 --- a/app/src/organisms/ProtocolSetupLiquids/LiquidDetails.tsx +++ b/app/src/organisms/ProtocolSetupLiquids/LiquidDetails.tsx @@ -23,7 +23,7 @@ import type { LabwareByLiquidId, ParsedLiquid } from '@opentrons/api-client' const Table = styled('table')` table-layout: ${SPACING.spacingAuto}; width: 100%; - border-spacing: 0 ${BORDERS.borderRadiusSize2}; + border-spacing: 0 ${BORDERS.borderRadius8}; text-align: ${TYPOGRAPHY.textAlignLeft}; color: ${COLORS.grey60}; ` @@ -46,13 +46,13 @@ const TableDatum = styled('td')` white-space: break-spaces; text-overflow: ${WRAP}; &:first-child { - border-top-left-radius: ${BORDERS.borderRadiusSize3}; - border-bottom-left-radius: ${BORDERS.borderRadiusSize3}; + border-top-left-radius: ${BORDERS.borderRadius12}; + border-bottom-left-radius: ${BORDERS.borderRadius12}; width: 20%; } &:last-child { - border-top-right-radius: ${BORDERS.borderRadiusSize3}; - border-bottom-right-radius: ${BORDERS.borderRadiusSize3}; + border-top-right-radius: ${BORDERS.borderRadius12}; + border-bottom-right-radius: ${BORDERS.borderRadius12}; } ` diff --git a/app/src/organisms/ProtocolSetupLiquids/index.tsx b/app/src/organisms/ProtocolSetupLiquids/index.tsx index 69b722795a8..a8d8d6ba47e 100644 --- a/app/src/organisms/ProtocolSetupLiquids/index.tsx +++ b/app/src/organisms/ProtocolSetupLiquids/index.tsx @@ -78,7 +78,7 @@ export function LiquidsList(props: LiquidsListProps): JSX.Element { return ( {t('setup_instructions_description')} diff --git a/app/src/organisms/ProtocolsLanding/ProtocolCard.tsx b/app/src/organisms/ProtocolsLanding/ProtocolCard.tsx index ab37ec6c37f..79893453b3a 100644 --- a/app/src/organisms/ProtocolsLanding/ProtocolCard.tsx +++ b/app/src/organisms/ProtocolsLanding/ProtocolCard.tsx @@ -94,7 +94,7 @@ export function ProtocolCard(props: ProtocolCardProps): JSX.Element | null { return ( ` padding: ${SPACING.spacing16} ${SPACING.spacing24}; - border-radius: ${BORDERS.borderRadiusSize4}; + border-radius: ${BORDERS.borderRadius16}; color: ${({ isSelected }) => isSelected === true ? COLORS.white : COLORS.black90}; background: ${({ isSelected }) => diff --git a/app/src/organisms/RobotSettingsDashboard/NetworkSettings/EthernetConnectionDetails.tsx b/app/src/organisms/RobotSettingsDashboard/NetworkSettings/EthernetConnectionDetails.tsx index fcae6ce7937..e558258ad28 100644 --- a/app/src/organisms/RobotSettingsDashboard/NetworkSettings/EthernetConnectionDetails.tsx +++ b/app/src/organisms/RobotSettingsDashboard/NetworkSettings/EthernetConnectionDetails.tsx @@ -25,7 +25,7 @@ const STRETCH_LIST_STYLE = css` width: 100%; padding: ${SPACING.spacing16}; background-color: ${COLORS.grey35}; - border-radius: ${BORDERS.borderRadiusSize3}; + border-radius: ${BORDERS.borderRadius12}; ` interface EthernetConnectionDetailsProps { diff --git a/app/src/organisms/RobotSettingsDashboard/NetworkSettings/NetworkDetailsModal.tsx b/app/src/organisms/RobotSettingsDashboard/NetworkSettings/NetworkDetailsModal.tsx index fd515306a4d..d9dc111b9c3 100644 --- a/app/src/organisms/RobotSettingsDashboard/NetworkSettings/NetworkDetailsModal.tsx +++ b/app/src/organisms/RobotSettingsDashboard/NetworkSettings/NetworkDetailsModal.tsx @@ -78,7 +78,7 @@ function ListItem({ itemName, itemValue }: ListItemProps): JSX.Element { padding={`${SPACING.spacing16} ${SPACING.spacing24}`} backgroundColor={COLORS.grey40} justifyContent={JUSTIFY_SPACE_BETWEEN} - borderRadius={BORDERS.borderRadiusSize3} + borderRadius={BORDERS.borderRadius12} > {itemName} diff --git a/app/src/organisms/RobotSettingsDashboard/NetworkSettings/WifiConnectionDetails.tsx b/app/src/organisms/RobotSettingsDashboard/NetworkSettings/WifiConnectionDetails.tsx index 82423db475e..852f0f65862 100644 --- a/app/src/organisms/RobotSettingsDashboard/NetworkSettings/WifiConnectionDetails.tsx +++ b/app/src/organisms/RobotSettingsDashboard/NetworkSettings/WifiConnectionDetails.tsx @@ -88,7 +88,7 @@ export function WifiConnectionDetails({ width="100%" padding={SPACING.spacing24} backgroundColor={COLORS.green35} - borderRadius={BORDERS.borderRadiusSize3} + borderRadius={BORDERS.borderRadius12} onClick={() => setShowNetworkDetailModal(true)} alignItems={ALIGN_CENTER} > diff --git a/app/src/organisms/RobotSettingsDashboard/NetworkSettings/index.tsx b/app/src/organisms/RobotSettingsDashboard/NetworkSettings/index.tsx index 08f61fbfcb8..3aadf02256d 100644 --- a/app/src/organisms/RobotSettingsDashboard/NetworkSettings/index.tsx +++ b/app/src/organisms/RobotSettingsDashboard/NetworkSettings/index.tsx @@ -113,7 +113,7 @@ function NetworkSettingButton({ paddingX={SPACING.spacing24} paddingY={SPACING.spacing20} backgroundColor={backgroundColor} - borderRadius={BORDERS.borderRadiusSize3} + borderRadius={BORDERS.borderRadius12} css={PUSHED_STATE_STYLE} onClick={onClick} > diff --git a/app/src/organisms/RobotSettingsDashboard/RobotSystemVersion.tsx b/app/src/organisms/RobotSettingsDashboard/RobotSystemVersion.tsx index 50d69fc7ffc..c0ee23d150b 100644 --- a/app/src/organisms/RobotSettingsDashboard/RobotSystemVersion.tsx +++ b/app/src/organisms/RobotSettingsDashboard/RobotSystemVersion.tsx @@ -83,7 +83,7 @@ export function RobotSystemVersion({ flexDirection={DIRECTION_ROW} padding={`${SPACING.spacing16} ${SPACING.spacing24}`} justifyContent={JUSTIFY_SPACE_BETWEEN} - borderRadius={BORDERS.borderRadiusSize3} + borderRadius={BORDERS.borderRadius12} > props.isActive ? COLORS.purple50 : COLORS.purple35}; ` diff --git a/app/src/organisms/RobotSettingsDashboard/TouchscreenBrightness.tsx b/app/src/organisms/RobotSettingsDashboard/TouchscreenBrightness.tsx index f16f2273a33..1ce6a75ce83 100644 --- a/app/src/organisms/RobotSettingsDashboard/TouchscreenBrightness.tsx +++ b/app/src/organisms/RobotSettingsDashboard/TouchscreenBrightness.tsx @@ -35,7 +35,7 @@ interface BrightnessTileProps { const BrightnessTile = styled(Box)` width: 100%; height: 8.75rem; - border-radius: ${BORDERS.borderRadiusSize2}; + border-radius: ${BORDERS.borderRadius8}; background: ${(props: BrightnessTileProps) => props.isActive ? COLORS.blue50 : COLORS.blue35}; ` diff --git a/app/src/organisms/RobotSettingsDashboard/UpdateChannel.tsx b/app/src/organisms/RobotSettingsDashboard/UpdateChannel.tsx index 36b6628f697..180486f76a8 100644 --- a/app/src/organisms/RobotSettingsDashboard/UpdateChannel.tsx +++ b/app/src/organisms/RobotSettingsDashboard/UpdateChannel.tsx @@ -33,7 +33,7 @@ const SettingButton = styled.input` const SettingButtonLabel = styled.label` padding: ${SPACING.spacing24}; - border-radius: ${BORDERS.borderRadiusSize4}; + border-radius: ${BORDERS.borderRadius16}; cursor: pointer; background: ${({ isSelected }) => isSelected === true ? COLORS.blue50 : COLORS.blue35}; diff --git a/app/src/organisms/RunPreview/index.tsx b/app/src/organisms/RunPreview/index.tsx index 1a27fea26d2..b7dd195cc96 100644 --- a/app/src/organisms/RunPreview/index.tsx +++ b/app/src/organisms/RunPreview/index.tsx @@ -117,7 +117,7 @@ export const RunPreviewComponent = ( index === jumpedIndex ? '#F5E3FF' : backgroundColor } color={COLORS.black90} - borderRadius={BORDERS.radiusSoftCorners} + borderRadius={BORDERS.borderRadius4} padding={SPACING.spacing8} css={css` transition: background-color ${COLOR_FADE_MS}ms ease-out, diff --git a/app/src/organisms/RunProgressMeter/index.tsx b/app/src/organisms/RunProgressMeter/index.tsx index fed3d864f18..0b5d2ae5424 100644 --- a/app/src/organisms/RunProgressMeter/index.tsx +++ b/app/src/organisms/RunProgressMeter/index.tsx @@ -259,14 +259,14 @@ export function RunProgressMeter(props: RunProgressMeterProps): JSX.Element { outerStyles={css` height: 0.375rem; background-color: ${COLORS.grey30}; - border-radius: ${BORDERS.radiusSoftCorners}; + border-radius: ${BORDERS.borderRadius4}; position: relative; overflow: initial; `} innerStyles={css` height: 0.375rem; background-color: ${COLORS.grey60}; - border-radius: ${BORDERS.radiusSoftCorners}; + border-radius: ${BORDERS.borderRadius4}; `} > @@ -366,7 +366,7 @@ function Task({ border={ isActiveTask && !isTaskOpen ? BORDERS.activeLineBorder : undefined } - borderRadius={BORDERS.radiusSoftCorners} + borderRadius={BORDERS.borderRadius4} width="100%" > diff --git a/app/src/organisms/UpdateRobotSoftware/CompleteUpdateSoftware.tsx b/app/src/organisms/UpdateRobotSoftware/CompleteUpdateSoftware.tsx index 631551adde6..0f083ea5f26 100644 --- a/app/src/organisms/UpdateRobotSoftware/CompleteUpdateSoftware.tsx +++ b/app/src/organisms/UpdateRobotSoftware/CompleteUpdateSoftware.tsx @@ -33,7 +33,7 @@ export function CompleteUpdateSoftware({ gridGap={SPACING.spacing40} alignItems={ALIGN_CENTER} justifyContent={JUSTIFY_CENTER} - borderRadius={BORDERS.borderRadiusSize3} + borderRadius={BORDERS.borderRadius12} > diff --git a/app/src/pages/ConnectViaEthernet/DisplayConnectionStatus.tsx b/app/src/pages/ConnectViaEthernet/DisplayConnectionStatus.tsx index f416a65d141..2791d9af36e 100644 --- a/app/src/pages/ConnectViaEthernet/DisplayConnectionStatus.tsx +++ b/app/src/pages/ConnectViaEthernet/DisplayConnectionStatus.tsx @@ -35,7 +35,7 @@ export function DisplayConnectionStatus({ {protocolRunDetailsContent} diff --git a/app/src/pages/Devices/RobotSettings/index.tsx b/app/src/pages/Devices/RobotSettings/index.tsx index ea2e8cabaaa..f9422adfcd4 100644 --- a/app/src/pages/Devices/RobotSettings/index.tsx +++ b/app/src/pages/Devices/RobotSettings/index.tsx @@ -107,7 +107,7 @@ export function RobotSettings(): JSX.Element | null { { {t('nothing_here_yet')} handleProtocolClick(longpress, protocol.id)} diff --git a/app/src/pages/ProtocolDetails/EmptySection.tsx b/app/src/pages/ProtocolDetails/EmptySection.tsx index 6386ad731e4..fca971be264 100644 --- a/app/src/pages/ProtocolDetails/EmptySection.tsx +++ b/app/src/pages/ProtocolDetails/EmptySection.tsx @@ -24,7 +24,7 @@ export const EmptySection = (props: EmptySectionProps): JSX.Element => { return ( { alignItems={TYPOGRAPHY.textAlignCenter} > { { {props.isOn ? t('on') : t('off')} diff --git a/components/src/atoms/buttons/AlertPrimaryButton.tsx b/components/src/atoms/buttons/AlertPrimaryButton.tsx index a31ce1ff021..2c87987f76c 100644 --- a/components/src/atoms/buttons/AlertPrimaryButton.tsx +++ b/components/src/atoms/buttons/AlertPrimaryButton.tsx @@ -1,11 +1,11 @@ import styled from 'styled-components' -import { BORDERS, TYPOGRAPHY, SPACING } from '../../ui-style-constants' -import { COLORS } from '../../helix-design-system' +import { TYPOGRAPHY, SPACING } from '../../ui-style-constants' +import { BORDERS, COLORS } from '../../helix-design-system' import { NewAlertPrimaryBtn, styleProps } from '../../primitives' export const AlertPrimaryButton = styled(NewAlertPrimaryBtn)` background-color: ${COLORS.red50}; - border-radius: ${BORDERS.radiusSoftCorners}; + border-radius: ${BORDERS.borderRadius4}; padding-left: ${SPACING.spacing16}; padding-right: ${SPACING.spacing16}; text-transform: ${TYPOGRAPHY.textTransformNone}; diff --git a/components/src/atoms/buttons/PrimaryButton.tsx b/components/src/atoms/buttons/PrimaryButton.tsx index 8005b021930..e4075770b9d 100644 --- a/components/src/atoms/buttons/PrimaryButton.tsx +++ b/components/src/atoms/buttons/PrimaryButton.tsx @@ -1,11 +1,11 @@ import styled from 'styled-components' -import { BORDERS, TYPOGRAPHY, SPACING } from '../../ui-style-constants' -import { COLORS } from '../../helix-design-system' +import { TYPOGRAPHY, SPACING } from '../../ui-style-constants' +import { BORDERS, COLORS } from '../../helix-design-system' import { NewPrimaryBtn, styleProps } from '../../primitives' export const PrimaryButton = styled(NewPrimaryBtn)` background-color: ${COLORS.blue50}; - border-radius: ${BORDERS.radiusSoftCorners}; + border-radius: ${BORDERS.borderRadius4}; box-shadow: none; padding-left: ${SPACING.spacing16}; padding-right: ${SPACING.spacing16}; diff --git a/components/src/atoms/buttons/SecondaryButton.tsx b/components/src/atoms/buttons/SecondaryButton.tsx index 00e456ba100..c5f2a9dbcaf 100644 --- a/components/src/atoms/buttons/SecondaryButton.tsx +++ b/components/src/atoms/buttons/SecondaryButton.tsx @@ -1,7 +1,9 @@ import styled from 'styled-components' -import { BORDERS, TYPOGRAPHY, SPACING } from '../../ui-style-constants' + +import { TYPOGRAPHY, SPACING } from '../../ui-style-constants' import { isntStyleProp, styleProps } from '../../primitives' -import { COLORS } from '../../helix-design-system' +import { BORDERS, COLORS } from '../../helix-design-system' + import type { StyleProps } from '../../index' interface SecondaryButtonProps extends StyleProps { @@ -16,7 +18,7 @@ export const SecondaryButton = styled.button.withConfig({ color: ${props => (props.isDangerous ? COLORS.red50 : COLORS.blue50)}; border: ${BORDERS.lineBorder}; border-color: ${props => (props.isDangerous ? COLORS.red50 : 'initial')}; - border-radius: ${BORDERS.radiusSoftCorners}; + border-radius: ${BORDERS.borderRadius4}; padding: ${SPACING.spacing8} ${SPACING.spacing16}; text-transform: ${TYPOGRAPHY.textTransformNone}; background-color: ${COLORS.transparent}; diff --git a/components/src/atoms/buttons/__tests__/AlertPrimaryButton.test.tsx b/components/src/atoms/buttons/__tests__/AlertPrimaryButton.test.tsx index 4725f5d96ff..3080dae524c 100644 --- a/components/src/atoms/buttons/__tests__/AlertPrimaryButton.test.tsx +++ b/components/src/atoms/buttons/__tests__/AlertPrimaryButton.test.tsx @@ -3,8 +3,8 @@ import { describe, it, beforeEach, expect } from 'vitest' import { screen } from '@testing-library/react' import '@testing-library/jest-dom/vitest' import { renderWithProviders } from '../../../testing/utils' -import { COLORS } from '../../../helix-design-system' -import { BORDERS, TYPOGRAPHY, SPACING } from '../../../ui-style-constants' +import { BORDERS, COLORS } from '../../../helix-design-system' +import { TYPOGRAPHY, SPACING } from '../../../ui-style-constants' import { AlertPrimaryButton } from '../AlertPrimaryButton' @@ -31,7 +31,7 @@ describe('AlertPrimaryButton', () => { expect(button).toHaveStyle(`font-size: ${TYPOGRAPHY.fontSizeP}`) expect(button).toHaveStyle(`font-weight: ${TYPOGRAPHY.fontWeightSemiBold}`) expect(button).toHaveStyle(`line-height: ${TYPOGRAPHY.lineHeight20}`) - expect(button).toHaveStyle(`border-radius: ${BORDERS.radiusSoftCorners}`) + expect(button).toHaveStyle(`border-radius: ${BORDERS.borderRadius4}`) expect(button).toHaveStyle( `text-transform: ${TYPOGRAPHY.textTransformNone}` ) diff --git a/components/src/atoms/buttons/__tests__/PrimaryButton.test.tsx b/components/src/atoms/buttons/__tests__/PrimaryButton.test.tsx index 3dc166514ba..651b17e2de8 100644 --- a/components/src/atoms/buttons/__tests__/PrimaryButton.test.tsx +++ b/components/src/atoms/buttons/__tests__/PrimaryButton.test.tsx @@ -3,8 +3,8 @@ import { describe, it, beforeEach, expect } from 'vitest' import { fireEvent, screen } from '@testing-library/react' import '@testing-library/jest-dom/vitest' import { renderWithProviders } from '../../../testing/utils' -import { COLORS } from '../../../helix-design-system' -import { BORDERS, TYPOGRAPHY, SPACING } from '../../../ui-style-constants' +import { BORDERS, COLORS } from '../../../helix-design-system' +import { TYPOGRAPHY, SPACING } from '../../../ui-style-constants' import { PrimaryButton } from '../PrimaryButton' const render = (props: React.ComponentProps) => { @@ -30,7 +30,7 @@ describe('PrimaryButton', () => { expect(button).toHaveStyle(`font-size: ${TYPOGRAPHY.fontSizeP}`) expect(button).toHaveStyle(`font-weight: ${TYPOGRAPHY.fontWeightSemiBold}`) expect(button).toHaveStyle(`line-height: ${TYPOGRAPHY.lineHeight20}`) - expect(button).toHaveStyle(`border-radius: ${BORDERS.radiusSoftCorners}`) + expect(button).toHaveStyle(`border-radius: ${BORDERS.borderRadius4}`) expect(button).toHaveStyle( `text-transform: ${TYPOGRAPHY.textTransformNone}` ) diff --git a/components/src/atoms/buttons/__tests__/SecondaryButton.test.tsx b/components/src/atoms/buttons/__tests__/SecondaryButton.test.tsx index 9d8bbaf35d1..1b461ffd9a5 100644 --- a/components/src/atoms/buttons/__tests__/SecondaryButton.test.tsx +++ b/components/src/atoms/buttons/__tests__/SecondaryButton.test.tsx @@ -3,8 +3,8 @@ import { describe, it, beforeEach, expect } from 'vitest' import { screen } from '@testing-library/react' import '@testing-library/jest-dom/vitest' import { renderWithProviders } from '../../../testing/utils' -import { BORDERS, TYPOGRAPHY, SPACING } from '../../../ui-style-constants' -import { COLORS } from '../../../helix-design-system' +import { TYPOGRAPHY, SPACING } from '../../../ui-style-constants' +import { BORDERS, COLORS } from '../../../helix-design-system' import { SecondaryButton } from '../SecondaryButton' @@ -31,7 +31,7 @@ describe('SecondaryButton', () => { expect(button).toHaveStyle(`font-size: ${TYPOGRAPHY.fontSizeP}`) expect(button).toHaveStyle(`font-weight: ${TYPOGRAPHY.fontWeightSemiBold}`) expect(button).toHaveStyle(`line-height: ${TYPOGRAPHY.lineHeight20}`) - expect(button).toHaveStyle(`border-radius: ${BORDERS.radiusSoftCorners}`) + expect(button).toHaveStyle(`border-radius: ${BORDERS.borderRadius4}`) expect(button).toHaveStyle( `text-transform: ${TYPOGRAPHY.textTransformNone}` ) diff --git a/components/src/hardware-sim/Deck/FlexTrash.tsx b/components/src/hardware-sim/Deck/FlexTrash.tsx index 0be63435543..038e21f857a 100644 --- a/components/src/hardware-sim/Deck/FlexTrash.tsx +++ b/components/src/hardware-sim/Deck/FlexTrash.tsx @@ -8,8 +8,8 @@ import { import { Icon } from '../../icons' import { Flex, Text } from '../../primitives' import { ALIGN_CENTER, JUSTIFY_CENTER } from '../../styles' -import { BORDERS, SPACING, TYPOGRAPHY } from '../../ui-style-constants' -import { COLORS } from '../../helix-design-system' +import { SPACING, TYPOGRAPHY } from '../../ui-style-constants' +import { COLORS, BORDERS } from '../../helix-design-system' import { RobotCoordsForeignObject } from './RobotCoordsForeignObject' import type { RobotType } from '@opentrons/shared-data' @@ -94,7 +94,7 @@ export const FlexTrash = ({ > = args => { width="8.75rem" flexDirection={DIRECTION_COLUMN} alignItems={ALIGN_CENTER} - borderRadius={BORDERS.borderRadiusSize3} + borderRadius={BORDERS.borderRadius12} marginRight={SPACING.spacing8} marginBottom={SPACING.spacing8} padding={SPACING.spacing16} diff --git a/components/src/index.ts b/components/src/index.ts index 99867c4c03e..6e38096c4a5 100644 --- a/components/src/index.ts +++ b/components/src/index.ts @@ -27,8 +27,6 @@ export * from './tooltips' export * from './styles' // new ui-overhaul style vars export * from './ui-style-constants' -// helix design system -export * from './helix-design-system' // helix design system export * from './helix-design-system' diff --git a/components/src/modals/ModalShell.tsx b/components/src/modals/ModalShell.tsx index 62bb638e4d1..ffe9d44d08b 100644 --- a/components/src/modals/ModalShell.tsx +++ b/components/src/modals/ModalShell.tsx @@ -1,7 +1,7 @@ import * as React from 'react' import styled from 'styled-components' -import { BORDERS, SPACING } from '../ui-style-constants' -import { COLORS } from '../helix-design-system' +import { SPACING } from '../ui-style-constants' +import { BORDERS, COLORS } from '../helix-design-system' import { StyleProps, styleProps } from '../primitives' import { POSITION_FIXED, @@ -104,7 +104,7 @@ const ModalArea = styled.div< overflow-y: ${OVERFLOW_AUTO}; max-height: 100%; width: 100%; - border-radius: ${BORDERS.radiusSoftCorners}; + border-radius: ${BORDERS.borderRadius4}; box-shadow: ${BORDERS.smallDropShadow}; height: ${({ isFullPage }) => (isFullPage ? '100%' : 'auto')}; background-color: ${COLORS.white}; diff --git a/components/src/molecules/LocationIcon/__tests__/LocationIcon.test.tsx b/components/src/molecules/LocationIcon/__tests__/LocationIcon.test.tsx index 960a21f61ea..9521bbbf8ea 100644 --- a/components/src/molecules/LocationIcon/__tests__/LocationIcon.test.tsx +++ b/components/src/molecules/LocationIcon/__tests__/LocationIcon.test.tsx @@ -2,8 +2,8 @@ import * as React from 'react' import { describe, it, beforeEach, expect } from 'vitest' import { renderWithProviders } from '../../../testing/utils' import { screen } from '@testing-library/react' -import { BORDERS, SPACING } from '../../../ui-style-constants' -import { COLORS } from '../../../helix-design-system' +import { SPACING } from '../../../ui-style-constants' +import { BORDERS, COLORS } from '../../../helix-design-system' import { LocationIcon } from '..' @@ -27,9 +27,7 @@ describe('LocationIcon', () => { expect(locationIcon).toHaveStyle('height: 2rem') expect(locationIcon).toHaveStyle('width: max-content') expect(locationIcon).toHaveStyle(`border: 2px solid ${COLORS.black90}`) - expect(locationIcon).toHaveStyle( - `border-radius: ${BORDERS.borderRadiusSize3}` - ) + expect(locationIcon).toHaveStyle(`border-radius: ${BORDERS.borderRadius12}`) }) it('should render slot name', () => { diff --git a/components/src/molecules/LocationIcon/index.tsx b/components/src/molecules/LocationIcon/index.tsx index f2279600fe2..1916692a474 100644 --- a/components/src/molecules/LocationIcon/index.tsx +++ b/components/src/molecules/LocationIcon/index.tsx @@ -4,8 +4,8 @@ import { css } from 'styled-components' import { Icon } from '../../icons' import { Flex, Text } from '../../primitives' import { ALIGN_CENTER } from '../../styles' -import { BORDERS, SPACING, TYPOGRAPHY } from '../../ui-style-constants' -import { COLORS } from '../../helix-design-system' +import { SPACING, TYPOGRAPHY } from '../../ui-style-constants' +import { BORDERS, COLORS } from '../../helix-design-system' import type { IconName } from '../../icons' import type { StyleProps } from '../../primitives' @@ -33,7 +33,7 @@ const LOCATION_ICON_STYLE = css<{ }>` align-items: ${ALIGN_CENTER}; border: 2px solid ${props => props.color ?? COLORS.black90}; - border-radius: ${BORDERS.borderRadiusSize3}; + border-radius: ${BORDERS.borderRadius12}; height: ${props => props.height ?? SPACING.spacing32}; width: ${props => props.width ?? 'max-content'}; padding: ${SPACING.spacing4} diff --git a/components/src/molecules/RoundTab.tsx b/components/src/molecules/RoundTab.tsx index 71c83e5a390..29dd54e2e16 100644 --- a/components/src/molecules/RoundTab.tsx +++ b/components/src/molecules/RoundTab.tsx @@ -1,7 +1,7 @@ import * as React from 'react' import { css } from 'styled-components' -import { TYPOGRAPHY, BORDERS, SPACING } from '../ui-style-constants' -import { COLORS } from '../helix-design-system' +import { TYPOGRAPHY, SPACING } from '../ui-style-constants' +import { COLORS, BORDERS } from '../helix-design-system' import { POSITION_RELATIVE } from '../styles' import { Btn } from '../primitives' @@ -10,7 +10,7 @@ const defaultTabStyle = css` color: ${COLORS.black90}; background-color: ${COLORS.purple30}; border: 0px ${BORDERS.styleSolid} ${COLORS.purple30}; - border-radius: ${BORDERS.borderRadiusSize2}; + border-radius: ${BORDERS.borderRadius8}; padding: ${SPACING.spacing8} ${SPACING.spacing16}; position: ${POSITION_RELATIVE}; diff --git a/components/src/tooltips/Tooltip.tsx b/components/src/tooltips/Tooltip.tsx index cea7e35ca20..70617d6dcfa 100644 --- a/components/src/tooltips/Tooltip.tsx +++ b/components/src/tooltips/Tooltip.tsx @@ -1,12 +1,11 @@ import * as React from 'react' import { css } from 'styled-components' -import { radiusSoftCorners } from '../ui-style-constants/borders' +import { BORDERS, COLORS } from '../helix-design-system' import { fontSizeH4 } from '../ui-style-constants/typography' import { spacing8 } from '../ui-style-constants/spacing' import { ARROW_SIZE_PX } from './styles' import { Box } from '../primitives' -import { COLORS } from '../helix-design-system' import type { CSSProperties } from 'react' import type { FlattenSimpleInterpolation } from 'styled-components' @@ -63,7 +62,7 @@ export const Tooltip = React.forwardRef(function TooltipComponent( filter: drop-shadow(0px 1px 3px rgba(0, 0, 0, 0.2)); cursor: pointer; font-size: ${fontSize}; - border-radius: ${radiusSoftCorners}; + border-radius: ${BORDERS.borderRadius4}; ` return visible ? ( diff --git a/components/src/ui-style-constants/borders.ts b/components/src/ui-style-constants/borders.ts deleted file mode 100644 index b097a6269c0..00000000000 --- a/components/src/ui-style-constants/borders.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { css } from 'styled-components' -import { COLORS } from '../helix-design-system' - -export const radiusSoftCorners = '4px' -export const radiusRoundEdge = '20px' -export const styleSolid = 'solid' - -// touch screen -export const borderRadiusSize1 = radiusSoftCorners -export const borderRadiusSize2 = '8px' -export const borderRadiusSize3 = '12px' -export const borderRadiusSize4 = '16px' -export const borderRadiusSize5 = '40px' -export const borderRadiusSize6 = '60px' - -export const tabBorder = css` - border-bottom-style: ${styleSolid}; - border-bottom-width: 2px; - border-bottom-color: ${COLORS.purple50}; -` - -export const activeLineBorder = `1px ${styleSolid} ${COLORS.blue50}` -export const lineBorder = `1px ${styleSolid} ${COLORS.grey30}` -export const transparentLineBorder = `1px ${styleSolid} ${COLORS.transparent}` -export const cardOutlineBorder = css` - border-style: ${styleSolid}; - border-width: 1px; - border-color: ${COLORS.grey30}; - border-radius: ${radiusSoftCorners}; - &:hover { - border-color: ${COLORS.grey55}; - } -` - -export const bigDropShadow = '0 3px 6px rgba(255, 0, 0, 1)' -export const smallDropShadow = '0px 3px 6px rgba(0, 0, 0, 0.23)' - -// touch screen -export const shadowBig = '0px 3px 6px rgba(0,0,0,0.23)' -export const shadowSmall = '0px 0px 40px rgba(0,0,0,0.4)' diff --git a/components/src/ui-style-constants/index.ts b/components/src/ui-style-constants/index.ts index b33b88ba25e..21a599f031c 100644 --- a/components/src/ui-style-constants/index.ts +++ b/components/src/ui-style-constants/index.ts @@ -1,4 +1,3 @@ -export * as BORDERS from './borders' export * as RESPONSIVENESS from './responsiveness' export * as TYPOGRAPHY from './typography' export * as SPACING from './spacing' diff --git a/protocol-designer/src/components/DeckSetup/LabwareOverlays/EditLabwareOffDeck.tsx b/protocol-designer/src/components/DeckSetup/LabwareOverlays/EditLabwareOffDeck.tsx index 48be1799a7f..778902a8b79 100644 --- a/protocol-designer/src/components/DeckSetup/LabwareOverlays/EditLabwareOffDeck.tsx +++ b/protocol-designer/src/components/DeckSetup/LabwareOverlays/EditLabwareOffDeck.tsx @@ -46,7 +46,7 @@ const REGULAR_OVERLAY_STYLE = css` display: flex; align-items: ${ALIGN_FLEX_START}; justify-content: ${JUSTIFY_SPACE_AROUND}; - border-radius: ${BORDERS.borderRadiusSize4}; + border-radius: ${BORDERS.borderRadius16}; bottom: 0; font-size: 0.7rem; position: ${POSITION_ABSOLUTE}; diff --git a/protocol-designer/src/components/OffDeckLabwareSlideout.tsx b/protocol-designer/src/components/OffDeckLabwareSlideout.tsx index c48479129a5..0fa281ef49c 100644 --- a/protocol-designer/src/components/OffDeckLabwareSlideout.tsx +++ b/protocol-designer/src/components/OffDeckLabwareSlideout.tsx @@ -92,7 +92,7 @@ export const OffDeckLabwareSlideout = ( > {offDeck == null ? ( Date: Thu, 14 Mar 2024 14:07:23 -0400 Subject: [PATCH 2/5] refactor(app,api): Add an "awaiting-recovery" run status (#14651) --- api-client/src/maintenance_runs/types.ts | 31 ++++--------------- api-client/src/runs/types.ts | 2 ++ .../protocol_engine/state/commands.py | 7 +++++ api/src/opentrons/protocol_engine/types.py | 8 +++++ .../Devices/ProtocolRun/ProtocolRunHeader.tsx | 5 +-- .../Devices/hooks/useLastRunCommandKey.ts | 2 ++ .../organisms/Devices/hooks/useRunStatuses.ts | 8 ++++- 7 files changed, 35 insertions(+), 28 deletions(-) diff --git a/api-client/src/maintenance_runs/types.ts b/api-client/src/maintenance_runs/types.ts index cda8f8fa0b5..9d8184d4173 100644 --- a/api-client/src/maintenance_runs/types.ts +++ b/api-client/src/maintenance_runs/types.ts @@ -4,35 +4,16 @@ import type { LoadedModule, LoadedPipette, } from '@opentrons/shared-data' -import type { RunCommandSummary, LabwareOffsetCreateData } from '../runs' - -export const ENGINE_STATUS_IDLE = 'idle' as const -export const ENGINE_STATUS_RUNNING = 'running' as const -export const ENGINE_STATUS_PAUSE_REQUESTED = 'pause-requested' as const -export const ENGINE_STATUS_PAUSED = 'paused' -export const ENGINE_STATUS_STOP_REQUESTED = 'stop-requested' as const -export const ENGINE_STATUS_STOPPED = 'stopped' as const -export const ENGINE_STATUS_FAILED = 'failed' as const -export const ENGINE_STATUS_FINISHING = 'finishing' as const -export const ENGINE_STATUS_SUCCEEDED = 'succeeded' as const -export const ENGINE_STATUS_BLOCKED_BY_OPEN_DOOR = 'blocked-by-open-door' as const - -export type EngineStatus = - | typeof ENGINE_STATUS_IDLE - | typeof ENGINE_STATUS_RUNNING - | typeof ENGINE_STATUS_PAUSE_REQUESTED - | typeof ENGINE_STATUS_PAUSED - | typeof ENGINE_STATUS_STOP_REQUESTED - | typeof ENGINE_STATUS_STOPPED - | typeof ENGINE_STATUS_FAILED - | typeof ENGINE_STATUS_FINISHING - | typeof ENGINE_STATUS_SUCCEEDED - | typeof ENGINE_STATUS_BLOCKED_BY_OPEN_DOOR +import type { + RunCommandSummary, + LabwareOffsetCreateData, + RunStatus, +} from '../runs' export interface MaintenanceRunData { id: string createdAt: string - status: EngineStatus + status: RunStatus current: boolean actions: MaintenanceRunAction[] errors: MaintenanceRunError[] diff --git a/api-client/src/runs/types.ts b/api-client/src/runs/types.ts index 319cb568d3a..317b99433c9 100644 --- a/api-client/src/runs/types.ts +++ b/api-client/src/runs/types.ts @@ -18,6 +18,7 @@ export const RUN_STATUS_FAILED = 'failed' as const export const RUN_STATUS_FINISHING = 'finishing' as const export const RUN_STATUS_SUCCEEDED = 'succeeded' as const export const RUN_STATUS_BLOCKED_BY_OPEN_DOOR = 'blocked-by-open-door' as const +export const RUN_STATUS_AWAITING_RECOVERY = 'awaiting-recovery' as const export type RunStatus = | typeof RUN_STATUS_IDLE @@ -30,6 +31,7 @@ export type RunStatus = | typeof RUN_STATUS_FINISHING | typeof RUN_STATUS_SUCCEEDED | typeof RUN_STATUS_BLOCKED_BY_OPEN_DOOR + | typeof RUN_STATUS_AWAITING_RECOVERY export interface RunData { id: string diff --git a/api/src/opentrons/protocol_engine/state/commands.py b/api/src/opentrons/protocol_engine/state/commands.py index 1c47986c62b..f143e8ccd08 100644 --- a/api/src/opentrons/protocol_engine/state/commands.py +++ b/api/src/opentrons/protocol_engine/state/commands.py @@ -691,6 +691,13 @@ def validate_action_allowed( "Setup commands are not allowed after run has started." ) + elif self.get_status() == EngineStatus.AWAITING_RECOVERY: + # While we're developing error recovery, we'll conservatively disallow + # all actions, to avoid putting the engine in weird undefined states. + # We'll allow specific actions here as we flesh things out and add support + # for them. + raise NotImplementedError() + return action def get_status(self) -> EngineStatus: diff --git a/api/src/opentrons/protocol_engine/types.py b/api/src/opentrons/protocol_engine/types.py index a8bc6e1f657..d5b126542d4 100644 --- a/api/src/opentrons/protocol_engine/types.py +++ b/api/src/opentrons/protocol_engine/types.py @@ -35,6 +35,14 @@ class EngineStatus(str, Enum): FAILED = "failed" SUCCEEDED = "succeeded" + AWAITING_RECOVERY = "awaiting-recovery" + """The engine is waiting for external input to recover from a nonfatal error. + + New fixup commands may be enqueued, which will run immediately. + The run can't be paused in this state, but it can be canceled, or resumed from the + next protocol command if recovery is complete. + """ + class DeckSlotLocation(BaseModel): """The location of something placed in a single deck slot.""" diff --git a/app/src/organisms/Devices/ProtocolRun/ProtocolRunHeader.tsx b/app/src/organisms/Devices/ProtocolRun/ProtocolRunHeader.tsx index 11930abee1e..eb0f37da7b2 100644 --- a/app/src/organisms/Devices/ProtocolRun/ProtocolRunHeader.tsx +++ b/app/src/organisms/Devices/ProtocolRun/ProtocolRunHeader.tsx @@ -14,7 +14,7 @@ import { RUN_STATUS_FINISHING, RUN_STATUS_SUCCEEDED, RUN_STATUS_BLOCKED_BY_OPEN_DOOR, - RunStatus, + RUN_STATUS_AWAITING_RECOVERY, } from '@opentrons/api-client' import { useModulesQuery, @@ -109,7 +109,7 @@ import { useMostRecentCompletedAnalysis } from '../../LabwarePositionCheck/useMo import { useMostRecentRunId } from '../../ProtocolUpload/hooks/useMostRecentRunId' import { useNotifyRunQuery } from '../../../resources/runs' -import type { Run, RunError } from '@opentrons/api-client' +import type { Run, RunError, RunStatus } from '@opentrons/api-client' import type { State } from '../../../redux/types' import type { HeaterShakerModule } from '../../../redux/modules/types' import type { PipetteModelSpecs } from '@opentrons/shared-data' @@ -126,6 +126,7 @@ const CANCELLABLE_STATUSES = [ RUN_STATUS_PAUSE_REQUESTED, RUN_STATUS_BLOCKED_BY_OPEN_DOOR, RUN_STATUS_IDLE, + RUN_STATUS_AWAITING_RECOVERY, ] const RUN_OVER_STATUSES: RunStatus[] = [ RUN_STATUS_FAILED, diff --git a/app/src/organisms/Devices/hooks/useLastRunCommandKey.ts b/app/src/organisms/Devices/hooks/useLastRunCommandKey.ts index 15b35c5f1ed..b51160abf2d 100644 --- a/app/src/organisms/Devices/hooks/useLastRunCommandKey.ts +++ b/app/src/organisms/Devices/hooks/useLastRunCommandKey.ts @@ -1,6 +1,7 @@ import { useAllCommandsQuery } from '@opentrons/react-api-client' import { useRunStatus } from '../../RunTimeControl/hooks' import { + RUN_STATUS_AWAITING_RECOVERY, RUN_STATUS_BLOCKED_BY_OPEN_DOOR, RUN_STATUS_FINISHING, RUN_STATUS_IDLE, @@ -21,6 +22,7 @@ const LIVE_RUN_STATUSES = [ RUN_STATUS_RUNNING, RUN_STATUS_FINISHING, RUN_STATUS_BLOCKED_BY_OPEN_DOOR, + RUN_STATUS_AWAITING_RECOVERY, ] const LIVE_RUN_COMMANDS_POLL_MS = 3000 diff --git a/app/src/organisms/Devices/hooks/useRunStatuses.ts b/app/src/organisms/Devices/hooks/useRunStatuses.ts index d7c8a3cf422..bba83f76299 100644 --- a/app/src/organisms/Devices/hooks/useRunStatuses.ts +++ b/app/src/organisms/Devices/hooks/useRunStatuses.ts @@ -1,4 +1,5 @@ import { + RUN_STATUS_AWAITING_RECOVERY, RUN_STATUS_FAILED, RUN_STATUS_IDLE, RUN_STATUS_PAUSED, @@ -21,7 +22,12 @@ export function useRunStatuses(): RunStatusesInfo { const runStatus = useRunStatus(currentRunId) const isRunIdle = runStatus === RUN_STATUS_IDLE const isRunRunning = - runStatus === RUN_STATUS_PAUSED || runStatus === RUN_STATUS_RUNNING + // todo(mm, 2024-03-13): Does this intentionally exclude + // RUN_STATUS_FINISHING, RUN_STATUS_STOP_REQUESTED, + // and RUN_STATUS_BLOCKED_BY_OPEN_DOOR? + runStatus === RUN_STATUS_PAUSED || + runStatus === RUN_STATUS_RUNNING || + runStatus === RUN_STATUS_AWAITING_RECOVERY const isRunTerminal = runStatus === RUN_STATUS_SUCCEEDED || runStatus === RUN_STATUS_STOPPED || From 2ac7dcb91ec0e29141d6e73f99db13f39f6e617e Mon Sep 17 00:00:00 2001 From: Seth Foster Date: Thu, 14 Mar 2024 15:41:35 -0400 Subject: [PATCH 3/5] feat(api): command executors can add notes (#14652) This PR adds an interface for command executors to add notes to the command that they're executing, succeed or fail, and uses that interface to implement an example note warning of aspirate volume rounding. The interface is done by callbacks from the command implementations to the command executor that is executing each command. Implementations, or the functions they call, are responsible for creating the CommandNote instances. The executor just gathers a list of commands and then issues an UpdateCommandAction with the new list. If there are already notes on the command before execution, the new ones are appended. While this doesn't seem necessary right now, we'll want this behavior generically when we have notes also coming from hardware. One thing that's a little annoying about this interface is that the callbacks have to be threaded through all the way to whatever wants to add a note. For instance, in the example aspirate-rounded note, we have to pass the callback all the way into the pipetting executor. An alternative would be to have an interface that can add notes on one of the state instances that can be called from anything that can access the state instance. The thing is, that function won't have the context to know when commands are currently executing or are done executing without having some sort of state machine that only looks at UpdateCommandActions from elsewhere. That code would be pretty ugly. The alternative there would be to issue a new UpdateCommandAction for each note; this would have race condition issues if it provided new values for the notes list. The alternative _there_ would be a new action called like AddCommandNoteAction that carries the attention of adding to the notes list along with it. Of course, that command is not idempotent. This interface works well enough for now that I think we should roll with it, and feel free to change it later. Closes EXEC-291 --------- Co-authored-by: Max Marrone --- api/src/opentrons/protocol_engine/__init__.py | 2 +- .../protocol_engine/commands/__init__.py | 2 - .../protocol_engine/commands/aspirate.py | 8 +- .../commands/aspirate_in_place.py | 9 +- .../protocol_engine/commands/command.py | 28 +- .../execution/command_executor.py | 68 ++++- .../protocol_engine/execution/pipetting.py | 35 ++- .../protocol_engine/notes/__init__.py | 5 + .../opentrons/protocol_engine/notes/notes.py | 42 +++ .../protocol_engine/commands/test_aspirate.py | 31 +- .../commands/test_aspirate_in_place.py | 21 +- .../opentrons/protocol_engine/conftest.py | 7 + .../execution/test_command_executor.py | 280 ++++++++++++++++++ .../execution/test_pipetting_handler.py | 46 ++- .../opentrons/protocol_engine/note_utils.py | 63 ++++ .../tests/runs/router/test_commands_router.py | 5 +- 16 files changed, 593 insertions(+), 59 deletions(-) create mode 100644 api/src/opentrons/protocol_engine/notes/__init__.py create mode 100644 api/src/opentrons/protocol_engine/notes/notes.py create mode 100644 api/tests/opentrons/protocol_engine/note_utils.py diff --git a/api/src/opentrons/protocol_engine/__init__.py b/api/src/opentrons/protocol_engine/__init__.py index 07f2ae17f9c..eb62ee7f33a 100644 --- a/api/src/opentrons/protocol_engine/__init__.py +++ b/api/src/opentrons/protocol_engine/__init__.py @@ -13,6 +13,7 @@ ) from .protocol_engine import ProtocolEngine from .errors import ProtocolEngineError, ErrorOccurrence +from .notes import CommandNote from .commands import ( Command, CommandParams, @@ -20,7 +21,6 @@ CommandStatus, CommandType, CommandIntent, - CommandNote, ) from .state import State, StateView, StateSummary, CommandSlice, CurrentCommand, Config from .plugins import AbstractPlugin diff --git a/api/src/opentrons/protocol_engine/commands/__init__.py b/api/src/opentrons/protocol_engine/commands/__init__.py index 97f0744a9a2..3dfe6eaf51f 100644 --- a/api/src/opentrons/protocol_engine/commands/__init__.py +++ b/api/src/opentrons/protocol_engine/commands/__init__.py @@ -28,7 +28,6 @@ BaseCommandCreate, CommandStatus, CommandIntent, - CommandNote, ) from .command_unions import ( @@ -333,7 +332,6 @@ "BaseCommandCreate", "CommandStatus", "CommandIntent", - "CommandNote", # command parameter hashing "hash_command_params", # command schema generation diff --git a/api/src/opentrons/protocol_engine/commands/aspirate.py b/api/src/opentrons/protocol_engine/commands/aspirate.py index 35f0878612b..4dcb81dcc33 100644 --- a/api/src/opentrons/protocol_engine/commands/aspirate.py +++ b/api/src/opentrons/protocol_engine/commands/aspirate.py @@ -20,6 +20,7 @@ if TYPE_CHECKING: from ..execution import MovementHandler, PipettingHandler from ..state import StateView + from ..notes import CommandNoteAdder AspirateCommandType = Literal["aspirate"] @@ -48,12 +49,14 @@ def __init__( state_view: StateView, hardware_api: HardwareControlAPI, movement: MovementHandler, + command_note_adder: CommandNoteAdder, **kwargs: object, ) -> None: self._pipetting = pipetting self._state_view = state_view self._hardware_api = hardware_api self._movement = movement + self._command_note_adder = command_note_adder async def execute(self, params: AspirateParams) -> AspirateResult: """Move to and aspirate from the requested well. @@ -98,7 +101,10 @@ async def execute(self, params: AspirateParams) -> AspirateResult: ) volume = await self._pipetting.aspirate_in_place( - pipette_id=pipette_id, volume=params.volume, flow_rate=params.flowRate + pipette_id=pipette_id, + volume=params.volume, + flow_rate=params.flowRate, + command_note_adder=self._command_note_adder, ) return AspirateResult( diff --git a/api/src/opentrons/protocol_engine/commands/aspirate_in_place.py b/api/src/opentrons/protocol_engine/commands/aspirate_in_place.py index 4cdcd36297c..f59bccdd9f7 100644 --- a/api/src/opentrons/protocol_engine/commands/aspirate_in_place.py +++ b/api/src/opentrons/protocol_engine/commands/aspirate_in_place.py @@ -18,7 +18,7 @@ if TYPE_CHECKING: from ..execution import PipettingHandler from ..state import StateView - + from ..notes import CommandNoteAdder AspirateInPlaceCommandType = Literal["aspirateInPlace"] @@ -45,11 +45,13 @@ def __init__( pipetting: PipettingHandler, hardware_api: HardwareControlAPI, state_view: StateView, + command_note_adder: CommandNoteAdder, **kwargs: object, ) -> None: self._pipetting = pipetting self._state_view = state_view self._hardware_api = hardware_api + self._command_note_adder = command_note_adder async def execute(self, params: AspirateInPlaceParams) -> AspirateInPlaceResult: """Aspirate without moving the pipette. @@ -69,7 +71,10 @@ async def execute(self, params: AspirateInPlaceParams) -> AspirateInPlaceResult: " so the plunger can be reset in a known safe position." ) volume = await self._pipetting.aspirate_in_place( - pipette_id=params.pipetteId, volume=params.volume, flow_rate=params.flowRate + pipette_id=params.pipetteId, + volume=params.volume, + flow_rate=params.flowRate, + command_note_adder=self._command_note_adder, ) return AspirateInPlaceResult(volume=volume) diff --git a/api/src/opentrons/protocol_engine/commands/command.py b/api/src/opentrons/protocol_engine/commands/command.py index 1bf72e12352..5c2ab46b06f 100644 --- a/api/src/opentrons/protocol_engine/commands/command.py +++ b/api/src/opentrons/protocol_engine/commands/command.py @@ -12,8 +12,6 @@ Optional, TypeVar, Tuple, - Union, - Literal, List, ) @@ -23,6 +21,7 @@ from opentrons.hardware_control import HardwareControlAPI from ..errors import ErrorOccurrence +from ..notes import CommandNote, CommandNoteAdder # Work around type-only circular dependencies. if TYPE_CHECKING: @@ -36,29 +35,6 @@ CommandPrivateResultT = TypeVar("CommandPrivateResultT") -NoteKind = Union[Literal["warning", "information"], str] - - -class CommandNote(BaseModel): - """A note about a command's execution or dispatch.""" - - noteKind: NoteKind = Field( - ..., - description="The kind of note this is. Only the literal possibilities should be" - " relied upon programmatically.", - ) - shortMessage: str = Field( - ..., - description="The accompanying human-readable short message (suitable for display in a single line)", - ) - longMessage: str = Field( - ..., - description="A longer message that may contain newlines and formatting characters describing the note.", - ) - source: str = Field( - ..., description="An identifier for the party that created the note" - ) - class CommandStatus(str, Enum): """Command execution status.""" @@ -215,6 +191,7 @@ def __init__( run_control: execution.RunControlHandler, rail_lights: execution.RailLightsHandler, status_bar: execution.StatusBarHandler, + command_note_adder: CommandNoteAdder, ) -> None: """Initialize the command implementation with execution handlers.""" pass @@ -256,6 +233,7 @@ def __init__( run_control: execution.RunControlHandler, rail_lights: execution.RailLightsHandler, status_bar: execution.StatusBarHandler, + command_note_adder: CommandNoteAdder, ) -> None: """Initialize the command implementation with execution handlers.""" pass diff --git a/api/src/opentrons/protocol_engine/execution/command_executor.py b/api/src/opentrons/protocol_engine/execution/command_executor.py index 7334d96e170..105d2af3994 100644 --- a/api/src/opentrons/protocol_engine/execution/command_executor.py +++ b/api/src/opentrons/protocol_engine/execution/command_executor.py @@ -1,7 +1,7 @@ """Command side-effect execution logic container.""" import asyncio from logging import getLogger -from typing import Optional +from typing import Optional, List, Dict, Any, Protocol from opentrons.hardware_control import HardwareControlAPI @@ -18,10 +18,12 @@ AbstractCommandImpl, CommandResult, CommandPrivateResult, + Command, ) from ..actions import ActionDispatcher, UpdateCommandAction, FailCommandAction from ..errors import RunStoppedError from ..errors.exceptions import EStopActivatedError as PE_EStopActivatedError +from ..notes import CommandNote, CommandNoteTracker from .equipment import EquipmentHandler from .movement import MovementHandler from .gantry_mover import GantryMover @@ -36,6 +38,29 @@ log = getLogger(__name__) +class CommandNoteTrackerProvider(Protocol): + """The correct shape for a function that provides a CommandNoteTracker. + + This function will be called by the executor once for each call to execute(). + It is mostly useful for testing harnesses. + """ + + def __call__(self) -> CommandNoteTracker: + """Provide a new CommandNoteTracker.""" + ... + + +class _NoteTracker(CommandNoteTracker): + def __init__(self) -> None: + self._notes: List[CommandNote] = [] + + def __call__(self, note: CommandNote) -> None: + self._notes.append(note) + + def get_notes(self) -> List[CommandNote]: + return self._notes + + class CommandExecutor: """CommandExecutor container class. @@ -58,6 +83,7 @@ def __init__( rail_lights: RailLightsHandler, status_bar: StatusBarHandler, model_utils: Optional[ModelUtils] = None, + command_note_tracker_provider: Optional[CommandNoteTrackerProvider] = None, ) -> None: """Initialize the CommandExecutor with access to its dependencies.""" self._hardware_api = hardware_api @@ -73,6 +99,9 @@ def __init__( self._rail_lights = rail_lights self._model_utils = model_utils or ModelUtils() self._status_bar = status_bar + self._command_note_tracker_provider = ( + command_note_tracker_provider or _NoteTracker + ) async def execute(self, command_id: str) -> None: """Run a given command's execution procedure. @@ -82,6 +111,7 @@ async def execute(self, command_id: str) -> None: command itself will be looked up from state. """ command = self._state_store.commands.get(command_id=command_id) + note_tracker = self._command_note_tracker_provider() command_impl = command._ImplementationCls( state_view=self._state_store, hardware_api=self._hardware_api, @@ -94,6 +124,7 @@ async def execute(self, command_id: str) -> None: run_control=self._run_control, rail_lights=self._rail_lights, status_bar=self._status_bar, + command_note_adder=note_tracker, ) started_at = self._model_utils.get_timestamp() @@ -128,6 +159,17 @@ async def execute(self, command_id: str) -> None: error = PE_EStopActivatedError(message=str(error), wrapping=[error]) elif not isinstance(error, EnumeratedError): error = PythonException(error) + notes_update = _append_notes_if_notes( + running_command, note_tracker.get_notes() + ) + + if notes_update: + command_with_new_notes = running_command.copy(update=notes_update) + self._action_dispatcher.dispatch( + UpdateCommandAction( + command=command_with_new_notes, private_result=None + ) + ) self._action_dispatcher.dispatch( FailCommandAction( @@ -138,15 +180,25 @@ async def execute(self, command_id: str) -> None: ) ) else: - completed_command = running_command.copy( - update={ - "result": result, - "status": CommandStatus.SUCCEEDED, - "completedAt": self._model_utils.get_timestamp(), - } - ) + update = { + "result": result, + "status": CommandStatus.SUCCEEDED, + "completedAt": self._model_utils.get_timestamp(), + **_append_notes_if_notes(running_command, note_tracker.get_notes()), + } + completed_command = running_command.copy(update=update) self._action_dispatcher.dispatch( UpdateCommandAction( command=completed_command, private_result=private_result ), ) + + +def _append_notes_if_notes( + running_command: Command, notes: List[CommandNote] +) -> Dict[str, Any]: + if not notes: + return {} + if running_command.notes is None: + return {"notes": notes} + return {"notes": running_command.notes + notes} diff --git a/api/src/opentrons/protocol_engine/execution/pipetting.py b/api/src/opentrons/protocol_engine/execution/pipetting.py index 7305a4c09da..7abfb158539 100644 --- a/api/src/opentrons/protocol_engine/execution/pipetting.py +++ b/api/src/opentrons/protocol_engine/execution/pipetting.py @@ -6,6 +6,7 @@ from opentrons.hardware_control import HardwareControlAPI from ..state import StateView, HardwarePipette +from ..notes import CommandNoteAdder, CommandNote from ..errors.exceptions import ( TipNotAttachedError, InvalidAspirateVolumeError, @@ -39,6 +40,7 @@ async def aspirate_in_place( pipette_id: str, volume: float, flow_rate: float, + command_note_adder: CommandNoteAdder, ) -> float: """Set flow-rate and aspirate.""" @@ -88,11 +90,15 @@ async def aspirate_in_place( pipette_id: str, volume: float, flow_rate: float, + command_note_adder: CommandNoteAdder, ) -> float: """Set flow-rate and aspirate.""" # get mount and config data from state and hardware controller adjusted_volume = _validate_aspirate_volume( - state_view=self._state_view, pipette_id=pipette_id, aspirate_volume=volume + state_view=self._state_view, + pipette_id=pipette_id, + aspirate_volume=volume, + command_note_adder=command_note_adder, ) hw_pipette = self._state_view.pipettes.get_hardware_pipette( pipette_id=pipette_id, @@ -199,11 +205,15 @@ async def aspirate_in_place( pipette_id: str, volume: float, flow_rate: float, + command_note_adder: CommandNoteAdder, ) -> float: """Virtually aspirate (no-op).""" self._validate_tip_attached(pipette_id=pipette_id, command_name="aspirate") return _validate_aspirate_volume( - state_view=self._state_view, pipette_id=pipette_id, aspirate_volume=volume + state_view=self._state_view, + pipette_id=pipette_id, + aspirate_volume=volume, + command_note_adder=command_note_adder, ) async def dispense_in_place( @@ -252,7 +262,10 @@ def create_pipetting_handler( def _validate_aspirate_volume( - state_view: StateView, pipette_id: str, aspirate_volume: float + state_view: StateView, + pipette_id: str, + aspirate_volume: float, + command_note_adder: CommandNoteAdder, ) -> float: """Get whether the given volume is valid to aspirate right now. @@ -285,7 +298,21 @@ def _validate_aspirate_volume( ), ) else: - return min(aspirate_volume, available_volume) + volume_to_aspirate = min(aspirate_volume, available_volume) + if volume_to_aspirate < aspirate_volume: + command_note_adder( + CommandNote( + noteKind="warning", + shortMessage=f"Aspirate clamped to {available_volume} µL", + longMessage=( + f"Command requested to aspirate {aspirate_volume} µL but only" + f" {available_volume} µL were available in the pipette. This is" + " probably a floating point artifact." + ), + source="execution", + ) + ) + return volume_to_aspirate def _validate_dispense_volume( diff --git a/api/src/opentrons/protocol_engine/notes/__init__.py b/api/src/opentrons/protocol_engine/notes/__init__.py new file mode 100644 index 00000000000..f5b1d8c1a2a --- /dev/null +++ b/api/src/opentrons/protocol_engine/notes/__init__.py @@ -0,0 +1,5 @@ +"""Protocol engine notes module.""" + +from .notes import NoteKind, CommandNote, CommandNoteAdder, CommandNoteTracker + +__all__ = ["NoteKind", "CommandNote", "CommandNoteAdder", "CommandNoteTracker"] diff --git a/api/src/opentrons/protocol_engine/notes/notes.py b/api/src/opentrons/protocol_engine/notes/notes.py new file mode 100644 index 00000000000..cf381aa4a68 --- /dev/null +++ b/api/src/opentrons/protocol_engine/notes/notes.py @@ -0,0 +1,42 @@ +"""Definitions of data and interface shapes for notes.""" +from typing import Union, Literal, Protocol, List +from pydantic import BaseModel, Field + +NoteKind = Union[Literal["warning", "information"], str] + + +class CommandNote(BaseModel): + """A note about a command's execution or dispatch.""" + + noteKind: NoteKind = Field( + ..., + description="The kind of note this is. Only the literal possibilities should be" + " relied upon programmatically.", + ) + shortMessage: str = Field( + ..., + description="The accompanying human-readable short message (suitable for display in a single line)", + ) + longMessage: str = Field( + ..., + description="A longer message that may contain newlines and formatting characters describing the note.", + ) + source: str = Field( + ..., description="An identifier for the party that created the note" + ) + + +class CommandNoteAdder(Protocol): + """The shape of a function that something can use to add a command note.""" + + def __call__(self, note: CommandNote) -> None: + """When called, this function should add the passed Note to some list.""" + ... + + +class CommandNoteTracker(CommandNoteAdder, Protocol): + """The shape of a class that can track notes.""" + + def get_notes(self) -> List[CommandNote]: + """When called, should return all notes previously added with __call__.""" + ... diff --git a/api/tests/opentrons/protocol_engine/commands/test_aspirate.py b/api/tests/opentrons/protocol_engine/commands/test_aspirate.py index 178f118cc50..f625c19f93f 100644 --- a/api/tests/opentrons/protocol_engine/commands/test_aspirate.py +++ b/api/tests/opentrons/protocol_engine/commands/test_aspirate.py @@ -19,6 +19,7 @@ ) from opentrons.protocol_engine.types import CurrentWell, LoadedPipette from opentrons.hardware_control import HardwareControlAPI +from opentrons.protocol_engine.notes import CommandNoteAdder @pytest.fixture @@ -27,6 +28,7 @@ def subject( hardware_api: HardwareControlAPI, movement: MovementHandler, pipetting: PipettingHandler, + mock_command_note_adder: CommandNoteAdder, ) -> AspirateImplementation: """Get the implementation subject.""" return AspirateImplementation( @@ -34,6 +36,7 @@ def subject( state_view=state_view, movement=movement, hardware_api=hardware_api, + command_note_adder=mock_command_note_adder, ) @@ -44,6 +47,7 @@ async def test_aspirate_implementation_no_prep( movement: MovementHandler, pipetting: PipettingHandler, subject: AspirateImplementation, + mock_command_note_adder: CommandNoteAdder, ) -> None: """An Aspirate should have an execution implementation without preparing to aspirate.""" location = WellLocation(origin=WellOrigin.BOTTOM, offset=WellOffset(x=0, y=0, z=1)) @@ -70,7 +74,12 @@ async def test_aspirate_implementation_no_prep( ).then_return(Point(x=1, y=2, z=3)) decoy.when( - await pipetting.aspirate_in_place(pipette_id="abc", volume=50, flow_rate=1.23), + await pipetting.aspirate_in_place( + pipette_id="abc", + volume=50, + flow_rate=1.23, + command_note_adder=mock_command_note_adder, + ), ).then_return(50) result = await subject.execute(data) @@ -84,6 +93,7 @@ async def test_aspirate_implementation_with_prep( hardware_api: HardwareControlAPI, movement: MovementHandler, pipetting: PipettingHandler, + mock_command_note_adder: CommandNoteAdder, subject: AspirateImplementation, ) -> None: """An Aspirate should have an execution implementation with preparing to aspirate.""" @@ -120,7 +130,12 @@ async def test_aspirate_implementation_with_prep( ).then_return(Point(x=1, y=2, z=3)) decoy.when( - await pipetting.aspirate_in_place(pipette_id="abc", volume=50, flow_rate=1.23), + await pipetting.aspirate_in_place( + pipette_id="abc", + volume=50, + flow_rate=1.23, + command_note_adder=mock_command_note_adder, + ), ).then_return(50) result = await subject.execute(data) @@ -139,7 +154,10 @@ async def test_aspirate_implementation_with_prep( async def test_aspirate_raises_volume_error( - decoy: Decoy, pipetting: PipettingHandler, subject: AspirateImplementation + decoy: Decoy, + pipetting: PipettingHandler, + mock_command_note_adder: CommandNoteAdder, + subject: AspirateImplementation, ) -> None: """Should raise an assertion error for volume larger than working volume.""" location = WellLocation(origin=WellOrigin.BOTTOM, offset=WellOffset(x=0, y=0, z=1)) @@ -156,7 +174,12 @@ async def test_aspirate_raises_volume_error( decoy.when(pipetting.get_is_ready_to_aspirate(pipette_id="abc")).then_return(True) decoy.when( - await pipetting.aspirate_in_place(pipette_id="abc", volume=50, flow_rate=1.23) + await pipetting.aspirate_in_place( + pipette_id="abc", + volume=50, + flow_rate=1.23, + command_note_adder=mock_command_note_adder, + ) ).then_raise(AssertionError("blah blah")) with pytest.raises(AssertionError): diff --git a/api/tests/opentrons/protocol_engine/commands/test_aspirate_in_place.py b/api/tests/opentrons/protocol_engine/commands/test_aspirate_in_place.py index 26a39b9001f..3d09c029bcd 100644 --- a/api/tests/opentrons/protocol_engine/commands/test_aspirate_in_place.py +++ b/api/tests/opentrons/protocol_engine/commands/test_aspirate_in_place.py @@ -11,6 +11,7 @@ AspirateInPlaceImplementation, ) from opentrons.protocol_engine.errors.exceptions import PipetteNotReadyToAspirateError +from opentrons.protocol_engine.notes import CommandNoteAdder from opentrons.protocol_engine.state import ( StateStore, @@ -40,12 +41,14 @@ def subject( pipetting: PipettingHandler, state_store: StateStore, hardware_api: HardwareAPI, + mock_command_note_adder: CommandNoteAdder, ) -> AspirateInPlaceImplementation: """Get the impelementation subject.""" return AspirateInPlaceImplementation( pipetting=pipetting, hardware_api=hardware_api, state_view=state_store, + command_note_adder=mock_command_note_adder, ) @@ -54,6 +57,7 @@ async def test_aspirate_in_place_implementation( pipetting: PipettingHandler, state_store: StateStore, hardware_api: HardwareAPI, + mock_command_note_adder: CommandNoteAdder, subject: AspirateInPlaceImplementation, ) -> None: """It should aspirate in place.""" @@ -71,7 +75,10 @@ async def test_aspirate_in_place_implementation( decoy.when( await pipetting.aspirate_in_place( - pipette_id="pipette-id-abc", volume=123, flow_rate=1.234 + pipette_id="pipette-id-abc", + volume=123, + flow_rate=1.234, + command_note_adder=mock_command_note_adder, ) ).then_return(123) @@ -110,7 +117,10 @@ async def test_handle_aspirate_in_place_request_not_ready_to_aspirate( async def test_aspirate_raises_volume_error( - decoy: Decoy, pipetting: PipettingHandler, subject: AspirateInPlaceImplementation + decoy: Decoy, + pipetting: PipettingHandler, + subject: AspirateInPlaceImplementation, + mock_command_note_adder: CommandNoteAdder, ) -> None: """Should raise an assertion error for volume larger than working volume.""" data = AspirateInPlaceParams( @@ -122,7 +132,12 @@ async def test_aspirate_raises_volume_error( decoy.when(pipetting.get_is_ready_to_aspirate(pipette_id="abc")).then_return(True) decoy.when( - await pipetting.aspirate_in_place(pipette_id="abc", volume=50, flow_rate=1.23) + await pipetting.aspirate_in_place( + pipette_id="abc", + volume=50, + flow_rate=1.23, + command_note_adder=mock_command_note_adder, + ) ).then_raise(AssertionError("blah blah")) with pytest.raises(AssertionError): diff --git a/api/tests/opentrons/protocol_engine/conftest.py b/api/tests/opentrons/protocol_engine/conftest.py index d703a964078..dfd59089c2d 100644 --- a/api/tests/opentrons/protocol_engine/conftest.py +++ b/api/tests/opentrons/protocol_engine/conftest.py @@ -21,6 +21,7 @@ from opentrons.hardware_control import HardwareControlAPI, OT2HardwareControlAPI from opentrons.hardware_control.api import API from opentrons.hardware_control.protocols.types import FlexRobotType, OT2RobotType +from opentrons.protocol_engine.notes import CommandNoteAdder if TYPE_CHECKING: from opentrons.hardware_control.ot3api import OT3API @@ -230,3 +231,9 @@ def supported_tip_fixture() -> pipette_definition.SupportedTipsDefinition: dispense=pipette_definition.ulPerMMDefinition(default={"1": [(0, 0, 0)]}), defaultPushOutVolume=3, ) + + +@pytest.fixture +def mock_command_note_adder(decoy: Decoy) -> CommandNoteAdder: + """Get a command note adder.""" + return decoy.mock(cls=CommandNoteAdder) diff --git a/api/tests/opentrons/protocol_engine/execution/test_command_executor.py b/api/tests/opentrons/protocol_engine/execution/test_command_executor.py index 50c54eceacf..961bfa3ac54 100644 --- a/api/tests/opentrons/protocol_engine/execution/test_command_executor.py +++ b/api/tests/opentrons/protocol_engine/execution/test_command_executor.py @@ -40,8 +40,12 @@ RailLightsHandler, StatusBarHandler, ) +from opentrons.protocol_engine.execution.command_executor import ( + CommandNoteTrackerProvider, +) from opentrons_shared_data.errors.exceptions import EStopActivatedError, PythonException +from opentrons.protocol_engine.notes import CommandNoteTracker, CommandNote @pytest.fixture @@ -122,6 +126,33 @@ def status_bar(decoy: Decoy) -> StatusBarHandler: return decoy.mock(cls=StatusBarHandler) +@pytest.fixture +def command_note_tracker_provider(decoy: Decoy) -> CommandNoteTrackerProvider: + """Get a mock tracker provider.""" + return decoy.mock(cls=CommandNoteTrackerProvider) + + +def get_next_tracker( + decoy: Decoy, provider: CommandNoteTrackerProvider +) -> CommandNoteTracker: + """Get the next tracker provided by a provider, in code without being a fixture. + + This is useful for testing the execution of multiple commands, each of which will get + a different tracker instance. + """ + new_tracker = decoy.mock(cls=CommandNoteTracker) + decoy.when(provider()).then_return(new_tracker) + return new_tracker + + +@pytest.fixture +def command_note_tracker( + decoy: Decoy, command_note_tracker_provider: CommandNoteTrackerProvider +) -> CommandNoteTracker: + """Get the tracker that the provider will provide.""" + return get_next_tracker(decoy, command_note_tracker_provider) + + @pytest.fixture def subject( hardware_api: HardwareControlAPI, @@ -137,6 +168,7 @@ def subject( rail_lights: RailLightsHandler, status_bar: StatusBarHandler, model_utils: ModelUtils, + command_note_tracker_provider: CommandNoteTrackerProvider, ) -> CommandExecutor: """Get a CommandExecutor test subject with its dependencies mocked out.""" return CommandExecutor( @@ -153,6 +185,7 @@ def subject( model_utils=model_utils, rail_lights=rail_lights, status_bar=status_bar, + command_note_tracker_provider=command_note_tracker_provider, ) @@ -184,6 +217,7 @@ async def test_execute( rail_lights: RailLightsHandler, status_bar: StatusBarHandler, model_utils: ModelUtils, + command_note_tracker: CommandNoteTracker, subject: CommandExecutor, ) -> None: """It should be able to execute a command.""" @@ -256,6 +290,7 @@ def _ImplementationCls(self) -> Type[_TestCommandImpl]: run_control=run_control, rail_lights=rail_lights, status_bar=status_bar, + command_note_adder=command_note_tracker, ) ).then_return( command_impl # type: ignore[arg-type] @@ -321,6 +356,7 @@ async def test_execute_raises_protocol_engine_error( status_bar: StatusBarHandler, model_utils: ModelUtils, subject: CommandExecutor, + command_note_tracker: CommandNoteTracker, command_error: Exception, expected_error: Any, unexpected_error: bool, @@ -380,6 +416,7 @@ def _ImplementationCls(self) -> Type[_TestCommandImpl]: run_control=run_control, rail_lights=rail_lights, status_bar=status_bar, + command_note_adder=command_note_tracker, ) ).then_return( command_impl # type: ignore[arg-type] @@ -408,3 +445,246 @@ def _ImplementationCls(self) -> Type[_TestCommandImpl]: ) ), ) + + +async def test_executor_forwards_notes_on_command_success( + decoy: Decoy, + hardware_api: HardwareControlAPI, + state_store: StateStore, + action_dispatcher: ActionDispatcher, + equipment: EquipmentHandler, + movement: MovementHandler, + mock_gantry_mover: GantryMover, + labware_movement: LabwareMovementHandler, + pipetting: PipettingHandler, + mock_tip_handler: TipHandler, + run_control: RunControlHandler, + rail_lights: RailLightsHandler, + status_bar: StatusBarHandler, + model_utils: ModelUtils, + command_note_tracker: CommandNoteTracker, + subject: CommandExecutor, +) -> None: + """It should be able to add notes during OK execution to command updates.""" + TestCommandImplCls = decoy.mock(func=_TestCommandImpl) + command_impl = decoy.mock(cls=_TestCommandImpl) + + class _TestCommand(BaseCommand[_TestCommandParams, _TestCommandResult]): + commandType: str = "testCommand" + params: _TestCommandParams + result: Optional[_TestCommandResult] + + @property + def _ImplementationCls(self) -> Type[_TestCommandImpl]: + return TestCommandImplCls + + command_params = _TestCommandParams() + command_result = _TestCommandResult() + + queued_command = cast( + Command, + _TestCommand( + id="command-id", + key="command-key", + createdAt=datetime(year=2021, month=1, day=1), + status=CommandStatus.QUEUED, + params=command_params, + ), + ) + + command_notes = [ + CommandNote( + noteKind="warning", + shortMessage="hello", + longMessage="test command note", + source="test", + ) + ] + + running_command = cast( + Command, + _TestCommand( + id="command-id", + key="command-key", + createdAt=datetime(year=2021, month=1, day=1), + startedAt=datetime(year=2022, month=2, day=2), + status=CommandStatus.RUNNING, + params=command_params, + ), + ) + + completed_command = cast( + Command, + _TestCommand( + id="command-id", + key="command-key", + createdAt=datetime(year=2021, month=1, day=1), + startedAt=datetime(year=2022, month=2, day=2), + completedAt=datetime(year=2023, month=3, day=3), + status=CommandStatus.SUCCEEDED, + params=command_params, + result=command_result, + notes=command_notes, + ), + ) + + decoy.when(state_store.commands.get(command_id="command-id")).then_return( + queued_command + ) + + decoy.when( + queued_command._ImplementationCls( + state_view=state_store, + hardware_api=hardware_api, + equipment=equipment, + movement=movement, + gantry_mover=mock_gantry_mover, + labware_movement=labware_movement, + pipetting=pipetting, + tip_handler=mock_tip_handler, + run_control=run_control, + rail_lights=rail_lights, + status_bar=status_bar, + command_note_adder=command_note_tracker, + ) + ).then_return( + command_impl # type: ignore[arg-type] + ) + + decoy.when(await command_impl.execute(command_params)).then_return(command_result) + + decoy.when(model_utils.get_timestamp()).then_return( + datetime(year=2022, month=2, day=2), + datetime(year=2023, month=3, day=3), + ) + decoy.when(command_note_tracker.get_notes()).then_return(command_notes) + + await subject.execute("command-id") + + decoy.verify( + action_dispatcher.dispatch( + UpdateCommandAction(private_result=None, command=running_command) + ), + action_dispatcher.dispatch( + UpdateCommandAction(private_result=None, command=completed_command) + ), + ) + + +async def test_executor_forwards_notes_on_command_failure( + decoy: Decoy, + hardware_api: HardwareControlAPI, + state_store: StateStore, + action_dispatcher: ActionDispatcher, + equipment: EquipmentHandler, + movement: MovementHandler, + mock_gantry_mover: GantryMover, + labware_movement: LabwareMovementHandler, + pipetting: PipettingHandler, + mock_tip_handler: TipHandler, + run_control: RunControlHandler, + rail_lights: RailLightsHandler, + status_bar: StatusBarHandler, + model_utils: ModelUtils, + subject: CommandExecutor, + command_note_tracker: CommandNoteTracker, +) -> None: + """It should handle an error occuring during execution.""" + TestCommandImplCls = decoy.mock(func=_TestCommandImpl) + command_impl = decoy.mock(cls=_TestCommandImpl) + + class _TestCommand(BaseCommand[_TestCommandParams, _TestCommandResult]): + commandType: str = "testCommand" + params: _TestCommandParams + result: Optional[_TestCommandResult] + + @property + def _ImplementationCls(self) -> Type[_TestCommandImpl]: + return TestCommandImplCls + + command_params = _TestCommandParams() + command_notes = [ + CommandNote( + noteKind="warning", + shortMessage="hello", + longMessage="test command note", + source="test", + ) + ] + + queued_command = cast( + Command, + _TestCommand( + id="command-id", + key="command-key", + createdAt=datetime(year=2021, month=1, day=1), + status=CommandStatus.QUEUED, + params=command_params, + ), + ) + + running_command = cast( + Command, + _TestCommand( + id="command-id", + key="command-key", + createdAt=datetime(year=2021, month=1, day=1), + startedAt=datetime(year=2022, month=2, day=2), + status=CommandStatus.RUNNING, + params=command_params, + ), + ) + running_command_with_notes = running_command.copy(update={"notes": command_notes}) + + decoy.when(state_store.commands.get(command_id="command-id")).then_return( + queued_command + ) + + decoy.when( + queued_command._ImplementationCls( + state_view=state_store, + hardware_api=hardware_api, + equipment=equipment, + movement=movement, + gantry_mover=mock_gantry_mover, + labware_movement=labware_movement, + pipetting=pipetting, + tip_handler=mock_tip_handler, + run_control=run_control, + rail_lights=rail_lights, + status_bar=status_bar, + command_note_adder=command_note_tracker, + ) + ).then_return( + command_impl # type: ignore[arg-type] + ) + + decoy.when(await command_impl.execute(command_params)).then_raise( + RuntimeError("oh no") + ) + + decoy.when(model_utils.generate_id()).then_return("error-id") + decoy.when(model_utils.get_timestamp()).then_return( + datetime(year=2022, month=2, day=2), + datetime(year=2023, month=3, day=3), + ) + decoy.when(command_note_tracker.get_notes()).then_return(command_notes) + + await subject.execute("command-id") + + decoy.verify( + action_dispatcher.dispatch( + UpdateCommandAction(private_result=None, command=running_command) + ), + action_dispatcher.dispatch( + UpdateCommandAction(private_result=None, command=running_command_with_notes) + ), + action_dispatcher.dispatch( + FailCommandAction( + command_id="command-id", + error_id="error-id", + failed_at=datetime(year=2023, month=3, day=3), + error=matchers.ErrorMatching(PythonException, match="oh no"), + ) + ), + ) diff --git a/api/tests/opentrons/protocol_engine/execution/test_pipetting_handler.py b/api/tests/opentrons/protocol_engine/execution/test_pipetting_handler.py index bcb61324ad0..b087084abff 100644 --- a/api/tests/opentrons/protocol_engine/execution/test_pipetting_handler.py +++ b/api/tests/opentrons/protocol_engine/execution/test_pipetting_handler.py @@ -21,6 +21,8 @@ InvalidPushOutVolumeError, InvalidDispenseVolumeError, ) +from opentrons.protocol_engine.notes import CommandNoteAdder, CommandNote +from ..note_utils import CommandNoteMatcher @pytest.fixture @@ -217,6 +219,7 @@ async def test_hw_aspirate_in_place( mock_state_view: StateView, mock_hardware_api: HardwareAPI, hardware_subject: HardwarePipettingHandler, + mock_command_note_adder: CommandNoteAdder, ) -> None: """Should set flow_rate and call hardware_api aspirate.""" decoy.when(mock_state_view.pipettes.get_working_volume("pipette-id")).then_return( @@ -247,7 +250,10 @@ async def test_hw_aspirate_in_place( ) result = await hardware_subject.aspirate_in_place( - pipette_id="pipette-id", volume=25, flow_rate=2.5 + pipette_id="pipette-id", + volume=25, + flow_rate=2.5, + command_note_adder=mock_command_note_adder, ) assert result == 25 @@ -324,7 +330,7 @@ def test_virtual_get_is_ready_to_aspirate( async def test_virtual_aspirate_in_place( - mock_state_view: StateView, decoy: Decoy + mock_state_view: StateView, decoy: Decoy, mock_command_note_adder: CommandNoteAdder ) -> None: """Should return the volume.""" decoy.when( @@ -342,7 +348,10 @@ async def test_virtual_aspirate_in_place( ) result = await subject.aspirate_in_place( - pipette_id="pipette-id", volume=2, flow_rate=5 + pipette_id="pipette-id", + volume=2, + flow_rate=5, + command_note_adder=mock_command_note_adder, ) assert result == 2 @@ -408,7 +417,7 @@ async def test_virtual_dispense_in_place_raises_no_tip( async def test_virtual_aspirate_validate_tip_attached( - mock_state_view: StateView, decoy: Decoy + mock_state_view: StateView, decoy: Decoy, mock_command_note_adder: CommandNoteAdder ) -> None: """Should raise an error that a tip is not attached.""" subject = VirtualPipettingHandler(state_view=mock_state_view) @@ -420,7 +429,12 @@ async def test_virtual_aspirate_validate_tip_attached( with pytest.raises( TipNotAttachedError, match="Cannot perform aspirate without a tip attached" ): - await subject.aspirate_in_place("pipette-id", volume=20, flow_rate=1) + await subject.aspirate_in_place( + "pipette-id", + volume=20, + flow_rate=1, + command_note_adder=mock_command_note_adder, + ) async def test_virtual_dispense_validate_tip_attached( @@ -446,6 +460,7 @@ async def test_aspirate_volume_validation( mock_state_view: StateView, mock_hardware_api: HardwareAPI, hardware_subject: HardwarePipettingHandler, + mock_command_note_adder: CommandNoteAdder, ) -> None: """It should validate the input volume, possibly adjusting it for rounding error. @@ -490,13 +505,30 @@ async def test_aspirate_volume_validation( for subject in [virtual_subject, hardware_subject]: assert ( await subject.aspirate_in_place( - pipette_id="pipette-id", volume=ok_volume, flow_rate=1 + pipette_id="pipette-id", + volume=ok_volume, + flow_rate=1, + command_note_adder=mock_command_note_adder, ) == expected_adjusted_volume ) + decoy.verify( + mock_command_note_adder( + cast( + CommandNote, + CommandNoteMatcher( + matching_noteKind_regex="warning", + matching_shortMessage_regex="Aspirate clamped to 1 µL", + ), + ) + ) + ) with pytest.raises(InvalidAspirateVolumeError): await subject.aspirate_in_place( - pipette_id="pipette-id", volume=not_ok_volume, flow_rate=1 + pipette_id="pipette-id", + volume=not_ok_volume, + flow_rate=1, + command_note_adder=mock_command_note_adder, ) diff --git a/api/tests/opentrons/protocol_engine/note_utils.py b/api/tests/opentrons/protocol_engine/note_utils.py new file mode 100644 index 00000000000..0ca3af9ccca --- /dev/null +++ b/api/tests/opentrons/protocol_engine/note_utils.py @@ -0,0 +1,63 @@ +"""Test utilities for dealing with notes.""" +import re +from typing import Optional +from opentrons.protocol_engine.notes import CommandNote + + +class CommandNoteMatcher: + """Decoy matcher for notes instances.""" + + def __init__( + self, + matching_noteKind_regex: Optional[str] = None, + matching_shortMessage_regex: Optional[str] = None, + matching_longMessage_regex: Optional[str] = None, + matching_source_regex: Optional[str] = None, + ) -> None: + """Build a CommandNoteMatcher. All provided arguments are checked with re.search.""" + self._matching_noteKind_regex = ( + re.compile(matching_noteKind_regex) + if matching_noteKind_regex is not None + else None + ) + self._matching_shortMessage_regex = ( + re.compile(matching_shortMessage_regex) + if matching_shortMessage_regex is not None + else None + ) + self._matching_longMessage_regex = ( + re.compile(matching_longMessage_regex) + if matching_longMessage_regex is not None + else None + ) + self._matching_source_regex = ( + re.compile(matching_source_regex) + if matching_source_regex is not None + else None + ) + + def __eq__(self, other: object) -> bool: + """Called by Decoy. returns True on a match, False otherwise.""" + if not isinstance(other, CommandNote): + return False + if ( + self._matching_noteKind_regex is not None + and not self._matching_noteKind_regex.search(other.noteKind) + ): + return False + if ( + self._matching_shortMessage_regex is not None + and not self._matching_shortMessage_regex.search(other.shortMessage) + ): + return False + if ( + self._matching_longMessage_regex is not None + and not self._matching_longMessage_regex.search(other.longMessage) + ): + return False + if ( + self._matching_source_regex is not None + and not self._matching_source_regex.search(other.source) + ): + return False + return True diff --git a/robot-server/tests/runs/router/test_commands_router.py b/robot-server/tests/runs/router/test_commands_router.py index cc06ddd621f..fa5e47ada9a 100644 --- a/robot-server/tests/runs/router/test_commands_router.py +++ b/robot-server/tests/runs/router/test_commands_router.py @@ -8,6 +8,7 @@ CommandSlice, CurrentCommand, ProtocolEngine, + CommandNote, commands as pe_commands, errors as pe_errors, ) @@ -249,7 +250,7 @@ async def test_get_run_commands( decoy: Decoy, mock_run_data_manager: RunDataManager ) -> None: """It should return a list of all commands in a run.""" - long_note = pe_commands.CommandNote( + long_note = CommandNote( noteKind="warning", shortMessage="this is a warning.", longMessage=""" @@ -261,7 +262,7 @@ async def test_get_run_commands( """, source="test", ) - unenumed_note = pe_commands.CommandNote( + unenumed_note = CommandNote( noteKind="lahsdlasd", shortMessage="Oh no", longMessage="its a notekind not in the enum", From 7689521103796ee548cea6503ad1f6b6503c0cd9 Mon Sep 17 00:00:00 2001 From: Jamey Huffnagle Date: Thu, 14 Mar 2024 16:09:28 -0400 Subject: [PATCH 4/5] refactor(app): borderRadius2 override (#14660) Closes EXEC-330 --- components/src/atoms/CheckboxField/index.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/src/atoms/CheckboxField/index.tsx b/components/src/atoms/CheckboxField/index.tsx index 00cb643f9e7..6cf761e38dc 100644 --- a/components/src/atoms/CheckboxField/index.tsx +++ b/components/src/atoms/CheckboxField/index.tsx @@ -1,7 +1,7 @@ import * as React from 'react' import { css } from 'styled-components' import { SPACING, TYPOGRAPHY } from '../../ui-style-constants' -import { COLORS } from '../../helix-design-system' +import { COLORS, BORDERS } from '../../helix-design-system' import { Flex, Box } from '../../primitives' import { Icon } from '../../icons' import { ALIGN_CENTER, JUSTIFY_CENTER, SIZE_1 } from '../../styles' @@ -128,7 +128,7 @@ export function CheckboxField(props: CheckboxFieldProps): JSX.Element { From 1096a6a35068797ea3286ca21e2cba813038f5f3 Mon Sep 17 00:00:00 2001 From: Nick Diehl <47604184+ncdiehl11@users.noreply.github.com> Date: Thu, 14 Mar 2024 20:25:50 -0400 Subject: [PATCH 5/5] fix(app): firmware update in progress modal graphic (#14484) closes RQA-2343 and EXEC-329 Co-authored-by: Jamey Huffnagle --- .../__tests__/FirmwareUpdateModal.test.tsx | 4 ++- .../organisms/FirmwareUpdateModal/index.tsx | 33 ++++++++----------- 2 files changed, 17 insertions(+), 20 deletions(-) diff --git a/app/src/organisms/FirmwareUpdateModal/__tests__/FirmwareUpdateModal.test.tsx b/app/src/organisms/FirmwareUpdateModal/__tests__/FirmwareUpdateModal.test.tsx index 4ef3942e413..6c49288b30e 100644 --- a/app/src/organisms/FirmwareUpdateModal/__tests__/FirmwareUpdateModal.test.tsx +++ b/app/src/organisms/FirmwareUpdateModal/__tests__/FirmwareUpdateModal.test.tsx @@ -119,12 +119,13 @@ describe('FirmwareUpdateModal', () => { vi.advanceTimersByTime(3000) }) screen.getByText('Firmware is up to date.') + screen.getByLabelText('check') act(() => { vi.advanceTimersByTime(3000) }) await waitFor(() => expect(props.proceed).toHaveBeenCalled()) }) - it('does not render text or a progress bar until instrument update status is known', () => { + it('does not render text until instrument update status is known', () => { vi.mocked(useSubsystemUpdateQuery).mockReturnValue({ data: { data: { @@ -159,6 +160,7 @@ describe('FirmwareUpdateModal', () => { vi.advanceTimersByTime(3000) }) screen.getByText('A firmware update is required, instrument is updating') + screen.getByLabelText('spinner') expect(updateSubsystem).toHaveBeenCalled() }) it('calls refetch instruments and then proceed once update is complete', async () => { diff --git a/app/src/organisms/FirmwareUpdateModal/index.tsx b/app/src/organisms/FirmwareUpdateModal/index.tsx index ceaf940ea90..f669b871445 100644 --- a/app/src/organisms/FirmwareUpdateModal/index.tsx +++ b/app/src/organisms/FirmwareUpdateModal/index.tsx @@ -9,7 +9,6 @@ import { Icon, RESPONSIVENESS, JUSTIFY_CENTER, - BORDERS, COLORS, } from '@opentrons/components' import { @@ -17,7 +16,6 @@ import { useSubsystemUpdateQuery, useUpdateSubsystemMutation, } from '@opentrons/react-api-client' -import { ProgressBar } from '../../atoms/ProgressBar' import { StyledText } from '../../atoms/text' import { BadGripper, BadPipette, Subsystem } from '@opentrons/api-client' @@ -55,11 +53,6 @@ const MODAL_STYLE = css` height: 31.5625rem; } ` -const OUTER_STYLES = css` - border-radius: ${BORDERS.borderRadius16}; - background: ${COLORS.grey30}; - width: 13.374rem; -` const SPINNER_STYLE = css` color: ${COLORS.grey50}; @@ -81,7 +74,7 @@ export const FirmwareUpdateModal = ( isOnDevice, } = props const [updateId, setUpdateId] = React.useState(null) - const [firmwareText, setFirmwareText] = React.useState('') + const [firmwareText, setFirmwareText] = React.useState(null) const { data: attachedInstruments, refetch: refetchInstruments, @@ -113,7 +106,6 @@ export const FirmwareUpdateModal = ( }, []) const { data: updateData } = useSubsystemUpdateQuery(updateId) const status = updateData?.data.updateStatus - const percentComplete = updateData?.data.updateProgress ?? 0 React.useEffect(() => { if ((status != null || updateNeeded) && firmwareText !== description) { @@ -140,24 +132,27 @@ export const FirmwareUpdateModal = ( return ( - - {firmwareText.length ? firmwareText : 'Checking for updates...'} - - {status != null || updateNeeded ? ( - - ) : null} - {firmwareText.length ? null : ( + {status != null || updateNeeded || !firmwareText ? ( + ) : ( + )} + + {firmwareText ?? 'Checking for updates...'} + ) }