diff --git a/components/src/atoms/ListItem/ListItemChildren/ListItemDescriptor.tsx b/components/src/atoms/ListItem/ListItemChildren/ListItemDescriptor.tsx index 7560bf25e5e..51d9ca9e181 100644 --- a/components/src/atoms/ListItem/ListItemChildren/ListItemDescriptor.tsx +++ b/components/src/atoms/ListItem/ListItemChildren/ListItemDescriptor.tsx @@ -1,6 +1,6 @@ import { Flex } from '../../../primitives' import { - ALIGN_CENTER, + ALIGN_FLEX_START, DIRECTION_ROW, FLEX_AUTO, JUSTIFY_SPACE_BETWEEN, @@ -22,7 +22,7 @@ export const ListItemDescriptor = ( flexDirection={DIRECTION_ROW} gridGap={SPACING.spacing8} width="100%" - alignItems={ALIGN_CENTER} + alignItems={ALIGN_FLEX_START} justifyContent={type === 'mini' ? JUSTIFY_SPACE_BETWEEN : 'none'} padding={ type === 'mini' @@ -36,7 +36,9 @@ export const ListItemDescriptor = ( > {description} - {content} + + {content} + ) } diff --git a/components/src/molecules/DropdownMenu/index.tsx b/components/src/molecules/DropdownMenu/index.tsx index d82aa20b4f8..30a02209121 100644 --- a/components/src/molecules/DropdownMenu/index.tsx +++ b/components/src/molecules/DropdownMenu/index.tsx @@ -9,7 +9,6 @@ import { DIRECTION_COLUMN, DIRECTION_ROW, JUSTIFY_SPACE_BETWEEN, - NO_WRAP, OVERFLOW_AUTO, OVERFLOW_HIDDEN, POSITION_ABSOLUTE, @@ -235,12 +234,9 @@ export function DropdownMenu(props: DropdownMenuProps): JSX.Element { font-weight: ${dropdownType === 'rounded' ? TYPOGRAPHY.pSemiBold : TYPOGRAPHY.pRegular}; - white-space: ${NO_WRAP}; - overflow: ${OVERFLOW_HIDDEN}; - text-overflow: ellipsis; `} > - + {currentOption.name} @@ -311,3 +307,12 @@ export function DropdownMenu(props: DropdownMenuProps): JSX.Element { ) } + +const MENU_TEXT_STYLE = css` + display: -webkit-box; + -webkit-box-orient: vertical; + overflow: ${OVERFLOW_HIDDEN}; + text-overflow: ellipsis; + word-wrap: break-word; + -webkit-line-clamp: 1; +` diff --git a/protocol-designer/src/pages/ProtocolOverview/LiquidDefinitions.tsx b/protocol-designer/src/pages/ProtocolOverview/LiquidDefinitions.tsx new file mode 100644 index 00000000000..03c274ce104 --- /dev/null +++ b/protocol-designer/src/pages/ProtocolOverview/LiquidDefinitions.tsx @@ -0,0 +1,71 @@ +import { useTranslation } from 'react-i18next' +import { css } from 'styled-components' +import { + ALIGN_CENTER, + DIRECTION_COLUMN, + Flex, + InfoScreen, + LiquidIcon, + ListItem, + ListItemDescriptor, + OVERFLOW_HIDDEN, + SPACING, + StyledText, +} from '@opentrons/components' + +import type { AllIngredGroupFields } from '../../labware-ingred/types' + +interface LiquidDefinitionsProps { + allIngredientGroupFields: AllIngredGroupFields +} + +export function LiquidDefinitions({ + allIngredientGroupFields, +}: LiquidDefinitionsProps): JSX.Element { + const { t } = useTranslation('protocol_overview') + return ( + + + {t('liquid_defs')} + + + {Object.keys(allIngredientGroupFields).length > 0 ? ( + Object.values(allIngredientGroupFields).map((liquid, index) => ( + + + + + {liquid.name} + + + } + content={liquid.description ?? t('na')} + /> + + )) + ) : ( + + )} + + + ) +} + +const LIQUID_DEFINITION_TEXT = css` + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: 3; + overflow: ${OVERFLOW_HIDDEN}; + text-overflow: ellipsis; +` diff --git a/protocol-designer/src/pages/ProtocolOverview/__tests__/LiquidDefinitions.test.tsx b/protocol-designer/src/pages/ProtocolOverview/__tests__/LiquidDefinitions.test.tsx new file mode 100644 index 00000000000..832cea4d800 --- /dev/null +++ b/protocol-designer/src/pages/ProtocolOverview/__tests__/LiquidDefinitions.test.tsx @@ -0,0 +1,78 @@ +import { describe, it, vi, beforeEach } from 'vitest' +import { screen } from '@testing-library/react' + +import { renderWithProviders } from '../../../__testing-utils__' +import { i18n } from '../../../assets/localization' +import { LiquidDefinitions } from '../LiquidDefinitions' + +import type { ComponentProps } from 'react' +import type { InfoScreen } from '@opentrons/components' + +vi.mock('@opentrons/components', async importOriginal => { + const actual = await importOriginal() + return { + ...actual, + InfoScreen: () =>
mock InfoScreen
, + } +}) + +const mockAllIngredientGroupFields = { + '0': { + name: 'EtOH', + displayColor: '#b925ff', + description: 'Immer fisch Hergestllter EtOH', + serialize: false, + liquidGroupId: '0', + }, + '1': { + name: '10mM Tris pH8,5', + displayColor: '#ffd600', + description: null, + serialize: false, + liquidGroupId: '1', + }, + '2': { + name: 'Amplicon PCR sample + AMPure XP beads', + displayColor: '#9dffd8', + description: '25µl Amplicon PCR + 20 µl AMPure XP beads', + serialize: false, + liquidGroupId: '2', + }, +} + +const render = (props: ComponentProps) => { + return renderWithProviders(, { + i18nInstance: i18n, + }) +} + +describe('LiquidDefinitions', () => { + let props: ComponentProps + + beforeEach(() => { + props = { + allIngredientGroupFields: {}, + } + }) + + it('should render text and InfoScreen if no liquid', () => { + render(props) + screen.getByText('Liquid Definitions') + screen.getByText('mock InfoScreen') + }) + + it('should render liquid information if there are liquids', () => { + props = { + allIngredientGroupFields: mockAllIngredientGroupFields, + } + render(props) + screen.getByText('EtOH') + screen.getByText('Immer fisch Hergestllter EtOH') + + screen.getByText('10mM Tris pH8,5') + screen.getByText('N/A') + + screen.getByText('Amplicon PCR sample + AMPure XP beads') + screen.getByText('25µl Amplicon PCR + 20 µl AMPure XP beads') + }) +}) diff --git a/protocol-designer/src/pages/ProtocolOverview/__tests__/ProtocolOverview.test.tsx b/protocol-designer/src/pages/ProtocolOverview/__tests__/ProtocolOverview.test.tsx index e77515eaba0..471898802f6 100644 --- a/protocol-designer/src/pages/ProtocolOverview/__tests__/ProtocolOverview.test.tsx +++ b/protocol-designer/src/pages/ProtocolOverview/__tests__/ProtocolOverview.test.tsx @@ -16,6 +16,7 @@ import { selectors as labwareIngredSelectors } from '../../../labware-ingred/sel import { ProtocolOverview } from '../index' import { DeckThumbnail } from '../DeckThumbnail' import { OffDeckThumbnail } from '../OffdeckThumbnail' +import { LiquidDefinitions } from '../LiquidDefinitions' import type { NavigateFunction } from 'react-router-dom' @@ -27,6 +28,8 @@ vi.mock('../../../organisms/MaterialsListModal') vi.mock('../../../labware-ingred/selectors') vi.mock('../../../organisms') vi.mock('../../../labware-ingred/selectors') +vi.mock('../LiquidDefinitions') + const mockNavigate = vi.fn() vi.mock('react-router-dom', async importOriginal => { @@ -72,6 +75,9 @@ describe('ProtocolOverview', () => { vi.mocked(OffDeckThumbnail).mockReturnValue(
mock OffdeckThumbnail
) + vi.mocked(LiquidDefinitions).mockReturnValue( +
mock LiquidDefinitions
+ ) }) it('renders each section with text', () => { @@ -101,7 +107,7 @@ describe('ProtocolOverview', () => { screen.getByText('Right pipette') screen.getByText('Extension mount') // liquids - screen.getByText('Liquid Definitions') + screen.getByText('mock LiquidDefinitions') // steps screen.getByText('Protocol steps') }) diff --git a/protocol-designer/src/pages/ProtocolOverview/index.tsx b/protocol-designer/src/pages/ProtocolOverview/index.tsx index 92c2ec27724..0009f4cf624 100644 --- a/protocol-designer/src/pages/ProtocolOverview/index.tsx +++ b/protocol-designer/src/pages/ProtocolOverview/index.tsx @@ -1,4 +1,4 @@ -import { useState, useEffect } from 'react' +import { Fragment, useState, useEffect } from 'react' import { useTranslation } from 'react-i18next' import { useNavigate } from 'react-router-dom' import { useDispatch, useSelector } from 'react-redux' @@ -16,7 +16,6 @@ import { JUSTIFY_FLEX_END, JUSTIFY_SPACE_BETWEEN, LargeButton, - LiquidIcon, ListItem, ListItemDescriptor, Modal, @@ -58,6 +57,7 @@ import { import { DeckThumbnail } from './DeckThumbnail' import { OffDeckThumbnail } from './OffdeckThumbnail' import { getWarningContent } from './UnusedModalContent' +import { LiquidDefinitions } from './LiquidDefinitions' import type { CreateCommand, PipetteName } from '@opentrons/shared-data' import type { DeckSlot } from '@opentrons/step-generation' @@ -223,8 +223,9 @@ export function ProtocolOverview(): JSX.Element { const cancelModal = (): void => { setShowExportWarningModal(false) } + return ( - <> + {showEditMetadataModal ? ( { @@ -449,41 +450,9 @@ export function ProtocolOverview(): JSX.Element { ) : null} - - - {t('liquid_defs')} - - - {Object.keys(allIngredientGroupFields).length > 0 ? ( - Object.values(allIngredientGroupFields).map( - (liquid, index) => ( - - - - - {liquid.name} - - - } - content={liquid.description ?? t('na')} - /> - - ) - ) - ) : ( - - )} - - + @@ -562,7 +531,7 @@ export function ProtocolOverview(): JSX.Element { - + ) }