From dd5a6a62102ea0a2d6782ea23ecad5e80a553c88 Mon Sep 17 00:00:00 2001
From: Jethary Rader <66035149+jerader@users.noreply.github.com>
Date: Thu, 9 May 2024 15:27:46 -0400
Subject: [PATCH] refactor(protocol-designer): tiprack option redesign to not
have scroll (#15141)
closes RQA-2681
---
components/src/forms/Select.tsx | 5 +-
.../FilePipettesModal/TiprackOption.tsx | 104 ++++++++++++++----
.../FilePipettesModal/TiprackSelect.tsx | 43 +++++---
.../__tests__/TiprackOptions.test.tsx | 27 +++--
4 files changed, 132 insertions(+), 47 deletions(-)
diff --git a/components/src/forms/Select.tsx b/components/src/forms/Select.tsx
index 6eafc8cc558..9e2b3d2082c 100644
--- a/components/src/forms/Select.tsx
+++ b/components/src/forms/Select.tsx
@@ -118,7 +118,10 @@ function DropdownIndicator(
[styles.flipped]: props.selectProps.menuIsOpen,
})}
>
-
+
)
diff --git a/protocol-designer/src/components/modals/FilePipettesModal/TiprackOption.tsx b/protocol-designer/src/components/modals/FilePipettesModal/TiprackOption.tsx
index 8908d0e7614..086966230e3 100644
--- a/protocol-designer/src/components/modals/FilePipettesModal/TiprackOption.tsx
+++ b/protocol-designer/src/components/modals/FilePipettesModal/TiprackOption.tsx
@@ -1,41 +1,99 @@
import * as React from 'react'
+import { useTranslation } from 'react-i18next'
+import { css } from 'styled-components'
import {
Flex,
- Text,
- Icon,
DIRECTION_ROW,
COLORS,
SPACING,
ALIGN_CENTER,
+ StyledText,
+ BORDERS,
+ useHoverTooltip,
+ Tooltip,
} from '@opentrons/components'
interface TiprackOptionProps {
onClick: React.MouseEventHandler
isSelected: boolean
+ isDisabled: boolean
text: React.ReactNode
}
export function TiprackOption(props: TiprackOptionProps): JSX.Element {
- const { text, onClick, isSelected } = props
+ const { text, onClick, isSelected, isDisabled } = props
+ const { t } = useTranslation('tooltip')
+ const [targetProps, tooltipProps] = useHoverTooltip()
+
+ const OPTION_STYLE = css`
+ background-color: ${COLORS.white};
+ border-radius: ${BORDERS.borderRadius8};
+ border: 1px ${BORDERS.styleSolid} ${COLORS.grey30};
+
+ &:hover {
+ background-color: ${COLORS.grey10};
+ border: 1px ${BORDERS.styleSolid} ${COLORS.grey35};
+ }
+
+ &:focus {
+ outline: 2px ${BORDERS.styleSolid} ${COLORS.blue50};
+ outline-offset: 3px;
+ }
+ `
+
+ const OPTION_SELECTED_STYLE = css`
+ ${OPTION_STYLE}
+ background-color: ${COLORS.blue10};
+ border: 1px ${BORDERS.styleSolid} ${COLORS.blue50};
+
+ &:hover {
+ border: 1px ${BORDERS.styleSolid} ${COLORS.blue50};
+ box-shadow: 0px 1px 3px 0px rgba(0, 0, 0, 0.2);
+ }
+ `
+
+ const OPTION_DISABLED_STYLE = css`
+ ${OPTION_STYLE}
+ background-color: ${COLORS.white};
+ border: 1px ${BORDERS.styleSolid} ${COLORS.grey30};
+ &:hover {
+ border: 1px ${BORDERS.styleSolid} ${COLORS.grey30};
+ background-color: ${COLORS.white};
+ }
+ `
+
+ let optionStyle
+ if (isDisabled) {
+ optionStyle = OPTION_DISABLED_STYLE
+ } else if (isSelected) {
+ optionStyle = OPTION_SELECTED_STYLE
+ } else {
+ optionStyle = OPTION_STYLE
+ }
+
return (
-
-
- {text}
-
+ <>
+
+ {text}
+
+ {isDisabled ? (
+ {t('disabled_no_space_pipette')}
+ ) : null}
+ >
)
}
diff --git a/protocol-designer/src/components/modals/FilePipettesModal/TiprackSelect.tsx b/protocol-designer/src/components/modals/FilePipettesModal/TiprackSelect.tsx
index 8aa608796ec..8c77e315531 100644
--- a/protocol-designer/src/components/modals/FilePipettesModal/TiprackSelect.tsx
+++ b/protocol-designer/src/components/modals/FilePipettesModal/TiprackSelect.tsx
@@ -1,5 +1,5 @@
import * as React from 'react'
-import { Flex, DIRECTION_COLUMN } from '@opentrons/components'
+import { Flex, DIRECTION_COLUMN, SPACING } from '@opentrons/components'
import { TiprackOption } from './TiprackOption'
import type { Mount } from '@opentrons/components'
import type { FormPipettesByMount } from '../../../step-forms'
@@ -30,21 +30,32 @@ export const TiprackSelect = (
return (
- {tiprackOptions.map(option => (
- {
- const updatedValues = selectedValues?.includes(option.value)
- ? selectedValues.filter(value => value !== option.value)
- : [...(selectedValues ?? []), option.value]
- onSetFieldValue(
- `pipettesByMount.${mount}.tiprackDefURI`,
- updatedValues.slice(0, 3)
- )
- }}
- />
+ {tiprackOptions.map((option, index) => (
+
+ {
+ const updatedValues = selectedValues?.includes(option.value)
+ ? selectedValues.filter(value => value !== option.value)
+ : [...(selectedValues ?? []), option.value]
+ onSetFieldValue(
+ `pipettesByMount.${mount}.tiprackDefURI`,
+ updatedValues.slice(0, 3)
+ )
+ }}
+ />
+
))}
)
diff --git a/protocol-designer/src/components/modals/FilePipettesModal/__tests__/TiprackOptions.test.tsx b/protocol-designer/src/components/modals/FilePipettesModal/__tests__/TiprackOptions.test.tsx
index 6b9004a2472..27810c71176 100644
--- a/protocol-designer/src/components/modals/FilePipettesModal/__tests__/TiprackOptions.test.tsx
+++ b/protocol-designer/src/components/modals/FilePipettesModal/__tests__/TiprackOptions.test.tsx
@@ -1,8 +1,8 @@
import * as React from 'react'
import { vi, describe, beforeEach, it, expect } from 'vitest'
-import { screen } from '@testing-library/react'
+import { BORDERS, COLORS } from '@opentrons/components'
+import { fireEvent, screen } from '@testing-library/react'
import { renderWithProviders } from '../../../../__testing-utils__'
-import { COLORS } from '@opentrons/components'
import { TiprackOption } from '../TiprackOption'
const render = (props: React.ComponentProps) => {
@@ -15,22 +15,35 @@ describe('TiprackOption', () => {
props = {
onClick: vi.fn(),
isSelected: true,
+ isDisabled: false,
text: 'mockText',
}
})
it('renders a selected tiprack option', () => {
render(props)
screen.getByText('mockText')
- expect(screen.getByLabelText('TiprackOption_checkbox-marked')).toHaveStyle(
- `color: ${COLORS.blue50}`
+ expect(screen.getByLabelText('TiprackOption_flex_mockText')).toHaveStyle(
+ `background-color: ${COLORS.blue10}`
)
+ fireEvent.click(screen.getByText('mockText'))
+ expect(props.onClick).toHaveBeenCalled()
})
it('renders an unselected tiprack option', () => {
props.isSelected = false
render(props)
screen.getByText('mockText')
- expect(
- screen.getByLabelText('TiprackOption_checkbox-blank-outline')
- ).toHaveStyle(`color: ${COLORS.grey50}`)
+ expect(screen.getByLabelText('TiprackOption_flex_mockText')).toHaveStyle(
+ `background-color: ${COLORS.white}`
+ )
+ fireEvent.click(screen.getByText('mockText'))
+ expect(props.onClick).toHaveBeenCalled()
+ })
+ it('renders a disabled tiprack option', () => {
+ props.isSelected = false
+ props.isDisabled = true
+ render(props)
+ expect(screen.getByLabelText('TiprackOption_flex_mockText')).toHaveStyle(
+ `border: 1px ${BORDERS.styleSolid} ${COLORS.grey30}`
+ )
})
})