Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(protocol-designer) add screen too small overlay #16604

Merged
merged 2 commits into from
Oct 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions components/src/modals/ModalShell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ export interface ModalShellProps extends StyleProps {
position?: Position
/** Optional visible overlay */
showOverlay?: boolean
/** Optional remove padding */
noPadding?: boolean
}

/**
Expand All @@ -58,6 +60,7 @@ export function ModalShell(props: ModalShellProps): JSX.Element {
zIndexOverlay = 1,
position = 'center',
showOverlay = true,
noPadding = false,
...styleProps
} = props

Expand All @@ -71,7 +74,7 @@ export function ModalShell(props: ModalShellProps): JSX.Element {
if (onOutsideClick != null) onOutsideClick(e)
}}
>
<ContentArea zIndex={zIndex} position={position}>
<ContentArea zIndex={zIndex} position={position} noPadding={noPadding}>
<ModalArea
aria-label="ModalShell_ModalArea"
isFullPage={fullPage}
Expand Down Expand Up @@ -102,7 +105,11 @@ const Overlay = styled.div<{ zIndex: string | number; showOverlay: boolean }>`
cursor: ${CURSOR_DEFAULT};
`

const ContentArea = styled.div<{ zIndex: string | number; position: Position }>`
const ContentArea = styled.div<{
zIndex: string | number
position: Position
noPadding: boolean
}>`
display: flex;
position: ${POSITION_ABSOLUTE};
align-items: ${({ position }) =>
Expand All @@ -116,7 +123,7 @@ const ContentArea = styled.div<{ zIndex: string | number; position: Position }>`
width: 100%;
height: 100%;
z-index: ${({ zIndex }) => zIndex};
padding: ${SPACING.spacing16};
padding: ${({ noPadding }) => (noPadding ? 0 : SPACING.spacing16)};
`

const ModalArea = styled.div<
Expand Down
4 changes: 4 additions & 0 deletions protocol-designer/src/ProtocolEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import { GateModal } from './organisms/GateModal'
import { CreateFileWizard } from './components/modals/CreateFileWizard'
import { AnnouncementModal } from './organisms'
import { ProtocolRoutes } from './ProtocolRoutes'
import { useScreenSizeCheck } from './resources/useScreenSizeCheck'
import { DisabledScreen } from './organisms/DisabledScreen'

import styles from './components/ProtocolEditor.module.css'
import './css/reset.module.css'
Expand All @@ -29,6 +31,7 @@ const showGateModal =

function ProtocolEditorComponent(): JSX.Element {
const enableRedesign = useSelector(getEnableRedesign)
const isValidSize = useScreenSizeCheck()

return (
<div
Expand All @@ -38,6 +41,7 @@ function ProtocolEditorComponent(): JSX.Element {
<TopPortalRoot />
{enableRedesign ? (
<Flex flexDirection={DIRECTION_COLUMN}>
{!isValidSize && <DisabledScreen />}
<HashRouter>
<ProtocolRoutes />
</HashRouter>
Expand Down
4 changes: 3 additions & 1 deletion protocol-designer/src/assets/localization/en/shared.json
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@
"reject": "Reject",
"reset_hints_and_tips": "Reset all hints and tips notifications",
"reset_hints": "Reset hints",
"resize_your_browser": "Resize your browser to at least 600px wide and 650px tall to continue editing your protocol",
"review_our_privacy_policy": "You can adjust this setting at any time by clicking on the settings icon. Find detailed information in our <link1>privacy policy</link1>.",
"right": "Right",
"save": "Save",
Expand Down Expand Up @@ -135,5 +136,6 @@
"we_are_improving": "In order to improve our products, Opentrons would like to collect data related to your use of Protocol Designer. With your consent, Opentrons will collect and store analytics and session data, including through the use of cookies and similar technologies, solely for the purpose enhancing our products. Find detailed information in our <link1>privacy policy</link1>. By using Protocol Designer, you consent to the Opentrons <link2>EULA</link2>.",
"welcome": "Welcome to Protocol Designer!",
"opentrons_collects_data": "In order to improve our products, Opentrons would like to collect data related to your use of Protocol Designer. With your consent, Opentrons will collect and store analytics and session data, including through the use of cookies and similar technologies, solely for the purpose enhancing our products.",
"yes": "Yes"
"yes": "Yes",
"your_screen_is_too_small": "Your browser size is too small"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { describe, it, expect } from 'vitest'
import { screen } from '@testing-library/react'
import { COLORS } from '@opentrons/components'

import { i18n } from '../../../assets/localization'
import { renderWithProviders } from '../../../__testing-utils__'
import { DisabledScreen } from '..'

const render = () => {
return renderWithProviders(<DisabledScreen />, { i18nInstance: i18n })
}

describe('DisabledScreen', () => {
it('should render icon and text', () => {
render()
screen.getByTestId('browser_icon_in_DisabledScreen')
screen.getByText('Your browser size is too small')
screen.getByText(
'Resize your browser to at least 600px wide and 650px tall to continue editing your protocol'
)
})

it('should render background with transparent', () => {
render()
expect(screen.getByLabelText('BackgroundOverlay_ModalShell')).toHaveStyle(
`background-color: ${COLORS.black90}${COLORS.opacity40HexCode}`
)
})

it('should render white text', () => {
render()
expect(screen.getByText('Your browser size is too small')).toHaveStyle(
`color: ${COLORS.white}`
)
expect(
screen.getByText(
'Resize your browser to at least 600px wide and 650px tall to continue editing your protocol'
)
).toHaveStyle(`color: ${COLORS.white}`)
})
})
60 changes: 60 additions & 0 deletions protocol-designer/src/organisms/DisabledScreen/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { useTranslation } from 'react-i18next'
import { createPortal } from 'react-dom'
import {
ALIGN_CENTER,
COLORS,
DIRECTION_COLUMN,
Flex,
Icon,
JUSTIFY_CENTER,
ModalShell,
OVERFLOW_HIDDEN,
SPACING,
StyledText,
TYPOGRAPHY,
} from '@opentrons/components'
import { getTopPortalEl } from '../../components/portals/TopPortal'

export function DisabledScreen(): JSX.Element {
const { t } = useTranslation('shared')

return createPortal(
<ModalShell
backgroundColor={`${COLORS.black90}${COLORS.opacity40HexCode}`}
overflow={OVERFLOW_HIDDEN}
noPadding
>
<Flex
flexDirection={DIRECTION_COLUMN}
gridGap={SPACING.spacing16}
width="100vw"
height="100vh"
alignItems={ALIGN_CENTER}
justifyContent={JUSTIFY_CENTER}
paddingX={SPACING.spacing80}
>
<Icon
name="browser"
size="2.5rem"
color={COLORS.white}
data-testid="browser_icon_in_DisabledScreen"
/>
<Flex
flexDirection={DIRECTION_COLUMN}
gridGap={SPACING.spacing4}
alignItems={ALIGN_CENTER}
justifyContent={JUSTIFY_CENTER}
textAlign={TYPOGRAPHY.textAlignCenter}
>
<StyledText desktopStyle="bodyDefaultSemiBold" color={COLORS.white}>
{t('your_screen_is_too_small')}
</StyledText>
<StyledText desktopStyle="bodyDefaultRegular" color={COLORS.white}>
{t('resize_your_browser')}
</StyledText>
</Flex>
</Flex>
</ModalShell>,
getTopPortalEl()
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { describe, it, vi, expect } from 'vitest'
import { renderHook } from '@testing-library/react'
import { useScreenSizeCheck } from '../useScreenSizeCheck'

describe('useScreenSizeCheck', () => {
it('should return true if the window size is greater than 600px x 650px', () => {
vi.stubGlobal('innerWidth', 1440)
vi.stubGlobal('innerHeight', 900)
const { result } = renderHook(() => useScreenSizeCheck())
expect(result.current).toBe(true)
})

it('should return false if the window height is less than 650px', () => {
vi.stubGlobal('innerWidth', 1440)
vi.stubGlobal('innerHeight', 649)
window.dispatchEvent(new Event('resize'))
const { result } = renderHook(() => useScreenSizeCheck())
expect(result.current).toBe(false)
})

it('should return false if the window width is less than 600px', () => {
vi.stubGlobal('innerWidth', 599)
vi.stubGlobal('innerHeight', 900)
window.dispatchEvent(new Event('resize'))
const { result } = renderHook(() => useScreenSizeCheck())
expect(result.current).toBe(false)
})
})
27 changes: 27 additions & 0 deletions protocol-designer/src/resources/useScreenSizeCheck.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { useState, useEffect } from 'react'

const BREAKPOINT_HEIGHT = 650
const BREAKPOINT_WIDTH = 600

export const useScreenSizeCheck = (): boolean => {
const [isValidSize, setValidSize] = useState<boolean>(
window.innerWidth > BREAKPOINT_WIDTH &&
window.innerHeight > BREAKPOINT_HEIGHT
)

useEffect(() => {
const handleResize = (): void => {
setValidSize(
window.innerWidth > BREAKPOINT_WIDTH &&
window.innerHeight > BREAKPOINT_HEIGHT
)
}

window.addEventListener('resize', handleResize)
return () => {
window.removeEventListener('resize', handleResize)
}
}, [])

return isValidSize
}
Loading