diff --git a/packages/account/src/Components/account-limits/__tests__/account-limits-extra-info.spec.tsx b/packages/account/src/Components/account-limits/__tests__/account-limits-extra-info.spec.tsx index 97b0830a2cd9..c107e46a526a 100644 --- a/packages/account/src/Components/account-limits/__tests__/account-limits-extra-info.spec.tsx +++ b/packages/account/src/Components/account-limits/__tests__/account-limits-extra-info.spec.tsx @@ -1,11 +1,11 @@ import React from 'react'; import { screen, render } from '@testing-library/react'; -import { isMobile } from '@deriv/shared'; import AccountLimitsExtraInfo from '../account-limits-extra-info'; +import { useDevice } from '@deriv-com/ui'; -jest.mock('@deriv/shared', () => ({ - ...jest.requireActual('@deriv/shared'), - isMobile: jest.fn(() => true), +jest.mock('@deriv-com/ui', () => ({ + ...jest.requireActual('@deriv-com/ui'), + useDevice: jest.fn(() => ({ isDesktop: false })), })); describe('', () => { @@ -14,14 +14,14 @@ describe('', () => { expect(screen.getByText(/lorem ipsum/i)).toBeInTheDocument(); }); - it('should render PopoverComponent if isMobile is false', () => { - (isMobile as jest.Mock).mockReturnValue(false); + it('should render PopoverComponent if its not a desktop screen', () => { + (useDevice as jest.Mock).mockReturnValueOnce({ isDesktop: true }); render(); expect(screen.queryByTestId('dt_acc_limits_popover')).toHaveClass('da-account-limits__popover'); }); - it('should pass props to PopoverComponent if isMobile is false', async () => { - (isMobile as jest.Mock).mockReturnValue(false); + it('should pass props to PopoverComponent if its not a desktop screen', async () => { + (useDevice as jest.Mock).mockReturnValueOnce({ isDesktop: true }); render(); const popover = await screen.findByTestId('dt_acc_limits_popover'); expect(popover).toHaveClass('test_class'); diff --git a/packages/account/src/Components/account-limits/__tests__/account-limits.spec.tsx b/packages/account/src/Components/account-limits/__tests__/account-limits.spec.tsx index 4fb5e3c2bd3d..7ce758a1d55e 100644 --- a/packages/account/src/Components/account-limits/__tests__/account-limits.spec.tsx +++ b/packages/account/src/Components/account-limits/__tests__/account-limits.spec.tsx @@ -1,6 +1,7 @@ import React from 'react'; import { screen, render } from '@testing-library/react'; -import { formatMoney, isDesktop, isMobile } from '@deriv/shared'; +import { formatMoney } from '@deriv/shared'; +import { useDevice } from '@deriv-com/ui'; import AccountLimits from '../account-limits'; import { BrowserRouter } from 'react-router-dom'; import { StoreProvider, mockStore } from '@deriv/stores'; @@ -19,10 +20,13 @@ jest.mock('@deriv/shared/src/services/ws-methods', () => ({ useWS: () => undefined, })); +jest.mock('@deriv-com/ui', () => ({ + ...jest.requireActual('@deriv-com/ui'), + useDevice: jest.fn(() => ({ isDesktop: true })), +})); + jest.mock('@deriv/shared', () => ({ ...jest.requireActual('@deriv/shared'), - isMobile: jest.fn(() => false), - isDesktop: jest.fn(() => true), formatMoney: jest.fn(), })); @@ -211,9 +215,8 @@ describe('', () => { expect(screen.queryByTestId('account_limits_data')).toBeInTheDocument(); }); - it('should render AccountLimitsArticle component if should_show_article is true in mobile mode', () => { - (isMobile as jest.Mock).mockReturnValue(true); - (isDesktop as jest.Mock).mockReturnValue(false); + it('should render AccountLimitsArticle component if should_show_article is true in responsive mode', () => { + (useDevice as jest.Mock).mockReturnValueOnce({ isDesktop: false }); render( @@ -225,8 +228,7 @@ describe('', () => { it('should not render AccountLimitsArticle component if should_show_article is false', () => { store = mockStore(mock); - (isMobile as jest.Mock).mockReturnValue(true); - (isDesktop as jest.Mock).mockReturnValue(false); + (useDevice as jest.Mock).mockReturnValueOnce({ isDesktop: false }); render( @@ -372,15 +374,14 @@ describe('', () => { expect(screen.getByText(/total withdrawal allowed/i)).toBeInTheDocument(); }); - it('should show limit_notice message when is_fully_authenticated is false in mobile mode', () => { + it('should show limit_notice message when is_fully_authenticated is false in responsive mode', () => { store = mockStore({ client: { ...mock.client, is_fully_authenticated: false, }, }); - (isMobile as jest.Mock).mockReturnValue(true); - (isDesktop as jest.Mock).mockReturnValue(false); + (useDevice as jest.Mock).mockReturnValueOnce({ isDesktop: false }); render( @@ -398,8 +399,7 @@ describe('', () => { is_fully_authenticated: false, }, }); - (isMobile as jest.Mock).mockReturnValue(false); - (isDesktop as jest.Mock).mockReturnValue(true); + (useDevice as jest.Mock).mockReturnValueOnce({ isDesktop: true }); render( @@ -414,8 +414,7 @@ describe('', () => { it('should show AccountLimitsArticle when should_show_article and isDesktop is true', () => { store = mockStore(mock); - (isMobile as jest.Mock).mockReturnValue(false); - (isDesktop as jest.Mock).mockReturnValue(true); + (useDevice as jest.Mock).mockReturnValueOnce({ isDesktop: true }); render( diff --git a/packages/account/src/Components/account-limits/account-limits-extra-info.tsx b/packages/account/src/Components/account-limits/account-limits-extra-info.tsx index 9fa3e8e8b456..07a1b632bd64 100644 --- a/packages/account/src/Components/account-limits/account-limits-extra-info.tsx +++ b/packages/account/src/Components/account-limits/account-limits-extra-info.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { Popover, Text } from '@deriv/components'; -import { isMobile } from '@deriv/shared'; +import { useDevice } from '@deriv-com/ui'; type TAccountLimitsExtraInfo = { message: string; @@ -8,7 +8,8 @@ type TAccountLimitsExtraInfo = { }; const AccountLimitsExtraInfo = ({ message, ...props }: TAccountLimitsExtraInfo) => { - if (isMobile()) { + const { isDesktop } = useDevice(); + if (!isDesktop) { return ( {message} diff --git a/packages/account/src/Components/account-limits/account-limits.scss b/packages/account/src/Components/account-limits/account-limits.scss index 73571f6c6dd9..3031c08d798e 100644 --- a/packages/account/src/Components/account-limits/account-limits.scss +++ b/packages/account/src/Components/account-limits/account-limits.scss @@ -2,14 +2,14 @@ $this: &; display: flex; - @include mobile { + @include mobile-or-tablet-screen { flex-direction: column; } &__table { width: calc(100% - 2.4rem); - @include mobile { + @include mobile-or-tablet-screen { width: 100%; } @@ -28,7 +28,7 @@ padding: 0.8rem 0; display: inline-flex; - @include mobile { + @include mobile-or-tablet-screen { flex-direction: column; } @@ -59,13 +59,13 @@ &-wrapper { flex: 1; + margin-inline-end: 1rem; - @include desktop { - margin-right: 1rem; - } - - @include mobile { - margin: 0 2rem 2rem; + @include mobile-or-tablet-screen { + margin-block-start: 0; + margin-inline-start: 1.6rem; + margin-block-end: 1.6rem; + margin-inline-end: 1.6rem; } } } @@ -77,18 +77,4 @@ &__popover { margin-inline-start: 0.8rem; } - - &--app-settings { - @include tablet-up { - padding: 2.4rem; - } - - @include mobile { - padding: 1.6rem 0 0; - } - - #{$this}__table { - width: 100%; - } - } } diff --git a/packages/account/src/Components/account-limits/account-limits.tsx b/packages/account/src/Components/account-limits/account-limits.tsx index 6a2e0968b61f..faa0ee1df9fe 100644 --- a/packages/account/src/Components/account-limits/account-limits.tsx +++ b/packages/account/src/Components/account-limits/account-limits.tsx @@ -1,8 +1,9 @@ import React from 'react'; import { FormikValues } from 'formik'; import clsx from 'clsx'; -import { formatMoney, isDesktop, isMobile, useIsMounted } from '@deriv/shared'; +import { formatMoney, useIsMounted } from '@deriv/shared'; import { Loading, ThemedScrollbars } from '@deriv/components'; +import { useDevice } from '@deriv-com/ui'; import { Localize, localize } from '@deriv/translations'; import { observer, useStore } from '@deriv/stores'; import DemoMessage from '../demo-message'; @@ -41,6 +42,7 @@ const AccountLimits = observer( const isMounted = useIsMounted(); const [is_loading, setLoading] = React.useState(true); const [is_overlay_shown, setIsOverlayShown] = React.useState(false); + const { isDesktop } = useDevice(); const handleGetLimitsResponse = () => { if (isMounted()) setLoading(false); @@ -117,9 +119,9 @@ const AccountLimits = observer( 'da-account-limits--app-settings': is_app_settings, })} > - {should_show_article && isMobile() && } + {should_show_article && !isDesktop && }
- + @@ -238,7 +240,7 @@ const AccountLimits = observer( )} - {should_show_article && isDesktop() && } + {should_show_article && isDesktop && } {footer_ref && } {is_overlay_shown && overlay_ref && } diff --git a/packages/account/src/Components/additional-kyc-info-modal/additional-kyc-info-form.tsx b/packages/account/src/Components/additional-kyc-info-modal/additional-kyc-info-form.tsx index 695fe4e2725b..3691c2f0ffff 100644 --- a/packages/account/src/Components/additional-kyc-info-modal/additional-kyc-info-form.tsx +++ b/packages/account/src/Components/additional-kyc-info-modal/additional-kyc-info-form.tsx @@ -1,5 +1,4 @@ import { Button, Loading, Modal, Text } from '@deriv/components'; -import { isMobile } from '@deriv/shared'; import { observer, useStore } from '@deriv/stores'; import { Localize } from '@deriv/translations'; import clsx from 'clsx'; @@ -12,18 +11,21 @@ import { FormInputField } from '../forms/form-fields'; import FormSelectField from '../forms/form-select-field'; import { getFormConfig } from './form-config'; import { TListItem } from 'Types'; +import { useDevice } from '@deriv-com/ui'; -const FormTitle = () => ( - - - -); +const FormTitle = () => { + const { isDesktop } = useDevice(); + return ( + + + + ); +}; type TAdditionalKycInfoFormProps = { setError?: React.Dispatch>; diff --git a/packages/account/src/Components/additional-kyc-info-modal/additional-kyc-info-modal.scss b/packages/account/src/Components/additional-kyc-info-modal/additional-kyc-info-modal.scss index 873a8703237f..bb9682d085d5 100644 --- a/packages/account/src/Components/additional-kyc-info-modal/additional-kyc-info-modal.scss +++ b/packages/account/src/Components/additional-kyc-info-modal/additional-kyc-info-modal.scss @@ -29,14 +29,14 @@ height: 100%; position: relative; - @include mobile { + @include mobile-or-tablet-screen { width: 100%; } &--header { margin: 1.6rem 0 2.4rem; - @include mobile { + @include mobile-or-tablet-screen { padding: 0; } } @@ -55,7 +55,7 @@ flex-direction: column; padding: 0 24.4rem; - @include mobile { + @include mobile-or-tablet-screen { padding: 0 1.6rem; } } @@ -74,7 +74,7 @@ &-action { padding: 1.6rem 2.4rem; - @include mobile { + @include mobile-or-tablet-screen { position: absolute; bottom: 0; width: 100%; @@ -82,7 +82,7 @@ } .dc-btn { - @include mobile { + @include mobile-or-tablet-screen { width: 100%; } } diff --git a/packages/account/src/Components/additional-kyc-info-modal/additional-kyc-info-modal.tsx b/packages/account/src/Components/additional-kyc-info-modal/additional-kyc-info-modal.tsx index bdaab836a1ec..6a243dbbe01d 100644 --- a/packages/account/src/Components/additional-kyc-info-modal/additional-kyc-info-modal.tsx +++ b/packages/account/src/Components/additional-kyc-info-modal/additional-kyc-info-modal.tsx @@ -1,16 +1,8 @@ -import { - DesktopWrapper, - Div100vhContainer, - InlineMessage, - MobileWrapper, - Modal, - PageOverlay, - Text, - UILoader, -} from '@deriv/components'; +import { Div100vhContainer, InlineMessage, Modal, PageOverlay, Text, UILoader } from '@deriv/components'; import { getPlatformSettings } from '@deriv/shared'; import { observer, useStore } from '@deriv/stores'; import { Localize } from '@deriv/translations'; +import { useDevice } from '@deriv-com/ui'; import React from 'react'; import AdditionalKycInfoForm from './additional-kyc-info-form'; @@ -44,6 +36,7 @@ export const AdditionalKycInfoModal = observer(() => { const { ui: { is_additional_kyc_info_modal_open: is_open, toggleAdditionalKycInfoModal }, } = useStore(); + const { isDesktop } = useDevice(); const [error, setError] = React.useState(''); const toggleModal = (e?: React.MouseEvent | React.KeyboardEvent) => { @@ -67,7 +60,7 @@ export const AdditionalKycInfoModal = observer(() => { return ( }>
- + {isDesktop ? ( { - - + ) : ( { - + )}
); diff --git a/packages/account/src/Components/address-details/__tests__/address-details.spec.tsx b/packages/account/src/Components/address-details/__tests__/address-details.spec.tsx index 9081bf080669..472168a85866 100644 --- a/packages/account/src/Components/address-details/__tests__/address-details.spec.tsx +++ b/packages/account/src/Components/address-details/__tests__/address-details.spec.tsx @@ -3,18 +3,19 @@ import { FormikProps } from 'formik'; import { act, fireEvent, render, screen, waitFor } from '@testing-library/react'; import { useDevice } from '@deriv-com/ui'; import { useStatesList } from '@deriv/hooks'; -import { isDesktop, isMobile } from '@deriv/shared'; import { StoreProvider, mockStore } from '@deriv/stores'; import AddressDetails, { TAddressDetailFormProps } from '../address-details'; -import { TStores } from '@deriv/stores/types'; import userEvent from '@testing-library/user-event'; import { splitValidationResultTypes } from 'Components/real-account-signup/helpers/utils'; +jest.mock('@deriv-com/ui', () => ({ + ...jest.requireActual('@deriv-com/ui'), + useDevice: jest.fn(() => ({ isDesktop: true })), +})); + jest.mock('@deriv/shared', () => ({ ...jest.requireActual('@deriv/shared'), getLocation: jest.fn().mockReturnValue('Default test state'), - isDesktop: jest.fn(), - isMobile: jest.fn(), makeCancellablePromise: jest.fn(() => ({ cancel: jest.fn(), promise: Promise.resolve('resolved') })), })); @@ -98,18 +99,15 @@ describe('', () => { expect(screen.queryByLabelText(address_town)).not.toBeInTheDocument(); }; - const renderComponent = ({ props = mock_props, store_config = store }) => { + const renderComponent = ({ props = mock_props }) => { return render( - + ); }; beforeEach(() => { - (isDesktop as jest.Mock).mockReturnValue(true); - (isMobile as jest.Mock).mockReturnValue(false); - (useDevice as jest.Mock).mockReturnValue({ isDesktop: true, isMobile: false }); jest.clearAllMocks(); }); @@ -124,16 +122,9 @@ describe('', () => { }); it('should render AddressDetails component for mobile', async () => { - (useDevice as jest.Mock).mockReturnValue({ isMobile: true, isDesktop: false }); - const new_store_config: TStores = { - ...store, - ui: { - ...store.ui, - is_mobile: true, - }, - }; + (useDevice as jest.Mock).mockReturnValueOnce({ isDesktop: false }); - renderComponent({ store_config: new_store_config }); + renderComponent({}); await waitFor(() => { svgCommonRenderCheck(); @@ -217,10 +208,7 @@ describe('', () => { }); it('should render AddressDetails component with states_list for mobile', async () => { - (isDesktop as jest.Mock).mockReturnValue(false); - (isMobile as jest.Mock).mockReturnValue(true); - (useDevice as jest.Mock).mockReturnValue({ isMobile: true, isDesktop: false }); - + (useDevice as jest.Mock).mockReturnValueOnce({ isDesktop: false }); (useStatesList as jest.Mock).mockReturnValue({ data: [ { text: 'State 1', value: 'State 1' }, @@ -228,14 +216,7 @@ describe('', () => { ], isFetched: true, }); - const new_store_config: TStores = { - ...store, - ui: { - ...store.ui, - is_mobile: true, - }, - }; - renderComponent({ store_config: new_store_config }); + renderComponent({}); expect(screen.getByText('Default test state')).toBeInTheDocument(); const address_state_input: HTMLInputElement = screen.getByRole('combobox'); diff --git a/packages/account/src/Components/address-details/address-details.tsx b/packages/account/src/Components/address-details/address-details.tsx index 3c187c879ec4..16ce979c0d69 100644 --- a/packages/account/src/Components/address-details/address-details.tsx +++ b/packages/account/src/Components/address-details/address-details.tsx @@ -74,6 +74,7 @@ type TAutoComplete = { * @param has_real_account - has real account * @returns react node */ + const AddressDetails = observer( ({ getCurrentStep, diff --git a/packages/account/src/Components/api-token/__tests__/api-token-table.spec.tsx b/packages/account/src/Components/api-token/__tests__/api-token-table.spec.tsx index dab9f5943a95..fd49eb9d0fe6 100644 --- a/packages/account/src/Components/api-token/__tests__/api-token-table.spec.tsx +++ b/packages/account/src/Components/api-token/__tests__/api-token-table.spec.tsx @@ -1,10 +1,15 @@ import React from 'react'; import { screen, render } from '@testing-library/react'; +import { useDevice } from '@deriv-com/ui'; import ApiTokenContext from '../api-token-context'; import ApiTokenTable from '../api-token-table'; -import { StoreProvider, mockStore } from '@deriv/stores'; import { TApiContext } from '../../../Types'; +jest.mock('@deriv-com/ui', () => ({ + ...jest.requireActual('@deriv-com/ui'), + useDevice: jest.fn(() => ({ isDesktop: true })), +})); + describe('ApiTokenTable', () => { const mock_props: TApiContext = { api_tokens: [ @@ -17,15 +22,12 @@ describe('ApiTokenTable', () => { ], deleteToken: jest.fn(), }; - const store = mockStore({}); - const renderComponent = ({ props = mock_props, store_config = store }) => { + const renderComponent = () => { render( - - - - - + + + ); }; @@ -48,21 +50,17 @@ describe('ApiTokenTable', () => { it('should render ApiTokenTable', () => { expectedTexts.push('Last used'); - renderComponent({}); + renderComponent(); expect(screen.getByText('Token 1')).not.toHaveClass('da-api-token__scope-item--name'); expectedTexts.forEach(text => { expect(screen.getByText(text)).toBeInTheDocument(); }); }); - it('should render in mobile view', () => { - const mock_store = mockStore({ - ui: { - is_mobile: true, - }, - }); + it('should render in responsive view', () => { + (useDevice as jest.Mock).mockReturnValue({ isDesktop: false }); expectedTexts.push('Last Used'); - renderComponent({ store_config: mock_store }); + renderComponent(); expect(screen.getByText('Token 1')).toHaveClass('da-api-token__scope-item--name'); expectedTexts.forEach(text => { expect(screen.getByText(text)).toBeInTheDocument(); @@ -78,7 +76,7 @@ describe('ApiTokenTable', () => { last_used: '', }, ]; - renderComponent({}); + renderComponent(); expect(screen.getByText('Never')).toBeInTheDocument(); }); }); diff --git a/packages/account/src/Components/api-token/api-token-delete-button.tsx b/packages/account/src/Components/api-token/api-token-delete-button.tsx index 7ef61daa58c6..f3493bb07efa 100644 --- a/packages/account/src/Components/api-token/api-token-delete-button.tsx +++ b/packages/account/src/Components/api-token/api-token-delete-button.tsx @@ -1,9 +1,10 @@ import React from 'react'; import { Button, Icon, Modal, Text, Popover } from '@deriv/components'; -import { isDesktop, useIsMounted } from '@deriv/shared'; +import { useIsMounted } from '@deriv/shared'; import { Localize } from '@deriv/translations'; import ApiTokenContext from './api-token-context'; import { TPopoverAlignment, TFormattedToken, TApiContext } from 'Types'; +import { useDevice } from '@deriv-com/ui'; type TApiTokenDeleteButton = { popover_alignment?: TPopoverAlignment; @@ -11,6 +12,7 @@ type TApiTokenDeleteButton = { }; const ApiTokenDeleteButton = ({ token, popover_alignment = 'left' }: TApiTokenDeleteButton) => { + const { isDesktop } = useDevice(); const { deleteToken } = React.useContext(ApiTokenContext); const [is_deleting, setIsDeleting] = React.useState(false); const [is_loading, setIsLoading] = React.useState(false); @@ -18,16 +20,16 @@ const ApiTokenDeleteButton = ({ token, popover_alignment = 'left' }: TApiTokenDe const isMounted = useIsMounted(); const getConfirmationBeforeDelete = () => { - if (isDesktop()) setIsPopoverOpen(false); + if (isDesktop) setIsPopoverOpen(false); setIsDeleting(true); }; const onMouseEnterHandler = () => { - if (!is_deleting && isDesktop()) setIsPopoverOpen(true); + if (!is_deleting && isDesktop) setIsPopoverOpen(true); }; const onMouseLeaveHandler = () => { - if (!is_deleting && isDesktop()) setIsPopoverOpen(false); + if (!is_deleting && isDesktop) setIsPopoverOpen(false); }; const onCancel = () => setIsDeleting(false); diff --git a/packages/account/src/Components/api-token/api-token-table.tsx b/packages/account/src/Components/api-token/api-token-table.tsx index c811497b692f..522ff6af6cd1 100644 --- a/packages/account/src/Components/api-token/api-token-table.tsx +++ b/packages/account/src/Components/api-token/api-token-table.tsx @@ -2,6 +2,7 @@ import React from 'react'; import { Text } from '@deriv/components'; import { formatDate } from '@deriv/shared'; import { Localize, localize } from '@deriv/translations'; +import { useDevice } from '@deriv-com/ui'; import ApiTokenContext from './api-token-context'; import ApiTokenDeleteButton from './api-token-delete-button'; import ApiTokenTableRow from './api-token-table-row'; @@ -9,12 +10,10 @@ import ApiTokenTableRowHeader from './api-token-table-row-header'; import ApiTokenTableRowScopesCell from './api-token-table-row-scopes-cell'; import ApiTokenTableRowTokenCell from './api-token-table-row-token-cell'; import { TApiContext, TToken } from 'Types'; -import { useStore } from '@deriv/stores'; const ApiTokenTable = () => { const { api_tokens } = React.useContext(ApiTokenContext); - const { ui } = useStore(); - const { is_mobile } = ui; + const { isDesktop } = useDevice(); const formatTokenScopes = (str: string) => { const replace_filter = str.replace(/[-_]/g, ' '); @@ -50,7 +49,7 @@ const ApiTokenTable = () => { token: token.token, }; }; - if (is_mobile) { + if (!isDesktop) { return ( {api_tokens?.map((token_data: TToken) => { diff --git a/packages/account/src/Components/article/article.scss b/packages/account/src/Components/article/article.scss index cbdeaef67e0d..1e5ce6e1be85 100644 --- a/packages/account/src/Components/article/article.scss +++ b/packages/account/src/Components/article/article.scss @@ -5,15 +5,11 @@ height: fit-content; border-radius: 8px; - @include mobile { + @include mobile-or-tablet-screen { width: calc(100% - 3.2rem); margin: 1.6rem; } - @include tablet-up { - margin-left: 1.2rem; - } - &__header { margin-bottom: 0.8rem; } diff --git a/packages/account/src/Components/currency-selector/__tests__/currency-selector.spec.tsx b/packages/account/src/Components/currency-selector/__tests__/currency-selector.spec.tsx index aa407be0d915..24534e4b3418 100644 --- a/packages/account/src/Components/currency-selector/__tests__/currency-selector.spec.tsx +++ b/packages/account/src/Components/currency-selector/__tests__/currency-selector.spec.tsx @@ -5,6 +5,7 @@ import { fireEvent, screen, render, waitFor } from '@testing-library/react'; import { StoreProvider, mockStore } from '@deriv/stores'; import CurrencySelector from '../currency-selector'; import { TStores } from '@deriv/stores/types'; +import { useDevice } from '@deriv-com/ui'; jest.mock('../../real-account-signup/helpers/utils.ts', () => ({ splitValidationResultTypes: jest.fn(() => ({ @@ -12,6 +13,10 @@ jest.mock('../../real-account-signup/helpers/utils.ts', () => ({ errors: {}, })), })); +jest.mock('@deriv-com/ui', () => ({ + ...jest.requireActual('@deriv-com/ui'), + useDevice: jest.fn(() => ({ isDesktop: false })), +})); describe('', () => { const mock_props: React.ComponentProps = { @@ -388,17 +393,13 @@ describe('', () => { configurable: true, value: 150, }); + (useDevice as jest.Mock).mockReturnValueOnce({ isDesktop: false }); const new_store = { ...store, client: { ...store.client, has_active_real_account: true, }, - ui: { - ...store.ui, - is_desktop: false, - is_mobile: true, - }, }; renderComponent({ store_config: new_store }); diff --git a/packages/account/src/Components/currency-selector/currency-selector.tsx b/packages/account/src/Components/currency-selector/currency-selector.tsx index 9e5933e27309..686d24271cac 100644 --- a/packages/account/src/Components/currency-selector/currency-selector.tsx +++ b/packages/account/src/Components/currency-selector/currency-selector.tsx @@ -8,6 +8,7 @@ import { localize } from '@deriv/translations'; import RadioButton from './radio-button'; import RadioButtonGroup from './radio-button-group'; import { splitValidationResultTypes } from '../real-account-signup/helpers/utils'; +import { useDevice } from '@deriv-com/ui'; export const Hr = () =>
; @@ -84,8 +85,8 @@ const CurrencySelector = observer( const has_currency = Boolean(currency); - const { real_account_signup, real_account_signup_target, resetRealAccountSignupParams, is_desktop, is_mobile } = - ui; + const { real_account_signup, real_account_signup_target, resetRealAccountSignupParams } = ui; + const { isMobile, isDesktop } = useDevice(); // Wrapped with String() to avoid type mismatch const crypto = legal_allowed_currencies.filter( @@ -182,10 +183,10 @@ const CurrencySelector = observer( {!!fiat?.length && ( @@ -248,7 +249,7 @@ const CurrencySelector = observer( )} - + { const original_module = jest.requireActual('@deriv/components'); @@ -11,12 +10,9 @@ jest.mock('@deriv/components', () => { Icon: jest.fn(() => 'mockedIcon'), }; }); -jest.mock('@deriv/shared', () => ({ - ...jest.requireActual('@deriv/shared'), - isDesktop: jest.fn(), - WS: { - getSocket: jest.fn(), - }, +jest.mock('@deriv-com/ui', () => ({ + ...jest.requireActual('@deriv-com/ui'), + useDevice: jest.fn(), })); describe('', () => { @@ -28,16 +24,9 @@ describe('', () => { files_description: '', onFileDrop: jest.fn(), }; - - (isDesktop as jest.Mock).mockReturnValue(true); + (useDevice as jest.Mock).mockReturnValue({ isDesktop: true }); jest.clearAllMocks(); }); - - const mock_store = mockStore({}); - const wrapper = ({ children }: { children: React.ReactNode }) => ( - {children} - ); - const file_size_msg = /maximum size: 8MB/i; const file_type_msg = /supported formats: JPEG, JPG, PNG, PDF, and GIF only/i; const file_warning_msg = /remember, selfies, pictures of houses, or non-related images will be rejected./i; @@ -53,12 +42,12 @@ describe('', () => { }; it('should render FileUploaderContainer component and show descriptions', () => { - render(, { wrapper }); + render(); runCommonTests(); }); it('should render FileUploaderContainer component if getSocket is not passed as prop', () => { - render(, { wrapper }); + render(); runCommonTests(); }); @@ -66,29 +55,21 @@ describe('', () => { mock_props.files_description =
Files description
; mock_props.examples =
Files failure examples
; - render(, { wrapper }); + render(); expect(screen.getByText('Files description')).toBeInTheDocument(); expect(screen.getByText('Files failure examples')).toBeInTheDocument(); }); it('should show hint message for desktop', () => { - render(, { wrapper }); + render(); expect(screen.getByText(hint_msg_desktop)).toBeInTheDocument(); expect(screen.queryByText(hint_msg_mobile)).not.toBeInTheDocument(); }); it('should show hint message for mobile', () => { - (isDesktop as jest.Mock).mockReturnValue(false); - - const mock_store = mockStore({ - ui: { - is_mobile: true, - }, - }); + (useDevice as jest.Mock).mockReturnValue({ isMobile: true }); - render(, { - wrapper: ({ children }) => {children}, - }); + render(); expect(screen.getByText(hint_msg_mobile)).toBeInTheDocument(); expect(screen.queryByText(hint_msg_desktop)).not.toBeInTheDocument(); }); diff --git a/packages/account/src/Components/file-uploader-container/__tests__/file-uploader.spec.tsx b/packages/account/src/Components/file-uploader-container/__tests__/file-uploader.spec.tsx index 13cec276214c..8ba3121dc9f4 100644 --- a/packages/account/src/Components/file-uploader-container/__tests__/file-uploader.spec.tsx +++ b/packages/account/src/Components/file-uploader-container/__tests__/file-uploader.spec.tsx @@ -1,27 +1,25 @@ import React from 'react'; import { render, screen, fireEvent, waitFor } from '@testing-library/react'; -import { isDesktop, readFiles } from '@deriv/shared'; +import { readFiles } from '@deriv/shared'; import FileUploader from '../file-uploader'; -import { StoreProvider, mockStore } from '@deriv/stores'; +import { useDevice } from '@deriv-com/ui'; jest.mock('@deriv/shared', () => ({ ...jest.requireActual('@deriv/shared'), - isDesktop: jest.fn(), compressImageFiles: jest.fn(() => Promise.resolve([{ path: 'hello.pdf' }])), readFiles: jest.fn(), })); +jest.mock('@deriv-com/ui', () => ({ + ...jest.requireActual('@deriv-com/ui'), + useDevice: jest.fn(), +})); describe('', () => { beforeEach(() => { - (isDesktop as jest.Mock).mockReturnValue(true); + (useDevice as jest.Mock).mockReturnValue({ isDesktop: true }); jest.clearAllMocks(); }); - const mock_store = mockStore({}); - const wrapper = ({ children }: { children: React.ReactNode }) => ( - {children} - ); - const props: React.ComponentProps = { onFileDrop: jest.fn(), }; @@ -32,25 +30,19 @@ describe('', () => { const click_msg = /click here to browse your files/i; it('should render FileUploader component in desktop mode', () => { - render(, { wrapper }); + render(); expect(screen.getByText(drop_click_msg)).toBeInTheDocument(); }); it('should render FileUploader component in mobile mode', () => { - (isDesktop as jest.Mock).mockReturnValue(false); - const mock_store = mockStore({ - ui: { - is_mobile: true, - }, - }); - render(, { - wrapper: ({ children }) => {children}, - }); + (useDevice as jest.Mock).mockReturnValue({ isMobile: true }); + + render(); expect(screen.getByText(click_msg)).toBeInTheDocument(); }); it('should upload supported file', async () => { - render(, { wrapper }); + render(); const file = new File(['hello'], 'hello.png', { type: 'image/png' }); @@ -64,7 +56,7 @@ describe('', () => { }); it('should show error message when unsupported file is uploaded', async () => { - render(, { wrapper }); + render(); const file = new File(['hello'], 'hello.html', { type: 'html' }); const input = screen.getByTestId('dt_file_upload_input'); @@ -76,7 +68,7 @@ describe('', () => { }); it('should show error message when multiple files are uploaded', async () => { - render(, { wrapper }); + render(); const files = [ new File(['hello'], 'hello.png', { type: 'image/png' }), @@ -91,7 +83,7 @@ describe('', () => { }); it('should show error message when larger files are uploaded', async () => { - render(, { wrapper }); + render(); const file = new File(['hello'], 'hello.png', { type: 'image/png' }); Object.defineProperty(file, 'size', { value: 1024 * 1024 * 10 }); @@ -104,7 +96,7 @@ describe('', () => { }); it('should remove the file when close icon is clicked', async () => { - render(, { wrapper }); + render(); const file = new File(['hello'], 'hello.png', { type: 'image/png' }); const input: HTMLInputElement = screen.getByTestId('dt_file_upload_input'); @@ -128,7 +120,7 @@ describe('', () => { it('upload methods should reject if readFile returns empty array ', async () => { (readFiles as jest.Mock).mockResolvedValue([]); - render(, { wrapper }); + render(); const blob = new Blob(['sample_data']); const file = new File([blob], 'hello.pdf', { type: 'application/pdf' }); diff --git a/packages/account/src/Components/file-uploader-container/file-uploader-container.tsx b/packages/account/src/Components/file-uploader-container/file-uploader-container.tsx index a41a1598109d..42c5a779fe8d 100644 --- a/packages/account/src/Components/file-uploader-container/file-uploader-container.tsx +++ b/packages/account/src/Components/file-uploader-container/file-uploader-container.tsx @@ -2,7 +2,7 @@ import React from 'react'; import { Text } from '@deriv/components'; import { Localize } from '@deriv/translations'; import FileUploader from './file-uploader'; -import { observer, useStore } from '@deriv/stores'; +import { useDevice } from '@deriv-com/ui'; type TFileUploaderContainer = { onFileDrop: (files: File[]) => void; @@ -11,32 +11,29 @@ type TFileUploaderContainer = { onError?: (error_message: string) => void; }; -const FileUploaderContainer = observer( - ({ examples, files_description, onFileDrop, onError }: TFileUploaderContainer) => { - const { - ui: { is_mobile }, - } = useStore(); - return ( -
- {files_description} - {examples} - - +const FileUploaderContainer = ({ examples, files_description, onFileDrop, onError }: TFileUploaderContainer) => { + const { isMobile } = useDevice(); + + return ( +
+ {files_description} + {examples} + + + +
+ +
+
+ + + + + -
- -
-
- - - - - - -
- ); - } -); +
+ ); +}; export default FileUploaderContainer; diff --git a/packages/account/src/Components/file-uploader-container/file-uploader.tsx b/packages/account/src/Components/file-uploader-container/file-uploader.tsx index c5a779d2cb7b..57abb8199a10 100644 --- a/packages/account/src/Components/file-uploader-container/file-uploader.tsx +++ b/packages/account/src/Components/file-uploader-container/file-uploader.tsx @@ -4,7 +4,7 @@ import { FileDropzone, Icon, Text } from '@deriv/components'; import { Localize, localize } from '@deriv/translations'; import { getSupportedFiles, max_document_size, supported_filetypes } from '@deriv/shared'; import { DropzoneOptions } from 'react-dropzone'; -import { observer, useStore } from '@deriv/stores'; +import { useDevice } from '@deriv-com/ui'; import { TFile } from '../../Types'; type THandleRejectedFiles = DropzoneOptions['onDropRejected']; @@ -14,28 +14,27 @@ type TFileUploaderProps = { onError?: (error_message: string) => void; }; -const UploadMessage = observer(() => { - const { - ui: { is_mobile }, - } = useStore(); +const UploadMessage = () => { + const { isDesktop, isMobile } = useDevice(); + return (
- {is_mobile ? ( - - ) : ( + {isDesktop ? ( + ) : ( + )} - +
); -}); +}; const FileUploader = ({ onFileDrop, onError }: TFileUploaderProps) => { const [document_files, setDocumentFiles] = React.useState([]); diff --git a/packages/account/src/Components/file-uploader-container/files-descriptions.tsx b/packages/account/src/Components/file-uploader-container/files-descriptions.tsx index 92e095fabd6e..a54c25d2cb45 100644 --- a/packages/account/src/Components/file-uploader-container/files-descriptions.tsx +++ b/packages/account/src/Components/file-uploader-container/files-descriptions.tsx @@ -1,21 +1,20 @@ import { Text } from '@deriv/components'; import React from 'react'; -import { observer, useStore } from '@deriv/stores'; import { TFilesDescription } from '../../Types'; +import { useDevice } from '@deriv-com/ui'; + +const FilesDescription = ({ descriptions, title }: TFilesDescription) => { + const { isMobile } = useDevice(); -const FilesDescription = observer(({ descriptions, title }: TFilesDescription) => { - const { - ui: { is_mobile }, - } = useStore(); return (
- + {title}
    {descriptions.map(item => (
  • - + {item.value}
  • @@ -23,6 +22,6 @@ const FilesDescription = observer(({ descriptions, title }: TFilesDescription) =
); -}); +}; export default FilesDescription; diff --git a/packages/account/src/Components/financial-details/__tests__/financial-details.spec.tsx b/packages/account/src/Components/financial-details/__tests__/financial-details.spec.tsx index ea9ea3fa600d..abd6ee05339e 100644 --- a/packages/account/src/Components/financial-details/__tests__/financial-details.spec.tsx +++ b/packages/account/src/Components/financial-details/__tests__/financial-details.spec.tsx @@ -1,15 +1,15 @@ import React from 'react'; import { FormikValues } from 'formik'; -import { EMPLOYMENT_VALUES, isDesktop, isMobile } from '@deriv/shared'; +import { EMPLOYMENT_VALUES } from '@deriv/shared'; import { render, screen, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import FinancialDetails from '../financial-details'; import { StoreProvider, mockStore } from '@deriv/stores'; +import { useDevice } from '@deriv-com/ui'; -jest.mock('@deriv/shared', () => ({ - ...jest.requireActual('@deriv/shared'), - isDesktop: jest.fn(() => true), - isMobile: jest.fn(() => false), +jest.mock('@deriv-com/ui', () => ({ + ...jest.requireActual('@deriv-com/ui'), + useDevice: jest.fn(() => ({ isDesktop: true })), })); const modal_root_el = document.createElement('div'); @@ -70,8 +70,7 @@ describe('', () => { }); it('should render "FinancialDetails" for mobile', () => { - (isDesktop as jest.Mock).mockReturnValue(false); - (isMobile as jest.Mock).mockReturnValue(true); + (useDevice as jest.Mock).mockReturnValue({ isDesktop: false }); renderComponent({}); @@ -97,8 +96,7 @@ describe('', () => { }); it('should trigger "Previous" or "Submit" button', async () => { - (isDesktop as jest.Mock).mockReturnValue(false); - (isMobile as jest.Mock).mockReturnValue(true); + (useDevice as jest.Mock).mockReturnValue({ isDesktop: false }); renderComponent({}); @@ -143,8 +141,7 @@ describe('', () => { }); it('should change the selected value when user changes the value in the dropdown', () => { - (isDesktop as jest.Mock).mockReturnValue(false); - (isMobile as jest.Mock).mockReturnValue(true); + (useDevice as jest.Mock).mockReturnValue({ isDesktop: false }); renderComponent({}); @@ -161,8 +158,7 @@ describe('', () => { }); it('should show "Unemployed" in occupation list if employment status is not "Employed"', async () => { - (isDesktop as jest.Mock).mockReturnValue(false); - (isMobile as jest.Mock).mockReturnValue(true); + (useDevice as jest.Mock).mockReturnValueOnce({ isDesktop: false }); const new_mock_props: React.ComponentProps = { ...mock_props, employment_status: 'Pensioner', diff --git a/packages/account/src/Components/financial-details/financial-details-partials.tsx b/packages/account/src/Components/financial-details/financial-details-partials.tsx index f703a9716d54..ec97de79d498 100644 --- a/packages/account/src/Components/financial-details/financial-details-partials.tsx +++ b/packages/account/src/Components/financial-details/financial-details-partials.tsx @@ -1,8 +1,9 @@ import React from 'react'; import { Field, FormikValues, useFormikContext } from 'formik'; -import { DesktopWrapper, MobileWrapper, Dropdown, SelectNative } from '@deriv/components'; +import { Dropdown, SelectNative } from '@deriv/components'; import { EMPLOYMENT_VALUES, TEmploymentStatus, shouldHideOccupationField } from '@deriv/shared'; import { localize } from '@deriv/translations'; +import { useDevice } from '@deriv-com/ui'; import { getAccountTurnoverList, getEducationLevelList, @@ -45,12 +46,12 @@ const FinancialDetailsDropdownField = ({ const { values, handleChange, handleBlur, touched, errors, setFieldValue } = useFormikContext<{ [key: string]: string; }>(); - + const { isDesktop } = useDevice(); return ( {({ field }: FormikValues) => ( - + {isDesktop ? ( - - + ) : ( - + )} )} @@ -97,6 +97,7 @@ const FinancialDetailsOccupationDropdownField = ({ const { values, handleChange, handleBlur, touched, errors, setFieldValue } = useFormikContext<{ [key: string]: string; }>(); + const { isDesktop } = useDevice(); const getFormattedOccupationValues = () => employment_status === EMPLOYMENT_VALUES.EMPLOYED && values?.occupation === EMPLOYMENT_VALUES.UNEMPLOYED @@ -107,7 +108,7 @@ const FinancialDetailsOccupationDropdownField = ({ {({ field }: FormikValues) => ( - + {isDesktop ? ( - - + ) : ( - + )} )} diff --git a/packages/account/src/Components/financial-details/financial-details.tsx b/packages/account/src/Components/financial-details/financial-details.tsx index 722e6b1bda8d..0a26ab35e3bb 100644 --- a/packages/account/src/Components/financial-details/financial-details.tsx +++ b/packages/account/src/Components/financial-details/financial-details.tsx @@ -9,7 +9,7 @@ import { Text, ThemedScrollbars, } from '@deriv/components'; -import { isDesktop, isMobile, EMPLOYMENT_VALUES, shouldHideOccupationField } from '@deriv/shared'; +import { EMPLOYMENT_VALUES, shouldHideOccupationField } from '@deriv/shared'; import { Localize, localize } from '@deriv/translations'; import { TFinancialInformationForm } from 'Types'; import { observer, useStore } from '@deriv/stores'; @@ -17,6 +17,7 @@ import FinancialInformation from './financial-details-partials'; import { splitValidationResultTypes } from '../real-account-signup/helpers/utils'; import ScrollToFieldWithError from '../forms/scroll-to-field-with-error'; import InlineNoteWithIcon from '../inline-note-with-icon'; +import { useDevice } from '@deriv-com/ui'; type TFinancialDetails = { goToPreviousStep: () => void; @@ -48,7 +49,7 @@ const FinancialDetails = observer((props: TFinancialDetails) => { props.onSave(current_step, values); props.onCancel(current_step, props.goToPreviousStep); }; - + const { isDesktop } = useDevice(); const { traders_hub: { is_eu_user }, } = useStore(); @@ -64,10 +65,10 @@ const FinancialDetails = observer((props: TFinancialDetails) => { return errors; }; - const fields_to_scroll_top = isMobile() - ? ['income_source', 'account_turnover', 'estimated_worth'] - : ['income_source']; - const fields_to_scroll_bottom = isMobile() ? [] : ['account_turnover', 'estimated_worth']; + const fields_to_scroll_top = isDesktop + ? ['income_source'] + : ['income_source', 'account_turnover', 'estimated_worth']; + const fields_to_scroll_bottom = isDesktop ? ['account_turnover', 'estimated_worth'] : []; return ( { {is_eu_user ? (
@@ -124,7 +125,7 @@ const FinancialDetails = observer((props: TFinancialDetails) => {
- + { values?.occupation === EMPLOYMENT_VALUES.UNEMPLOYED ) } - is_absolute={isMobile()} + is_absolute={!isDesktop} label={localize('Next')} has_cancel cancel_label={localize('Previous')} diff --git a/packages/account/src/Components/form-body-section/form-body-section.tsx b/packages/account/src/Components/form-body-section/form-body-section.tsx index 0c3fa4b89f95..2939455908ed 100644 --- a/packages/account/src/Components/form-body-section/form-body-section.tsx +++ b/packages/account/src/Components/form-body-section/form-body-section.tsx @@ -2,7 +2,7 @@ import React from 'react'; import clsx from 'clsx'; import { Text } from '@deriv/components'; -import { isMobile } from '@deriv/shared'; +import { useDevice } from '@deriv-com/ui'; import { Localize } from '@deriv/translations'; export type TFormBodySection = { @@ -40,6 +40,7 @@ const FormBodySection = ({ side_note_position = 'left', type = 'text', }: React.PropsWithChildren): JSX.Element => { + const { isDesktop } = useDevice(); if (has_side_note) { return (
{type === 'text' ? ( - + {side_note} ) : ( - +
{side_note}
diff --git a/packages/account/src/Components/form-body/__tests__/form-body.spec.tsx b/packages/account/src/Components/form-body/__tests__/form-body.spec.tsx index 851a6d3e89c5..7de8764bec59 100644 --- a/packages/account/src/Components/form-body/__tests__/form-body.spec.tsx +++ b/packages/account/src/Components/form-body/__tests__/form-body.spec.tsx @@ -1,12 +1,11 @@ import React from 'react'; import { render, screen } from '@testing-library/react'; -import { isMobile, isDesktop } from '@deriv/shared'; import { FormBody } from '../form-body'; +import { useDevice } from '@deriv-com/ui'; -jest.mock('@deriv/shared/src/utils/screen/responsive', () => ({ - ...jest.requireActual('@deriv/shared/src/utils/screen/responsive'), - isMobile: jest.fn(), - isDesktop: jest.fn(() => true), +jest.mock('@deriv-com/ui', () => ({ + ...jest.requireActual('@deriv-com/ui'), + useDevice: jest.fn(() => ({ isDesktop: true })), })); describe('', () => { @@ -27,8 +26,7 @@ describe('', () => { }); it('should render FormBody component with children in mobile', () => { - (isMobile as jest.Mock).mockReturnValue(true); - (isDesktop as jest.Mock).mockReturnValue(false); + (useDevice as jest.Mock).mockReturnValueOnce({ isDesktop: false }); render(
Test children mobile
diff --git a/packages/account/src/Components/form-body/form-body.tsx b/packages/account/src/Components/form-body/form-body.tsx index 9431966abef9..04fad3384f3d 100644 --- a/packages/account/src/Components/form-body/form-body.tsx +++ b/packages/account/src/Components/form-body/form-body.tsx @@ -1,31 +1,36 @@ // [TODO] - To be removed once CFD is configured to use the new form-body component import React, { PropsWithChildren, Fragment } from 'react'; import { ScrollbarsContainer } from '../scrollbars-container/scrollbars-container'; -import { Div100vhContainer, DesktopWrapper, MobileWrapper } from '@deriv/components'; +import { Div100vhContainer } from '@deriv/components'; +import { useDevice } from '@deriv-com/ui'; import clsx from 'clsx'; type TFormBody = { scroll_offset?: string; className?: string; + isFullHeight?: boolean; }; -export const FormBody = ({ children, scroll_offset, className }: PropsWithChildren) => ( - - - - {children} - - - - - {children} - - - -); +export const FormBody = ({ children, scroll_offset, className, isFullHeight }: PropsWithChildren) => { + const { isDesktop } = useDevice(); + return ( + + {isDesktop ? ( + + {children} + + ) : ( + + {children} + + )} + + ); +}; diff --git a/packages/account/src/Components/form-field-info/form-field-info.tsx b/packages/account/src/Components/form-field-info/form-field-info.tsx index 10563cefac35..b3c2d015e719 100644 --- a/packages/account/src/Components/form-field-info/form-field-info.tsx +++ b/packages/account/src/Components/form-field-info/form-field-info.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { Popover, useOnClickOutside } from '@deriv/components'; import { TPopoverProps } from '@deriv/components/src/components/types'; -import { isMobile } from '@deriv/shared'; +import { useDevice } from '@deriv-com/ui'; /** * A component that renders a popover with an info icon. @@ -22,6 +22,7 @@ export const FormFieldInfo = (props: Omit) => { }; useOnClickOutside(ref, () => setIsOpen(false), validateClickOutside); + const { isDesktop } = useDevice(); return (
) => { zIndex='9999' is_open={is_open} onClick={() => setIsOpen(prev_is_open => !prev_is_open)} - alignment={isMobile() ? 'left' : 'right'} + alignment={isDesktop ? 'right' : 'left'} />
); diff --git a/packages/account/src/Components/forms/form-select-field.tsx b/packages/account/src/Components/forms/form-select-field.tsx index 08a3cbb0766c..5d12b7b02a02 100644 --- a/packages/account/src/Components/forms/form-select-field.tsx +++ b/packages/account/src/Components/forms/form-select-field.tsx @@ -1,9 +1,9 @@ import { FC, Fragment } from 'react'; import { Autocomplete, SelectNative } from '@deriv/components'; -import { useStore } from '@deriv/stores'; import { Field, FieldProps, FormikErrors } from 'formik'; import { TGetField } from '../additional-kyc-info-modal/form-config'; import { TListItem } from 'Types'; +import { useDevice } from '@deriv-com/ui'; type TFormSelectField = TGetField & { onItemSelection?: (item: TListItem) => void; @@ -26,9 +26,7 @@ const FormSelectField: FC = ({ placeholder, list_height, }) => { - const { ui } = useStore(); - const { is_mobile } = ui; - + const { isDesktop } = useDevice(); const onSelect = (field: string, setFieldValue: TSetFieldValue) => ({ value, text }: TListItem) => { @@ -39,7 +37,7 @@ const FormSelectField: FC = ({ {({ field, meta: { touched, error }, form: { setFieldValue } }: FieldProps) => ( - {is_mobile ? ( + {!isDesktop ? ( { const [document_list, setDocumentList] = React.useState>([]); const [selected_doc, setSelectedDoc] = React.useState(''); + const { isDesktop } = useDevice(); const { documents_supported: document_data } = selected_country?.identity?.services?.idv ?? {}; @@ -116,7 +118,6 @@ const IDVForm = ({ setFieldValue('document_additional', '', false); } }; - return (
@@ -132,7 +133,7 @@ const IDVForm = ({ {({ field }: FieldProps) => ( - + {isDesktop ? ( - - + ) : ( - + )} )} diff --git a/packages/account/src/Components/forms/personal-details-form.jsx b/packages/account/src/Components/forms/personal-details-form.jsx index cc2d47fcb0a8..cc2764a284b5 100644 --- a/packages/account/src/Components/forms/personal-details-form.jsx +++ b/packages/account/src/Components/forms/personal-details-form.jsx @@ -2,7 +2,6 @@ import React from 'react'; import { Link } from 'react-router-dom'; import clsx from 'clsx'; import { Field, useFormikContext } from 'formik'; -import { useDevice } from '@deriv-com/ui'; import { Autocomplete, Checkbox, @@ -21,6 +20,7 @@ import FormBodySection from '../form-body-section'; import { DateOfBirthField, FormInputField } from './form-fields'; import FormSubHeader from '../form-sub-header'; import InlineNoteWithIcon from '../inline-note-with-icon'; +import { useDevice } from '@deriv-com/ui'; const PersonalDetailsForm = props => { const { isDesktop } = useDevice(); @@ -131,7 +131,7 @@ const PersonalDetailsForm = props => { )} {
{'salutation' in values && !is_eu_user && (
- + {is_virtual ? ( localize( 'Please remember that it is your responsibility to keep your answers accurate and up to date. You can update your personal details at any time in your account settings.' @@ -530,7 +530,7 @@ const PersonalDetailsForm = props => { label={ } - label_font_size={!isDesktop ? 'xxs' : 'xs'} + label_font_size={isDesktop ? 'xs' : 'xxs'} disabled={is_confirmation_checkbox_disabled} onChange={handleChange} has_error={!!(touched.confirmation_checkbox && errors.confirmation_checkbox)} @@ -596,7 +596,7 @@ const PersonalDetailsForm = props => { label={ } - label_font_size={!isDesktop ? 'xxs' : 'xs'} + label_font_size={isDesktop ? 'xs' : 'xxs'} onChange={e => { setFieldValue('crs_confirmation', e.target.checked, true); setFieldTouched('crs_confirmation', true); @@ -629,7 +629,6 @@ const PhoneField = ({ value, editable_fields, has_real_account, required }) => ( const PlaceOfBirthField = ({ handleChange, setFieldValue, disabled, residence_list, required }) => { const { isDesktop } = useDevice(); - return ( {({ field, meta }) => ( @@ -687,7 +686,6 @@ const TaxResidenceField = ({ disabled, }) => { const { isDesktop } = useDevice(); - return ( {({ field, meta }) => ( @@ -761,7 +759,6 @@ const TaxIdentificationNumberField = ({ required = false, }) => { const { isDesktop } = useDevice(); - return (
{ const { isDesktop } = useDevice(); - return ( {!no_header && } diff --git a/packages/account/src/Components/icon-message-content/__tests__/icon-message-content.spec.tsx b/packages/account/src/Components/icon-message-content/__tests__/icon-message-content.spec.tsx index e461af60a8c3..db8a564e7f84 100644 --- a/packages/account/src/Components/icon-message-content/__tests__/icon-message-content.spec.tsx +++ b/packages/account/src/Components/icon-message-content/__tests__/icon-message-content.spec.tsx @@ -2,7 +2,11 @@ import React from 'react'; import { screen, render } from '@testing-library/react'; import { Icon } from '@deriv/components'; import IconMessageContent from '../icon-message-content'; -import { mockStore, StoreProvider } from '@deriv/stores'; + +jest.mock('@deriv-com/ui', () => ({ + ...jest.requireActual('@deriv-com/ui'), + useDevice: jest.fn(() => ({ isDesktop: true })), +})); jest.mock('@deriv/components', () => { const original_module = jest.requireActual('@deriv/components'); @@ -19,18 +23,8 @@ describe('', () => { text: 'sampleText', }; - const mock_store = mockStore({ - ui: { - is_desktop: true, - }, - }); - it('should render the IconWithMessage component', () => { - render( - - - - ); + render(); expect(screen.getByTestId('mockedIcon')).toBeInTheDocument(); expect(screen.getByText('sampleMessage')).toBeInTheDocument(); @@ -39,11 +33,9 @@ describe('', () => { it('renders the children', () => { render( - - -
test
-
-
+ +
test
+
); expect(screen.getByText('test')).toBeInTheDocument(); }); diff --git a/packages/account/src/Components/icon-message-content/icon-message-content.tsx b/packages/account/src/Components/icon-message-content/icon-message-content.tsx index 547b1581f734..2753e285a037 100644 --- a/packages/account/src/Components/icon-message-content/icon-message-content.tsx +++ b/packages/account/src/Components/icon-message-content/icon-message-content.tsx @@ -1,7 +1,7 @@ import React from 'react'; import clsx from 'clsx'; import { Div100vhContainer, Text } from '@deriv/components'; -import { isDesktop } from '@deriv/shared'; +import { useDevice } from '@deriv-com/ui'; type TIconMessageContent = { className?: string; @@ -20,57 +20,60 @@ const IconMessageContent = ({ is_disabled_for_mobile = false, message, text, -}: React.PropsWithChildren) => ( - -
) => { + const { isDesktop } = useDevice(); + + return ( + - {icon && ( -
- {icon} -
- )} - - {message} - - {text && ( -
- - {text} - -
- )} - {children} -
-
-); + {icon} +
+ )} + + {message} + + {text && ( +
+ + {text} + +
+ )} + {children} +
+ + ); +}; export default IconMessageContent; diff --git a/packages/account/src/Components/icon-message-list/icon-message-list.tsx b/packages/account/src/Components/icon-message-list/icon-message-list.tsx index 48e3d8a0b647..f55c0f96b509 100644 --- a/packages/account/src/Components/icon-message-list/icon-message-list.tsx +++ b/packages/account/src/Components/icon-message-list/icon-message-list.tsx @@ -2,9 +2,9 @@ import React from 'react'; import clsx from 'clsx'; import { Div100vhContainer, Text, Button, ThemedScrollbars, Icon } from '@deriv/components'; import { getOnfidoError } from '@deriv/shared'; -import { observer, useStore } from '@deriv/stores'; import { Localize } from '@deriv/translations'; import ListItem from './list-item'; +import { useDevice } from '@deriv-com/ui'; type TIconMessageList = { className?: string; @@ -14,14 +14,14 @@ type TIconMessageList = { onContinue: () => void; }; -const IconMessageList = observer(({ className, icon, message, message_list = [], onContinue }: TIconMessageList) => { - const { ui } = useStore(); - const { is_mobile, is_desktop } = ui; +const IconMessageList = ({ className, icon, message, message_list = [], onContinue }: TIconMessageList) => { + const { isDesktop, isMobile } = useDevice(); + return ( - +
{message} @@ -87,6 +87,6 @@ const IconMessageList = observer(({ className, icon, message, message_list = [], ); -}); +}; export default IconMessageList; diff --git a/packages/account/src/Components/icon-message-list/list-item.tsx b/packages/account/src/Components/icon-message-list/list-item.tsx index 24bef3127ef9..d1ed45181d23 100644 --- a/packages/account/src/Components/icon-message-list/list-item.tsx +++ b/packages/account/src/Components/icon-message-list/list-item.tsx @@ -1,18 +1,17 @@ import React from 'react'; import { Text } from '@deriv/components'; -import { observer, useStore } from '@deriv/stores'; import { Localize } from '@deriv/translations'; +import { useDevice } from '@deriv-com/ui'; type TListItem = { text: React.ReactNode; index?: number; }; -const ListItem = observer(({ text, index }: TListItem) => { - const { - ui: { is_desktop }, - } = useStore(); - const text_size = is_desktop ? 'xs' : 'xxs'; +const ListItem = ({ text, index }: TListItem) => { + const { isDesktop } = useDevice(); + + const text_size = isDesktop ? 'xs' : 'xxs'; return (
{index && ( @@ -25,6 +24,6 @@ const ListItem = observer(({ text, index }: TListItem) => {
); -}); +}; export default ListItem; diff --git a/packages/account/src/Components/icon-with-message/icon-with-message.tsx b/packages/account/src/Components/icon-with-message/icon-with-message.tsx index e9d8a3c04eec..2b6eec2f1611 100644 --- a/packages/account/src/Components/icon-with-message/icon-with-message.tsx +++ b/packages/account/src/Components/icon-with-message/icon-with-message.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { Icon, Text, Button } from '@deriv/components'; -import { isMobile } from '@deriv/shared'; +import { useDevice } from '@deriv-com/ui'; import { observer, useStore } from '@deriv/stores'; import { localize } from '@deriv/translations'; @@ -12,6 +12,7 @@ type TIconWithMessage = { const IconWithMessage = observer(({ has_button, icon, message }: TIconWithMessage) => { const { client, ui } = useStore(); + const { isDesktop } = useDevice(); const { has_any_real_account: has_real_account } = client; const { toggleAccountsDialog, toggleShouldShowRealAccountsList } = ui; @@ -22,7 +23,7 @@ const IconWithMessage = observer(({ has_button, icon, message }: TIconWithMessag className='da-icon-with-message__text' as='p' color='general' - size={isMobile() ? 'xs' : 's'} + size={isDesktop ? 's' : 'xs'} line_height='m' weight='bold' > diff --git a/packages/account/src/Components/leave-confirm/leave-confirm.tsx b/packages/account/src/Components/leave-confirm/leave-confirm.tsx index 03ef8b01da24..41cc0318a4b4 100644 --- a/packages/account/src/Components/leave-confirm/leave-confirm.tsx +++ b/packages/account/src/Components/leave-confirm/leave-confirm.tsx @@ -2,44 +2,39 @@ import React from 'react'; import { RouteComponentProps, useHistory, withRouter } from 'react-router-dom'; import { FormikConsumer } from 'formik'; import { Button, Icon, Modal } from '@deriv/components'; -import { isMobile } from '@deriv/shared'; import { localize } from '@deriv/translations'; import IconMessageContent from '../icon-message-content'; +import { useDevice } from '@deriv-com/ui'; type TLeaveConfirmMessage = { back: () => void; leave: () => void; }; - type TTransitionBlocker = RouteComponentProps & { dirty: boolean; onDirty?: (prop: boolean) => void; }; const LeaveConfirmMessage = ({ back, leave }: TLeaveConfirmMessage) => { + const { isMobile } = useDevice(); + return ( } + icon={} + is_disabled_for_mobile={true} >
-
@@ -53,24 +48,21 @@ export const TransitionBlocker = ({ dirty, onDirty }: TTransitionBlocker) => { const [show, setShow] = React.useState(false); const [next_location, setNextLocation] = React.useState<{ pathname: string } | null>(null); const history = useHistory(); + const { isMobile } = useDevice(); React.useEffect(() => { return () => unblock(); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); - const unblock = history.block((location: { pathname: string }) => { if (dirty) { if (onDirty) onDirty(false); - if (show) leave(); - setShow(true); setNextLocation(location); } return !dirty; }); - const leave = () => { if (next_location?.pathname) { const { pathname } = next_location; @@ -78,7 +70,6 @@ export const TransitionBlocker = ({ dirty, onDirty }: TTransitionBlocker) => { history.push(pathname); } else history.push(null); }; - const back = () => { setNextLocation(null); setShow(false); @@ -87,7 +78,7 @@ export const TransitionBlocker = ({ dirty, onDirty }: TTransitionBlocker) => { return ( <> - {show && isMobile() ? ( + {show && isMobile ? ( ) : ( @@ -100,11 +91,9 @@ export const TransitionBlocker = ({ dirty, onDirty }: TTransitionBlocker) => { ); }; export const TransitionBlockerWithRouter = withRouter(TransitionBlocker); - const LeaveConfirm = ({ onDirty }: { onDirty?: (prop: boolean) => void }) => ( {formik => } ); - export default LeaveConfirm; diff --git a/packages/account/src/Components/personal-details/__tests__/personal-details.spec.tsx b/packages/account/src/Components/personal-details/__tests__/personal-details.spec.tsx index cb1f3d2f0e32..e400886920c1 100644 --- a/packages/account/src/Components/personal-details/__tests__/personal-details.spec.tsx +++ b/packages/account/src/Components/personal-details/__tests__/personal-details.spec.tsx @@ -2,14 +2,13 @@ import React, { ComponentProps, ReactNode } from 'react'; import { BrowserRouter } from 'react-router-dom'; import { fireEvent, render, screen, waitFor, within } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; -import { useDevice } from '@deriv-com/ui'; -import { isDesktop, isMobile } from '@deriv/shared'; import { splitValidationResultTypes } from '../../real-account-signup/helpers/utils'; import PersonalDetails from '../personal-details'; import { shouldShowIdentityInformation, isDocumentTypeValid, isAdditionalDocumentValid } from '../../../Helpers/utils'; import { StoreProvider, mockStore } from '@deriv/stores'; import { Analytics } from '@deriv-com/analytics'; import { FormikErrors } from 'formik'; +import { useDevice } from '@deriv-com/ui'; jest.mock('@deriv-com/ui', () => ({ ...jest.requireActual('@deriv-com/ui'), @@ -23,13 +22,6 @@ jest.mock('@deriv/components', () => ({ Popover: jest.fn(props => props.is_open && {props.message}), })); -// [TODO] - To be removed when PersonalDetailsForm is migrated to TSX -jest.mock('@deriv/shared', () => ({ - ...jest.requireActual('@deriv/shared'), - isMobile: jest.fn(() => false), - isDesktop: jest.fn(() => true), -})); - jest.mock('../../real-account-signup/helpers/utils.ts', () => ({ splitValidationResultTypes: jest.fn(() => ({ warnings: mock_warnings, @@ -317,9 +309,8 @@ describe('', () => { it('should have validation errors on form fields', async () => { const new_props = { ...mock_props, is_svg: false }; - const store_config = mockStore({ ui: { is_desktop: true } }); - renderwithRouter({ props: new_props, store: store_config }); + renderwithRouter({ props: new_props }); const first_name = screen.getByTestId('first_name'); const last_name = screen.getByTestId('last_name'); @@ -490,8 +481,6 @@ describe('', () => { }); it('should disable tax_residence field if it is immutable from BE', () => { - const new_store = mockStore({ ui: { is_mobile: false, is_desktop: true } }); - const new_props = { ...mock_props, value: { @@ -501,7 +490,7 @@ describe('', () => { }, disabled_items: ['salutation', 'first_name', 'last_name', 'date_of_birth', 'tax_residence'], }; - renderwithRouter({ props: new_props, store: new_store }); + renderwithRouter({ props: new_props }); expect(screen.getByTestId('tax_residence')).toBeDisabled(); }); @@ -617,13 +606,11 @@ describe('', () => { it('should display proper data in mobile mode', () => { // [TODO] - Remove this when PersonalDetailsForm is migrated to TSX - (isMobile as jest.Mock).mockReturnValue(true); - (isDesktop as jest.Mock).mockReturnValue(false); - (useDevice as jest.Mock).mockReturnValue({ isMobile: true }); - const mock_store = mockStore({ ui: { is_mobile: true, is_desktop: false } }); - const new_props = { ...mock_props, is_svg: false }; - renderwithRouter({ props: new_props, store: mock_store }); + (useDevice as jest.Mock).mockReturnValue({ isDesktop: false }); + + const new_props = { ...mock_props, is_svg: false }; + renderwithRouter({ props: new_props }); expect(screen.getByRole('radio', { name: /mr/i })).toBeInTheDocument(); expect(screen.getByRole('radio', { name: /ms/i })).toBeInTheDocument(); @@ -647,13 +634,11 @@ describe('', () => { }); it('should select correct dropdown options in mobile mode', () => { - (isMobile as jest.Mock).mockReturnValue(true); - (isDesktop as jest.Mock).mockReturnValue(false); - (useDevice as jest.Mock).mockReturnValue({ isMobile: true }); - const mock_store = mockStore({ ui: { is_mobile: true, is_desktop: false } }); + (useDevice as jest.Mock).mockReturnValueOnce({ isDesktop: false }); + const new_props = { ...mock_props, is_svg: false }; - renderwithRouter({ props: new_props, store: mock_store }); + renderwithRouter({ props: new_props }); const place_of_birth_mobile = screen.queryByTestId('place_of_birth_mobile'); expect(place_of_birth_mobile).toBeInTheDocument(); @@ -726,8 +711,7 @@ describe('', () => { it('should submit the form if there is no validation error on mobile', async () => { // [TODO] - Remove this when PersonalDetailsForm is migrated to TSX - (isMobile as jest.Mock).mockReturnValue(true); - (isDesktop as jest.Mock).mockReturnValue(false); + (useDevice as jest.Mock).mockReturnValueOnce({ isDesktop: false }); (splitValidationResultTypes as jest.Mock).mockReturnValue({ warnings: {}, errors: {} }); const new_props = { diff --git a/packages/account/src/Components/personal-details/personal-details.tsx b/packages/account/src/Components/personal-details/personal-details.tsx index 4d578a6271c2..d8490583f6be 100644 --- a/packages/account/src/Components/personal-details/personal-details.tsx +++ b/packages/account/src/Components/personal-details/personal-details.tsx @@ -3,6 +3,7 @@ import clsx from 'clsx'; import { Form, Formik, FormikErrors } from 'formik'; import { Analytics, TEvents } from '@deriv-com/analytics'; import { AutoHeightWrapper, Div100vhContainer, FormSubmitButton, Modal, ThemedScrollbars } from '@deriv/components'; +import { useDevice } from '@deriv-com/ui'; import { getIDVNotApplicableOption, removeEmptyPropertiesFromObject } from '@deriv/shared'; import { Localize, localize } from '@deriv/translations'; import { useStore, observer } from '@deriv/stores'; @@ -79,12 +80,12 @@ const PersonalDetails = observer( }: TPersonalDetailProps) => { const { traders_hub: { is_eu_user }, - ui: { is_mobile, is_desktop }, } = useStore(); const { account_status, account_settings, residence, real_account_signup_target } = props; const [should_close_tooltip, setShouldCloseTooltip] = useState(false); const [no_confirmation_needed, setNoConfirmationNeeded] = useState(false); + const { isDesktop } = useDevice(); const handleCancel = (values: TPersonalDetailsSectionForm) => { const current_step = getCurrentStep() - 1; onSave(current_step, values); @@ -198,7 +199,7 @@ const PersonalDetails = observer( }} > {({ handleSubmit, isSubmitting, values }) => ( - + {({ setRef, height }) => (
- + handleCancel(values)} /> diff --git a/packages/account/src/Components/poa/common-mistakes/common-mistake-examples.scss b/packages/account/src/Components/poa/common-mistakes/common-mistake-examples.scss index 5edc9aa93c05..2a63016d7a73 100644 --- a/packages/account/src/Components/poa/common-mistakes/common-mistake-examples.scss +++ b/packages/account/src/Components/poa/common-mistakes/common-mistake-examples.scss @@ -17,6 +17,9 @@ column-gap: calc((100% - 23.7rem * 3) / 2); row-gap: 3.2rem; } + @include tablet-screen { + grid-template-columns: repeat(2, 1fr); + } &-layout { background-color: var(--transparent-danger); diff --git a/packages/account/src/Components/poa/common-mistakes/common-mistake-examples.tsx b/packages/account/src/Components/poa/common-mistakes/common-mistake-examples.tsx index d428ef1ad989..4257ad880d27 100644 --- a/packages/account/src/Components/poa/common-mistakes/common-mistake-examples.tsx +++ b/packages/account/src/Components/poa/common-mistakes/common-mistake-examples.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { Text } from '@deriv/components'; -import { isMobile } from '@deriv/shared'; +import { useDevice } from '@deriv-com/ui'; import { Localize } from '@deriv/translations'; import { useStore } from '@deriv/stores'; import { getExampleImagesConfig } from '../../../Configs/poa-common-mistake-examples-config'; @@ -36,12 +36,13 @@ const CommonMistakeExamplePartials = ({ description, image }: TCommonMistakeExam * @returns React.ReactElement */ const CommonMistakeExamples = () => { + const { isDesktop } = useDevice(); const { client } = useStore(); const { is_eu } = client; const example_images = getExampleImagesConfig(is_eu); return ( - +
diff --git a/packages/account/src/Components/poi/idv-document-submit/__tests__/idv-document-submit.spec.tsx b/packages/account/src/Components/poi/idv-document-submit/__tests__/idv-document-submit.spec.tsx index 3915af45f4bc..8594f9b5f25d 100644 --- a/packages/account/src/Components/poi/idv-document-submit/__tests__/idv-document-submit.spec.tsx +++ b/packages/account/src/Components/poi/idv-document-submit/__tests__/idv-document-submit.spec.tsx @@ -1,16 +1,15 @@ import React from 'react'; import { fireEvent, render, screen, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; -import { isDesktop, isMobile } from '@deriv/shared'; import { StoreProvider, mockStore } from '@deriv/stores'; import { isDocumentNumberValid } from 'Helpers/utils'; import IdvDocumentSubmit from '../idv-document-submit'; +import { useDevice } from '@deriv-com/ui'; const mock_store = mockStore({ client: { getChangeableFields: jest.fn(() => []), }, - ui: { is_desktop: true }, }); jest.mock('Assets/ic-document-submit-icon.svg', () => jest.fn(() => 'DocumentSubmitLogo')); @@ -38,8 +37,6 @@ jest.mock('Helpers/utils', () => ({ jest.mock('@deriv/shared', () => ({ ...jest.requireActual('@deriv/shared'), - isDesktop: jest.fn(() => true), - isMobile: jest.fn(() => false), formatInput: jest.fn(() => '5436454364243'), WS: { send: jest.fn(() => Promise.resolve({ error: '' })), @@ -57,6 +54,11 @@ jest.mock('@deriv/shared', () => ({ })), })); +jest.mock('@deriv-com/ui', () => ({ + ...jest.requireActual('@deriv-com/ui'), + useDevice: jest.fn(() => ({ isDesktop: true })), +})); + describe('', () => { const mock_props: React.ComponentProps = { handleBack: jest.fn(), @@ -85,12 +87,16 @@ describe('', () => { getChangeableFields: jest.fn(() => []), }; - it('should render IdvDocumentSubmit component', () => { + const renderComponent = () => { render( ); + }; + + it('should render IdvDocumentSubmit component', () => { + renderComponent(); expect(screen.getByText(/Identity verification/i)).toBeInTheDocument(); expect(screen.getByText(/details/i)).toBeInTheDocument(); @@ -104,11 +110,7 @@ describe('', () => { }); it('should trigger "go back" button, inputs and check document_type validation after rendering IdvDocumentSubmit component', async () => { - render( - - - - ); + renderComponent(); const backBtn = screen.getByRole('button', { name: /back/i }); userEvent.click(backBtn); @@ -134,14 +136,9 @@ describe('', () => { }); it('should change inputs, check document_number validation and trigger "Verify" button after rendering IdvDocumentSubmit component', async () => { - (isDesktop as jest.Mock).mockReturnValue(false); - (isMobile as jest.Mock).mockReturnValue(true); + (useDevice as jest.Mock).mockReturnValue({ isDesktop: false }); - render( - - - - ); + renderComponent(); const verifyBtn = screen.getByRole('button', { name: /verify/i }); expect(verifyBtn).toBeDisabled(); diff --git a/packages/account/src/Components/poi/idv-document-submit/idv-document-submit.tsx b/packages/account/src/Components/poi/idv-document-submit/idv-document-submit.tsx index a790a42c35c0..6f2c7278ee7b 100644 --- a/packages/account/src/Components/poi/idv-document-submit/idv-document-submit.tsx +++ b/packages/account/src/Components/poi/idv-document-submit/idv-document-submit.tsx @@ -12,6 +12,7 @@ import { WS, } from '@deriv/shared'; import { observer, useStore } from '@deriv/stores'; +import { useDevice } from '@deriv-com/ui'; import { isAdditionalDocumentValid, isDocumentNumberValid, @@ -48,9 +49,9 @@ export type TIdvDocumentSubmitForm = TIDVFormValues & TConfirmPersonalDetailsFor const IdvDocumentSubmit = observer( ({ handleBack, handleViewComplete, handleSelectionNext, selected_country }: TIDVDocumentSubmitProps) => { - const { client, ui } = useStore(); + const { client } = useStore(); const { account_settings, getChangeableFields } = client; - const { is_mobile, is_desktop } = ui; + const { isDesktop } = useDevice(); const IDV_NOT_APPLICABLE_OPTION = React.useMemo(() => getIDVNotApplicableOption(), []); const shouldSkipIdv = (document_id?: string) => document_id === IDV_NOT_APPLICABLE_OPTION.id; @@ -201,7 +202,7 @@ const IdvDocumentSubmit = observer( />
)} - + {!shouldSkipIdv(values?.document_type?.id) && ( @@ -223,7 +224,7 @@ const IdvDocumentSubmit = observer( )} - {is_desktop && ( + {isDesktop && (
-); +const Message = ({ data, open }: TMessage) => { + const { isDesktop } = useDevice(); + return ( +
+ + + {data?.info} + +
+ ); +}; const Preview = ({ data, setFieldValue, value, has_frame, handleChange }: Omit) => { const [background_url, setBackgroundUrl] = React.useState(''); @@ -95,6 +99,7 @@ const Preview = ({ data, setFieldValue, value, has_frame, handleChange }: Omit) => { + const { isDesktop } = useDevice(); const [image, setImage] = React.useState(); React.useEffect(() => { @@ -131,7 +136,7 @@ const Uploader = ({ data, value, is_full, onChange, has_frame }: Omit
diff --git a/packages/account/src/Components/poi/status/unsupported/card-with-arrow.tsx b/packages/account/src/Components/poi/status/unsupported/card-with-arrow.tsx index b6c786092fcf..05e706566156 100644 --- a/packages/account/src/Components/poi/status/unsupported/card-with-arrow.tsx +++ b/packages/account/src/Components/poi/status/unsupported/card-with-arrow.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { Icon, Text } from '@deriv/components'; -import { isMobile } from '@deriv/shared'; +import { useDevice } from '@deriv-com/ui'; type TCardWithArrow = { onClick: () => void; @@ -10,6 +10,7 @@ type TCardWithArrow = { }; const CardWithArrow = ({ onClick, title, description, icon }: TCardWithArrow) => { + const { isDesktop } = useDevice(); return (
@@ -17,12 +18,12 @@ const CardWithArrow = ({ onClick, title, description, icon }: TCardWithArrow) => {title} - + {description}
- +
); }; diff --git a/packages/account/src/Components/poi/status/unsupported/unsupported.scss b/packages/account/src/Components/poi/status/unsupported/unsupported.scss index 6229104d50d0..8ceb188dafe8 100644 --- a/packages/account/src/Components/poi/status/unsupported/unsupported.scss +++ b/packages/account/src/Components/poi/status/unsupported/unsupported.scss @@ -5,6 +5,7 @@ &__title { margin-inline: 1.6rem; + padding-top: 1.6rem; } .dc-card__wrapper { diff --git a/packages/account/src/Components/scrollbars-container/__tests__/scrollbars-container.spec.tsx b/packages/account/src/Components/scrollbars-container/__tests__/scrollbars-container.spec.tsx index 8e3313b71867..124319058a39 100644 --- a/packages/account/src/Components/scrollbars-container/__tests__/scrollbars-container.spec.tsx +++ b/packages/account/src/Components/scrollbars-container/__tests__/scrollbars-container.spec.tsx @@ -1,11 +1,11 @@ import React from 'react'; import { render, screen } from '@testing-library/react'; -import { isMobile } from '@deriv/shared'; import { ScrollbarsContainer } from '../scrollbars-container'; +import { useDevice } from '@deriv-com/ui'; -jest.mock('@deriv/shared/src/utils/screen/responsive', () => ({ - ...jest.requireActual('@deriv/shared'), - isMobile: jest.fn(() => false), +jest.mock('@deriv-com/ui', () => ({ + ...jest.requireActual('@deriv-com/ui'), + useDevice: jest.fn(() => ({ isDesktop: true })), })); describe('', () => { @@ -35,8 +35,8 @@ describe('', () => { expect(screen.getByTestId('dt_themed_scrollbars')).toHaveStyle('max-height: calc(100% - 33%)'); }); - it('should render children with ScrollbarsContainer component with scroll_offset and extra className for mobile', () => { - (isMobile as jest.Mock).mockReturnValue(true); + it('should render children with ScrollbarsContainer component with scroll_offset and extra className for responsive', () => { + (useDevice as jest.Mock).mockReturnValueOnce({ isDesktop: false }); render( diff --git a/packages/account/src/Components/scrollbars-container/scrollbars-container.tsx b/packages/account/src/Components/scrollbars-container/scrollbars-container.tsx index bf09fcab9ba5..5796ecc8d9c2 100644 --- a/packages/account/src/Components/scrollbars-container/scrollbars-container.tsx +++ b/packages/account/src/Components/scrollbars-container/scrollbars-container.tsx @@ -1,21 +1,30 @@ import clsx from 'clsx'; import React from 'react'; import { ThemedScrollbars } from '@deriv/components'; -import { isMobile } from '@deriv/shared'; +import { useDevice } from '@deriv-com/ui'; type TScrollbarsContainer = { className?: string; scroll_offset?: string; + isFullHeight?: boolean; }; export const ScrollbarsContainer = ({ children, className, scroll_offset, -}: React.PropsWithChildren) => ( - -
- {children} -
-
-); + isFullHeight = false, +}: React.PropsWithChildren) => { + const { isDesktop } = useDevice(); + const height_unit = isFullHeight ? '100vh' : '100%'; + return ( + +
+ {children} +
+
+ ); +}; diff --git a/packages/account/src/Components/self-exclusion/__tests__/self-exclusion-article.spec.tsx b/packages/account/src/Components/self-exclusion/__tests__/self-exclusion-article.spec.tsx index 773d6819becf..82320ab0ae76 100644 --- a/packages/account/src/Components/self-exclusion/__tests__/self-exclusion-article.spec.tsx +++ b/packages/account/src/Components/self-exclusion/__tests__/self-exclusion-article.spec.tsx @@ -18,6 +18,8 @@ describe('', () => { handleSubmit: jest.fn(), }; + const store = mockStore({}); + const eu_item = /these trading limits and self-exclusion help you control the amount of money and time you spend on deriv.com and exercise/i; const non_eu_item = @@ -34,16 +36,9 @@ describe('', () => { }; }); - it('should render SelfExclusionArticle desktop component with selfExclusionArticleItems', () => { - const new_store = mockStore({ - ui: { - is_desktop: true, - is_mobile: true, - }, - }); - + it('should render SelfExclusionArticle with selfExclusionArticleItems', () => { render( - + @@ -55,17 +50,11 @@ describe('', () => { expect(screen.queryByText(non_eu_item)).toBeInTheDocument(); }); - it('should render SelfExclusionArticle desktop component without is_appstore for EU items', () => { + it('should render SelfExclusionArticle for EU items', () => { mock_self_exclusion_context.is_eu = true; - const new_store = mockStore({ - ui: { - is_desktop: false, - is_mobile: true, - }, - }); render( - + @@ -77,16 +66,9 @@ describe('', () => { expect(screen.queryByText(non_eu_item)).not.toBeInTheDocument(); }); - it('should render SelfExclusionArticle desktop component for non EU items', () => { - const new_store = mockStore({ - ui: { - is_desktop: false, - is_mobile: false, - }, - }); - + it('should render SelfExclusionArticle for non EU items', () => { render( - + @@ -98,17 +80,11 @@ describe('', () => { expect(screen.queryByText(eu_item)).not.toBeInTheDocument(); }); - it('should render SelfExclusionArticle mobile component and trigger click', () => { - const new_store = mockStore({ - ui: { - is_desktop: false, - is_mobile: true, - }, - }); + it('should render SelfExclusionArticle component and trigger click', () => { const mockToggleArticle = mock_self_exclusion_context.toggleArticle; render( - + diff --git a/packages/account/src/Components/self-exclusion/__tests__/self-exclusion-wrapper.spec.tsx b/packages/account/src/Components/self-exclusion/__tests__/self-exclusion-wrapper.spec.tsx index 4dd015f8b12a..6b4cb757ffe0 100644 --- a/packages/account/src/Components/self-exclusion/__tests__/self-exclusion-wrapper.spec.tsx +++ b/packages/account/src/Components/self-exclusion/__tests__/self-exclusion-wrapper.spec.tsx @@ -1,12 +1,12 @@ import React from 'react'; -import { isMobile } from '@deriv/shared'; import { render, screen } from '@testing-library/react'; import SelfExclusionWrapper from '../self-exclusion-wrapper'; import SelfExclusionContext from '../self-exclusion-context'; +import { useDevice } from '@deriv-com/ui'; -jest.mock('@deriv/shared/src/utils/screen/responsive', () => ({ - ...jest.requireActual('@deriv/shared/src/utils/screen/responsive'), - isMobile: jest.fn(), +jest.mock('@deriv-com/ui', () => ({ + ...jest.requireActual('@deriv-com/ui'), + useDevice: jest.fn(() => ({ isDesktop: true })), })); jest.mock('../self-exclusion-article', () => { @@ -47,9 +47,9 @@ describe('', () => { expect(screen.getByRole('section-self-exclusion-wrapper')).not.toHaveClass('da-self-exclusion__scrollbars'); }); - it('should render SelfExclusionWrapper mobile component without wrapper', () => { + it('should render SelfExclusionWrapper responsive component without wrapper', () => { mock_context.is_wrapper_bypassed = true; - (isMobile as jest.Mock).mockReturnValue(true); + (useDevice as jest.Mock).mockReturnValueOnce({ isDesktop: false }); render( @@ -63,7 +63,6 @@ describe('', () => { }); it('should render SelfExclusionWrapper component with wrapper', () => { - (isMobile as jest.Mock).mockReturnValue(false); const mock_child =
MockChild
; render( @@ -73,13 +72,13 @@ describe('', () => { ); expect(screen.getByText('MockChild')).toBeInTheDocument(); - expect(screen.getAllByText('SelfExclusionArticle').length).toBe(1); + expect(screen.getByText('SelfExclusionArticle')).toBeInTheDocument(); expect(screen.getByTestId('dt_div_100_vh')).toHaveClass('da-self-exclusion__wrapper'); expect(screen.getByTestId('dt_themed_scrollbars')).toHaveClass('da-self-exclusion__scrollbars'); }); - it('should render SelfExclusionWrapper mobile component with wrapper', () => { - (isMobile as jest.Mock).mockReturnValue(true); + it('should render SelfExclusionWrapper responsive component with wrapper', () => { + (useDevice as jest.Mock).mockReturnValueOnce({ isDesktop: false }); const mock_child =
MockChild
; render( @@ -89,7 +88,7 @@ describe('', () => { ); expect(screen.getByText('MockChild')).toBeInTheDocument(); - expect(screen.getAllByText('SelfExclusionArticle').length).toBe(2); + expect(screen.getByText('SelfExclusionArticle')).toBeInTheDocument(); expect(screen.getByTestId('dt_div_100_vh')).toHaveClass('da-self-exclusion__wrapper'); expect(screen.getByTestId('dt_div_100_vh')).not.toHaveClass('da-self-exclusion__scrollbars'); }); diff --git a/packages/account/src/Components/self-exclusion/self-exclusion-inputs.tsx b/packages/account/src/Components/self-exclusion/self-exclusion-inputs.tsx index 0c6c9d1033d7..98776d6a22d3 100644 --- a/packages/account/src/Components/self-exclusion/self-exclusion-inputs.tsx +++ b/packages/account/src/Components/self-exclusion/self-exclusion-inputs.tsx @@ -1,7 +1,8 @@ import React from 'react'; import clsx from 'clsx'; import { Button, DatePicker, Input, Text } from '@deriv/components'; -import { epochToMoment, toMoment, isMobile } from '@deriv/shared'; +import { epochToMoment, toMoment } from '@deriv/shared'; +import { useDevice } from '@deriv-com/ui'; import { Localize, localize } from '@deriv/translations'; import { Field, @@ -33,11 +34,12 @@ type TFormikContext = { }; const SectionTitle = ({ title, has_border_line }: TSectionTitle) => { + const { isDesktop } = useDevice(); return ( { const { is_app_settings, is_wrapper_bypassed, state } = React.useContext(SelfExclusionContext); + const { isDesktop } = useDevice(); // "is_wrapper_bypassed" is currently used for a hosted . // It only features the for mobile views, as the footer @@ -19,7 +20,7 @@ const SelfExclusionWrapper = ({ children }: { children?: React.ReactNode }) => { 'da-self-exclusion--app-settings': is_app_settings, })} > - {isMobile() && } + {!isDesktop && } {children} ); @@ -30,14 +31,14 @@ const SelfExclusionWrapper = ({ children }: { children?: React.ReactNode }) => { className={clsx('da-self-exclusion__wrapper', { 'da-self-exclusion__wrapper--show-article': state?.show_article, })} - is_disabled={isDesktop()} + is_disabled={isDesktop} height_offset='80px' > - - {isMobile() && } + + {!isDesktop && } {children} - {isDesktop() && } + {isDesktop && } ); }; diff --git a/packages/account/src/Components/self-exclusion/self-exclusion.scss b/packages/account/src/Components/self-exclusion/self-exclusion.scss index d2835c14caf7..575300ae62be 100644 --- a/packages/account/src/Components/self-exclusion/self-exclusion.scss +++ b/packages/account/src/Components/self-exclusion/self-exclusion.scss @@ -23,7 +23,7 @@ } &-article { &__content { - @include mobile { + @include mobile-or-tablet-screen { margin: 1.6rem; } @@ -31,7 +31,7 @@ max-width: 440px; margin: 2.4rem; - @include mobile { + @include mobile-screen { max-height: 480px; margin: 1.6rem; } @@ -73,7 +73,7 @@ } > :last-child { - @include mobile { + @include mobile-or-tablet-screen { padding-bottom: 2.4rem; } } @@ -110,21 +110,18 @@ margin-top: 1.6rem; @include typeface(--paragraph-center-bold-red, none); } - @include mobile { - width: 300px; - height: 272px; - } } &__wrapper { display: flex; width: 100%; height: 100%; - @include mobile { + @include mobile-screen { &:not(&--show-article) { max-height: calc(100% - 72px); } - + } + @include mobile-or-tablet-screen { flex-direction: column; overflow-y: auto; } @@ -139,7 +136,7 @@ justify-content: center; align-items: center; - @include mobile { + @include mobile-or-tablet-screen { padding: 1.6rem; } @@ -180,7 +177,7 @@ margin-right: 1rem; height: 100%; - @include mobile { + @include mobile-or-tablet-screen { margin: 1.6rem; padding-bottom: 1.6rem; } @@ -221,10 +218,10 @@ grid-template-columns: 1fr 1fr 1fr; grid-gap: 1.6rem; - @media (max-width: 1024px) { - grid-template-columns: 1fr; + @include tablet-screen { + grid-template-columns: 2fr 2fr; } - @include mobile { + @include mobile-screen { grid-template-columns: 1fr; } } @@ -245,6 +242,9 @@ flex: 1; } &__button { + @include mobile-or-tablet-screen { + width: 100%; + } &-wrapper { position: sticky; bottom: 0; @@ -259,9 +259,12 @@ justify-content: flex-end; margin-top: 2.4rem; - @include mobile { + @include mobile-screen { position: absolute; } + @include tablet-screen { + padding: 0; + } } } &__warning { diff --git a/packages/account/src/Components/sent-email-modal/__tests__/sent-email-modal.spec.tsx b/packages/account/src/Components/sent-email-modal/__tests__/sent-email-modal.spec.tsx index ad13c9e32ab7..ec3b069ed7e9 100644 --- a/packages/account/src/Components/sent-email-modal/__tests__/sent-email-modal.spec.tsx +++ b/packages/account/src/Components/sent-email-modal/__tests__/sent-email-modal.spec.tsx @@ -1,12 +1,11 @@ import React from 'react'; import { fireEvent, render, screen } from '@testing-library/react'; -import { isMobile } from '@deriv/shared'; import SentEmailModal from '../sent-email-modal'; +import { useDevice } from '@deriv-com/ui'; -jest.mock('@deriv/shared', () => ({ - ...jest.requireActual('@deriv/shared'), - isMobile: jest.fn(), - isDesktop: jest.fn(), +jest.mock('@deriv-com/ui', () => ({ + ...jest.requireActual('@deriv-com/ui'), + useDevice: jest.fn(() => ({ isDesktop: true })), })); describe('', () => { @@ -84,7 +83,7 @@ describe('', () => { }); it('should render SentEmailModal component when isMobile is true', () => { - (isMobile as jest.Mock).mockReturnValue(true); + (useDevice as jest.Mock).mockReturnValueOnce({ isDesktop: false }); render( { + const { isDesktop } = useDevice(); + const getSubtitle = () => { let subtitle: string | React.ReactElement = ''; switch (identifier_title) { @@ -132,7 +135,7 @@ const SentEmailModal = ({ ); - if (isMobile() && !is_modal_when_mobile) { + if (!isDesktop && !is_modal_when_mobile) { return ( diff --git a/packages/account/src/Components/terms-of-use/fatca-declaration.tsx b/packages/account/src/Components/terms-of-use/fatca-declaration.tsx index fabeb7796cfb..8b41d212b91f 100644 --- a/packages/account/src/Components/terms-of-use/fatca-declaration.tsx +++ b/packages/account/src/Components/terms-of-use/fatca-declaration.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { FieldInputProps } from 'formik'; import { Text, Dropdown } from '@deriv/components'; -import { isDesktop } from '@deriv/shared'; +import { useDevice } from '@deriv-com/ui'; import { Localize, localize } from '@deriv/translations'; import { getFatcaDeclaration, getAgreementOptions } from '../../Constants/fatca-declaration'; import './terms-of-use.scss'; @@ -17,43 +17,46 @@ type TFATCADeclarationProps = { * @param field - Formik FieldInputProps * @returns React Component */ -const FatcaDeclaration = ({ field: { value, onChange, name }, ...props }: TFATCADeclarationProps) => ( - - - - -
-
    - {getFatcaDeclaration().map((item, idx) => ( - - {idx + 1}. {item} - - ))} -
- - ]} - /> +const FatcaDeclaration = ({ field: { value, onChange, name }, ...props }: TFATCADeclarationProps) => { + const { isDesktop } = useDevice(); + return ( + + + - -
-
-); +
+
    + {getFatcaDeclaration().map((item, idx) => ( + + {idx + 1}. {item} + + ))} +
+ + ]} + /> + + +
+ + ); +}; export default FatcaDeclaration; diff --git a/packages/account/src/Components/terms-of-use/terms-of-use-messages.tsx b/packages/account/src/Components/terms-of-use/terms-of-use-messages.tsx index 523d95e02a9b..3afdb6899cf9 100644 --- a/packages/account/src/Components/terms-of-use/terms-of-use-messages.tsx +++ b/packages/account/src/Components/terms-of-use/terms-of-use-messages.tsx @@ -1,7 +1,8 @@ import React from 'react'; import { Text } from '@deriv/components'; -import { getLegalEntityName, isDesktop, Jurisdiction, TBrokerCodes } from '@deriv/shared'; +import { getLegalEntityName, Jurisdiction, TBrokerCodes } from '@deriv/shared'; import { Localize } from '@deriv/translations'; +import { useDevice } from '@deriv-com/ui'; /** * Renders a horizontal line @@ -17,61 +18,68 @@ export const Hr = () =>
; * @returns JSX.Element */ -export const BrokerSpecificMessage = ({ target }: { target: TBrokerCodes }) => ( - - - - - - {target === Jurisdiction.SVG ? ( - - ) : ( - +export const BrokerSpecificMessage = ({ target }: { target: TBrokerCodes }) => { + const { isDesktop } = useDevice(); + + return ( + + + + + + {target === Jurisdiction.SVG ? ( + + ) : ( + + )} + +
+ + + + + + + {target === Jurisdiction.MALTA_INVEST && ( + +
+ + + + + + +
)} -
-
- - - - - - - {target === Jurisdiction.MALTA_INVEST && ( - -
- - - - - - -
- )} -
-); + + ); +}; /** * Returns the generic terms of use message * @name SVGDescription * @returns JSX.Element */ -export const SharedMessage = () => ( - - - - - - - - -); +export const SharedMessage = () => { + const { isDesktop } = useDevice(); + return ( + + + + + + + + + ); +}; diff --git a/packages/account/src/Components/terms-of-use/terms-of-use.tsx b/packages/account/src/Components/terms-of-use/terms-of-use.tsx index 8ad4f3fca0b1..d752dca8b66b 100644 --- a/packages/account/src/Components/terms-of-use/terms-of-use.tsx +++ b/packages/account/src/Components/terms-of-use/terms-of-use.tsx @@ -11,12 +11,13 @@ import { } from '@deriv/components'; import { useResidenceSelfDeclaration } from '@deriv/hooks'; import { observer } from '@deriv/stores'; -import { isDesktop, isMobile, TBrokerCodes } from '@deriv/shared'; +import { TBrokerCodes } from '@deriv/shared'; import { localize, Localize } from '@deriv/translations'; import CheckboxField from './checkbox-field'; import { SharedMessage, BrokerSpecificMessage, Hr } from './terms-of-use-messages'; import './terms-of-use.scss'; import FatcaDeclaration from './fatca-declaration'; +import { useDevice } from '@deriv-com/ui'; type TTermsOfUseFormProps = { agreed_tos: boolean; @@ -86,7 +87,7 @@ const TermsOfUse = observer( const current_step = (getCurrentStep?.() || 1) - 1; onSave(current_step, values); }; - + const { isDesktop } = useDevice(); return ( {({ handleSubmit, values, isSubmitting }) => ( - + {({ setRef }) => (
@@ -124,12 +125,12 @@ const TermsOfUse = observer( label={localize( 'I am not a PEP, and I have not been a PEP in the last 12 months.' )} - label_font_size={isDesktop() ? 'xs' : 'xxs'} + label_font_size={isDesktop ? 'xs' : 'xxs'} />
- + handleCancel()} cancel_label={localize('Previous')} form_error={props.form_error} diff --git a/packages/account/src/Components/trading-assessment/__tests__/trading-assessment-form.spec.tsx b/packages/account/src/Components/trading-assessment/__tests__/trading-assessment-form.spec.tsx index d6978ec7c3ad..56d622c014e6 100644 --- a/packages/account/src/Components/trading-assessment/__tests__/trading-assessment-form.spec.tsx +++ b/packages/account/src/Components/trading-assessment/__tests__/trading-assessment-form.spec.tsx @@ -30,55 +30,38 @@ describe('TradingAssessmentForm', () => { should_move_to_next: false, setSubSectionIndex: mockSetSubSectionIndex, is_independent_section: false, - is_mobile: false, + is_responsive: false, }; + const mock_store = mockStore({}); + afterEach(() => { jest.clearAllMocks(); }); - it('should display the provided question', () => { - const mock_store = mockStore({ - ui: { - is_mobile: false, - }, - }); + const renderComponent = () => { render( ); + }; + + it('should display the provided question', () => { + renderComponent(); expect( screen.getByText('Do you understand that you could potentially lose 100% of the money you use to trade?') ).toBeInTheDocument(); }); it('should display the provided options in the form', () => { - const mock_store = mockStore({ - ui: { - is_mobile: false, - }, - }); - render( - - - - ); + renderComponent(); expect(screen.getByText('Yes')).toBeInTheDocument(); expect(screen.getByText('No')).toBeInTheDocument(); }); it('should go to the next question on when the checkbox is "yes" and next button is selected', async () => { - const mock_store = mockStore({ - ui: { - is_mobile: false, - }, - }); - render( - - - - ); + renderComponent(); userEvent.click(screen.getByText('Yes')); userEvent.click(screen.getByText('Next')); @@ -91,16 +74,7 @@ describe('TradingAssessmentForm', () => { }); it('should call onCancel when displaying the first question and "Previous" is clicked', async () => { - const mock_store = mockStore({ - ui: { - is_mobile: false, - }, - }); - render( - - - - ); + renderComponent(); const prevButton = screen.getByRole('button', { name: /Previous/i }); userEvent.click(prevButton); const text = screen.getByText( diff --git a/packages/account/src/Components/trading-assessment/__tests__/trading-assessment-new-user.spec.tsx b/packages/account/src/Components/trading-assessment/__tests__/trading-assessment-new-user.spec.tsx index 8a525d546591..8f1834714da2 100644 --- a/packages/account/src/Components/trading-assessment/__tests__/trading-assessment-new-user.spec.tsx +++ b/packages/account/src/Components/trading-assessment/__tests__/trading-assessment-new-user.spec.tsx @@ -42,11 +42,7 @@ describe('TradingAssessmentNewUser', () => { it('should handle the cancel event correctly', () => { mockGetCurrentStep.mockReturnValue(2); - const mock_store = mockStore({ - ui: { - is_mobile: false, - }, - }); + const mock_store = mockStore({}); render( diff --git a/packages/account/src/Components/trading-assessment/risk-tolerance-warning-modal.tsx b/packages/account/src/Components/trading-assessment/risk-tolerance-warning-modal.tsx index 38c6c885e93a..70436cd930d9 100644 --- a/packages/account/src/Components/trading-assessment/risk-tolerance-warning-modal.tsx +++ b/packages/account/src/Components/trading-assessment/risk-tolerance-warning-modal.tsx @@ -1,6 +1,7 @@ import React from 'react'; -import { Button, Icon, Modal, Text, DesktopWrapper, MobileDialog, MobileWrapper } from '@deriv/components'; +import { Button, Icon, Modal, Text, MobileDialog } from '@deriv/components'; import { localize } from '@deriv/translations'; +import { useDevice } from '@deriv-com/ui'; type RiskToleranceWarningModalProps = { show_risk_modal: boolean; @@ -19,9 +20,10 @@ const RiskToleranceWarningModal = ({ body_content, has_sub_header = false, }: RiskToleranceWarningModalProps) => { + const { isDesktop } = useDevice(); return ( - + {isDesktop ? ( - - + ) : ( - + )} ); }; diff --git a/packages/account/src/Components/trading-assessment/test-warning-modal.tsx b/packages/account/src/Components/trading-assessment/test-warning-modal.tsx index fc81f738ab11..fdb015871faf 100644 --- a/packages/account/src/Components/trading-assessment/test-warning-modal.tsx +++ b/packages/account/src/Components/trading-assessment/test-warning-modal.tsx @@ -1,6 +1,7 @@ import React from 'react'; -import { DesktopWrapper, MobileDialog, MobileWrapper, Modal } from '@deriv/components'; +import { MobileDialog, Modal } from '@deriv/components'; import { localize } from '@deriv/translations'; +import { useDevice } from '@deriv-com/ui'; type TestWarningModalProps = { show_risk_modal: boolean; @@ -8,32 +9,34 @@ type TestWarningModalProps = { footer_content: JSX.Element; }; -const TestWarningModal = ({ show_risk_modal, body_content, footer_content }: TestWarningModalProps) => ( - - - - {body_content} - {footer_content} - - - - - {body_content} - {footer_content} - - - -); +const TestWarningModal = ({ show_risk_modal, body_content, footer_content }: TestWarningModalProps) => { + const { isDesktop } = useDevice(); + return ( + + {isDesktop ? ( + + {body_content} + {footer_content} + + ) : ( + + {body_content} + {footer_content} + + )} + + ); +}; export default TestWarningModal; diff --git a/packages/account/src/Components/trading-assessment/trading-assessment-dropdown.tsx b/packages/account/src/Components/trading-assessment/trading-assessment-dropdown.tsx index 747a2efe7f76..9f3d77d01d4a 100644 --- a/packages/account/src/Components/trading-assessment/trading-assessment-dropdown.tsx +++ b/packages/account/src/Components/trading-assessment/trading-assessment-dropdown.tsx @@ -1,10 +1,11 @@ import React from 'react'; import clsx from 'clsx'; import { Field } from 'formik'; -import { DesktopWrapper, Dropdown, MobileWrapper, Text, SelectNative } from '@deriv/components'; +import { Dropdown, Text, SelectNative } from '@deriv/components'; import { localize } from '@deriv/translations'; import { TTradingAssessmentForm, TQuestion } from 'Types'; import { MAX_QUESTION_TEXT_LENGTH } from '../../Constants/trading-assessment'; +import { useDevice } from '@deriv-com/ui'; type TradingAssessmentDropdownProps = { disabled_items: string[]; @@ -43,6 +44,8 @@ const TradingAssessmentDropdown = ({ checkIfAllFieldsFilled(); }, [values]); + const { isDesktop } = useDevice(); + const checkIfAllFieldsFilled = () => { if (values) { setEnableNextSection( @@ -67,7 +70,7 @@ const TradingAssessmentDropdown = ({ return ( - + {isDesktop ? ( - - - - {question?.question_text} - - { - onChange(e, question.form_control, setFieldValue); - }} - value={values[question.form_control]} - hide_top_placeholder - disabled={disabled_items.includes(question.form_control)} - error={meta.touched && meta.error} - /> - + ) : ( + + + {question?.question_text} + + { + onChange(e, question.form_control, setFieldValue); + }} + value={values[question.form_control]} + hide_top_placeholder + disabled={disabled_items.includes(question.form_control)} + error={meta.touched && meta.error} + /> + + )} ); }} diff --git a/packages/account/src/Components/trading-assessment/trading-assessment-form.tsx b/packages/account/src/Components/trading-assessment/trading-assessment-form.tsx index 97ab15c29f35..9d85001ed43f 100644 --- a/packages/account/src/Components/trading-assessment/trading-assessment-form.tsx +++ b/packages/account/src/Components/trading-assessment/trading-assessment-form.tsx @@ -23,7 +23,7 @@ type TradingAssessmentFormProps = { should_move_to_next: boolean; setSubSectionIndex: (index: number) => void; is_independent_section: boolean; - is_mobile?: boolean; + is_responsive?: boolean; }; const TradingAssessmentForm = observer( @@ -38,7 +38,7 @@ const TradingAssessmentForm = observer( should_move_to_next, setSubSectionIndex, is_independent_section, - is_mobile, + is_responsive, }: TradingAssessmentFormProps) => { const { traders_hub } = useStore(); const { is_eu_user } = traders_hub; @@ -271,7 +271,7 @@ const TradingAssessmentForm = observer(
diff --git a/packages/account/src/Components/trading-assessment/trading-assessment-new-user.tsx b/packages/account/src/Components/trading-assessment/trading-assessment-new-user.tsx index 18f27ad2900f..46f6bd8649f3 100644 --- a/packages/account/src/Components/trading-assessment/trading-assessment-new-user.tsx +++ b/packages/account/src/Components/trading-assessment/trading-assessment-new-user.tsx @@ -1,6 +1,6 @@ -import { observer, useStore } from '@deriv/stores'; import { TTradingAssessmentForm } from 'Types'; import TradingAssessmentForm from './trading-assessment-form'; +import { useDevice } from '@deriv-com/ui'; type TradingAssessmentNewUserProps = { disabled_items: string[]; @@ -20,61 +20,58 @@ type TradingAssessmentNewUserProps = { setSubSectionIndex: (index: number) => void; }; -const TradingAssessmentNewUser = observer( - ({ - disabled_items, - goToNextStep, - goToPreviousStep, - onSave, - onCancel, - onSubmit, - getCurrentStep, - value, - setSubSectionIndex, - }: TradingAssessmentNewUserProps) => { - const { ui } = useStore(); - const { is_mobile } = ui; - const handleCancel = (values: TTradingAssessmentForm) => { - const current_step = getCurrentStep() - 1; - onSave(current_step, values); - onCancel(current_step, goToPreviousStep); - }; +const TradingAssessmentNewUser = ({ + disabled_items, + goToNextStep, + goToPreviousStep, + onSave, + onCancel, + onSubmit, + getCurrentStep, + value, + setSubSectionIndex, +}: TradingAssessmentNewUserProps) => { + const { isDesktop } = useDevice(); + const handleCancel = (values: TTradingAssessmentForm) => { + const current_step = getCurrentStep() - 1; + onSave(current_step, values); + onCancel(current_step, goToPreviousStep); + }; - const handleSubmit = (values?: TTradingAssessmentForm, should_override?: boolean) => { - let process_form_values = { ...values }; - if (should_override) { - // Remove the keys with no values - process_form_values = Object.entries(process_form_values).reduce((accumulator, [key, val]) => { - if (val) { - return { ...accumulator, [key]: val }; - } - return { ...accumulator }; - }, {}); - } - onSubmit( - getCurrentStep() - 1, - process_form_values as TTradingAssessmentForm, - undefined, - goToNextStep, - should_override - ); - }; - - return ( - + const handleSubmit = (values?: TTradingAssessmentForm, should_override?: boolean) => { + let process_form_values = { ...values }; + if (should_override) { + // Remove the keys with no values + process_form_values = Object.entries(process_form_values).reduce((accumulator, [key, val]) => { + if (val) { + return { ...accumulator, [key]: val }; + } + return { ...accumulator }; + }, {}); + } + onSubmit( + getCurrentStep() - 1, + process_form_values as TTradingAssessmentForm, + undefined, + goToNextStep, + should_override ); - } -); + }; + + return ( + + ); +}; export default TradingAssessmentNewUser; diff --git a/packages/account/src/Containers/Account/account.tsx b/packages/account/src/Containers/Account/account.tsx index 6a86cbe8e179..989079fd3cb2 100644 --- a/packages/account/src/Containers/Account/account.tsx +++ b/packages/account/src/Containers/Account/account.tsx @@ -6,6 +6,7 @@ import { observer, useStore } from '@deriv/stores'; import PageOverlayWrapper from './page-overlay-wrapper'; import { TRoute } from '../../Types'; import 'Styles/account.scss'; +import { useDevice } from '@deriv-com/ui'; type TAccountProps = RouteComponentProps & { routes: Array; @@ -32,12 +33,12 @@ const Account = observer(({ history, location, routes }: TAccountProps) => { should_allow_poinc_authentication, is_passkey_supported, } = client; - const { toggleAccountSettings, is_account_settings_visible, is_mobile, is_desktop } = ui; - + const { toggleAccountSettings, is_account_settings_visible } = ui; + const { isMobile } = useDevice(); // subroutes of a route is structured as an array of arrays const subroutes = flatten(routes.map(i => i.subroutes)); const selected_content = subroutes.find(r => matchRoute(r, location.pathname)); - const should_remove_passkeys_route = is_desktop || (is_mobile && !is_passkey_supported); + const should_remove_passkeys_route = !isMobile || (isMobile && !is_passkey_supported); React.useEffect(() => { toggleAccountSettings(true); diff --git a/packages/account/src/Containers/Account/page-overlay-wrapper.tsx b/packages/account/src/Containers/Account/page-overlay-wrapper.tsx index 08acf59e49ee..bf11e9c160f2 100644 --- a/packages/account/src/Containers/Account/page-overlay-wrapper.tsx +++ b/packages/account/src/Containers/Account/page-overlay-wrapper.tsx @@ -7,6 +7,7 @@ import { observer, useStore } from '@deriv/stores'; import { Localize } from '@deriv/translations'; import TradingHubLogout from './tradinghub-logout'; import { TRoute } from '../../Types'; +import { useDevice } from '@deriv-com/ui'; type RouteItems = React.ComponentProps['list']; @@ -22,10 +23,10 @@ type PageOverlayWrapperProps = { */ const PageOverlayWrapper = observer(({ routes, subroutes }: PageOverlayWrapperProps) => { const history = useHistory(); - const { client, common, ui } = useStore(); - const { is_mobile } = ui; + const { client, common } = useStore(); const { logout } = client; const { is_from_derivgo } = common; + const { isDesktop } = useDevice(); const passkeysMenuCloseActionEventTrack = React.useCallback(() => { Analytics.trackEvent('ce_passkey_account_settings_form', { @@ -57,7 +58,7 @@ const PageOverlayWrapper = observer(({ routes, subroutes }: PageOverlayWrapperPr logout(); }; - if (is_mobile && selected_route) { + if (!isDesktop && selected_route) { const RouteComponent = selected_route.component as React.ElementType<{ component_icon: string | undefined }>; return ( } + is_sidebar_enabled={isDesktop} /> ); diff --git a/packages/account/src/Containers/toast-popup.tsx b/packages/account/src/Containers/toast-popup.tsx index 740016ba5be5..837bd9ac537d 100644 --- a/packages/account/src/Containers/toast-popup.tsx +++ b/packages/account/src/Containers/toast-popup.tsx @@ -1,8 +1,9 @@ import clsx from 'clsx'; import React from 'react'; import ReactDOM from 'react-dom'; -import { MobileWrapper, Toast } from '@deriv/components'; +import { Toast } from '@deriv/components'; import { observer, useStore } from '@deriv/stores'; +import { useDevice } from '@deriv-com/ui'; type TToastPopUp = { portal_id?: string; @@ -36,6 +37,7 @@ export const ToastPopup = ({ */ const NetworkStatusToastError = ({ status, portal_id, message }: TNetworkStatusToastError) => { const [is_open, setIsOpen] = React.useState(false); + const { isDesktop } = useDevice(); const new_portal_id = document.getElementById(portal_id); if (!new_portal_id || !message) return null; @@ -49,7 +51,7 @@ const NetworkStatusToastError = ({ status, portal_id, message }: TNetworkStatusT } return ReactDOM.createPortal( - + !isDesktop && ( {message} - , + ), new_portal_id ); }; diff --git a/packages/account/src/Sections/Assessment/FinancialAssessment/financial-assessment.tsx b/packages/account/src/Sections/Assessment/FinancialAssessment/financial-assessment.tsx index 239899ced2aa..8eb6a5285afe 100644 --- a/packages/account/src/Sections/Assessment/FinancialAssessment/financial-assessment.tsx +++ b/packages/account/src/Sections/Assessment/FinancialAssessment/financial-assessment.tsx @@ -5,18 +5,7 @@ import clsx from 'clsx'; import React from 'react'; import { Formik, FormikHelpers } from 'formik'; import { useHistory, withRouter } from 'react-router'; -import { - FormSubmitErrorMessage, - Loading, - Button, - Dropdown, - Modal, - Icon, - DesktopWrapper, - MobileWrapper, - SelectNative, - Text, -} from '@deriv/components'; +import { FormSubmitErrorMessage, Loading, Button, Dropdown, Modal, Icon, SelectNative, Text } from '@deriv/components'; import { routes, platforms, WS, shouldHideOccupationField } from '@deriv/shared'; import { observer, useStore } from '@deriv/stores'; import { localize, Localize } from '@deriv/translations'; @@ -50,6 +39,7 @@ import type { TCoreStores } from '@deriv/stores/types'; import { GetFinancialAssessment, GetFinancialAssessmentResponse } from '@deriv/api-types'; import { getFormattedOccupationList } from 'Configs/financial-details-config'; import { TFinancialInformationForm } from 'Types'; +import { useDevice } from '@deriv-com/ui'; type TConfirmationPage = { toggleModal: (prop: boolean) => void; @@ -189,7 +179,7 @@ const SubmittedPage = ({ platform, routeBackInApp }: TSubmittedPage) => { }; const FinancialAssessment = observer(() => { - const { client, common, notifications, ui } = useStore(); + const { client, common, notifications } = useStore(); const { landing_company_shortcode, is_virtual, @@ -201,9 +191,9 @@ const FinancialAssessment = observer(() => { is_authentication_needed, is_financial_information_incomplete, } = client; + const { isMobile, isTablet, isDesktop } = useDevice(); const { platform, routeBackInApp } = common; const { refreshNotifications } = notifications; - const { is_mobile, is_desktop } = ui; const is_mf = landing_company_shortcode === 'maltainvest'; const history = useHistory(); @@ -301,7 +291,7 @@ const FinancialAssessment = observer(() => { setIsSubmitSuccess(true); setIsBtnLoading(false); - if (is_desktop) { + if (isDesktop) { setTimeout(() => setIsSubmitSuccess(false), 10000); } }); @@ -331,7 +321,7 @@ const FinancialAssessment = observer(() => { const toggleConfirmationModal = (value: boolean) => { setIsConfirmationVisible(value); - if (is_mobile) { + if (isMobile) { setIsFormVisible(!value); } }; @@ -348,16 +338,17 @@ const FinancialAssessment = observer(() => { const getScrollOffset = () => { if (is_mf) { - if (is_mobile && is_financial_information_incomplete) return '22rem'; + if (isMobile && is_financial_information_incomplete) return '22rem'; return is_financial_information_incomplete && !is_submit_success ? '16.5rem' : '16rem'; - } else if (is_mobile) return '20rem'; + } else if (isMobile) return '22rem'; + else if (isTablet) return '20rem'; return '8rem'; }; if (is_loading) return ; if (api_initial_load_error) return ; if (is_virtual) return ; - if (is_mobile && is_authentication_needed && !is_mf && is_submit_success) + if (isMobile && is_authentication_needed && !is_mf && is_submit_success) return ; const setInitialFormData = () => { @@ -411,17 +402,17 @@ const FinancialAssessment = observer(() => { isValid, }) => ( - {is_mobile && is_confirmation_visible && ( + {isMobile && is_confirmation_visible && ( )} - {is_desktop && ( + {isDesktop && ( )} - undefined} /> + undefined} /> {is_form_visible && ( {is_mf && is_financial_information_incomplete && !is_submit_success && ( @@ -429,7 +420,7 @@ const FinancialAssessment = observer(() => {
- {is_mobile ? ( + {isMobile ? ( @@ -451,7 +442,7 @@ const FinancialAssessment = observer(() => { side_note={localize('We’re legally obliged to ask for your financial information.')} >
- + {isDesktop ? ( { handleBlur={handleBlur} error={touched.income_source && errors.income_source} /> - - + ) : ( { handleChange(e); }} /> - + )}
{!is_mf && (
- + {isDesktop ? ( { handleBlur={handleBlur} error={touched.employment_status && errors.employment_status} /> - - + ) : ( { handleChange(e); }} /> - + )}
)}
- + {isDesktop ? ( { handleBlur={handleBlur} error={touched.employment_industry && errors.employment_industry} /> - - + ) : ( { handleChange(e); }} /> - + )}
{!shouldHideOccupationField(values.employment_status || employment_status) && (
- + {isDesktop ? ( { error={touched.occupation && errors.occupation} test_id='occupation' /> - - + ) : ( { }} data_testid='occupation' /> - + )}
)}
- + {isDesktop ? ( { handleBlur={handleBlur} error={touched.source_of_wealth && errors.source_of_wealth} /> - - + ) : ( { handleChange(e); }} /> - + )}
- + {isDesktop ? ( { handleBlur={handleBlur} error={touched.education_level && errors.education_level} /> - - + ) : ( { handleChange(e); }} /> - + )}
- + {isDesktop ? ( { handleBlur={handleBlur} error={touched.net_income && errors.net_income} /> - - + ) : ( { handleChange(e); }} /> - + )}
- + {isDesktop ? ( { handleBlur={handleBlur} error={touched.estimated_worth && errors.estimated_worth} /> - - + ) : ( { handleChange(e); }} /> - + )}
- + {isDesktop ? ( { handleBlur={handleBlur} error={touched.account_turnover && errors.account_turnover} /> - - + ) : ( { handleChange(e); }} /> - + )}
{/* Trading experience fieldset */} @@ -741,7 +723,7 @@ const FinancialAssessment = observer(() => { />
- + {isDesktop ? ( { errors.forex_trading_experience } /> - - + ) : ( { handleChange(e); }} /> - + )}
- + {isDesktop ? ( { errors.forex_trading_frequency } /> - - + ) : ( { handleChange(e); }} /> - + )}
- + {isDesktop ? ( { errors.binary_options_trading_experience } /> - - + ) : ( { handleChange(e); }} /> - + )}
- + {isDesktop ? ( { errors.binary_options_trading_frequency } /> - - + ) : ( { handleChange(e); }} /> - + )}
- + {isDesktop ? ( { errors.cfd_trading_experience } /> - - + ) : ( { handleChange(e); }} /> - + )}
- + {isDesktop ? ( { errors.cfd_trading_frequency } /> - - + ) : ( { handleChange(e); }} /> - + )}
- + {isDesktop ? ( { errors.other_instruments_trading_experience } /> - - + ) : ( { handleChange(e); }} /> - + )}
- + {isDesktop ? ( { errors.other_instruments_trading_frequency } /> - - + ) : ( { handleChange(e); }} /> - + )}
@@ -1033,7 +1007,7 @@ const FinancialAssessment = observer(() => { {status?.msg && } - {is_mobile && !is_mf && ( + {isMobile && !is_mf && ( { return { @@ -34,8 +26,8 @@ const populateData = form_data => { required_initial_margin: form_data.required_initial_margin, }; }; - const TradingAssessment = observer(() => { + const { isDesktop } = useDevice(); const { client } = useStore(); const { is_virtual, setFinancialAndTradingAssessment } = client; const history = useHistory(); @@ -164,7 +156,7 @@ const TradingAssessment = observer(() => { {({ values, dirty, isSubmitting, handleChange, handleBlur }) => { return ( - + { if (item.field_type === 'radio') { return (
- - - {item.question_text} - - - - - - {item?.question_text} - - handleChange(e)} - should_show_empty_option={false} - /> - + {isDesktop ? ( + + + {item.question_text} + + + + ) : ( + + + {item?.question_text} + + handleChange(e)} + should_show_empty_option={false} + /> + + )}
); // eslint-disable-next-line no-else-return @@ -222,44 +217,47 @@ const TradingAssessment = observer(() => { const sub_form_control = items.form_control; return (
- - - {items.question_text} - - - - - - {items?.question_text} - - handleChange(e)} - should_show_empty_option={false} - /> - + {isDesktop ? ( + + + {items.question_text} + + + + ) : ( + + + {items?.question_text} + + handleChange(e)} + should_show_empty_option={false} + /> + + )}
); })} @@ -273,7 +271,7 @@ const TradingAssessment = observer(() => { is_disabled={isSubmitting || !dirty || is_btn_loading} is_loading={is_btn_loading} has_effect - is_absolute={isMobile()} + is_absolute={!isDesktop} is_submit_success={is_submit_success && !dirty} green={is_submit_success && !dirty} label={localize('Submit')} diff --git a/packages/account/src/Sections/Profile/LanguageSettings/__tests__/language-settings.spec.tsx b/packages/account/src/Sections/Profile/LanguageSettings/__tests__/language-settings.spec.tsx index 15d9aa4a0b94..e488156d4150 100644 --- a/packages/account/src/Sections/Profile/LanguageSettings/__tests__/language-settings.spec.tsx +++ b/packages/account/src/Sections/Profile/LanguageSettings/__tests__/language-settings.spec.tsx @@ -4,13 +4,28 @@ import userEvent from '@testing-library/user-event'; import { routes } from '@deriv/shared'; import LanguageSettings from '../language-settings'; import { mockStore, StoreProvider } from '@deriv/stores'; +import { useDevice } from '@deriv-com/ui'; import { useTranslations } from '@deriv-com/translations'; +jest.mock('@deriv-com/ui', () => ({ + ...jest.requireActual('@deriv-com/ui'), + useDevice: jest.fn(() => ({ isDesktop: true })), +})); + +jest.mock('@deriv/translations', () => ({ + ...jest.requireActual('@deriv/translations'), + getAllowedLanguages: jest.fn(() => ({ lang_1: 'Test Lang 1', lang_2: 'Test Lang 2' })), +})); + +jest.mock('@deriv/components', () => ({ + ...jest.requireActual('@deriv/components'), + Icon: jest.fn(() =>
Flag Icon
), +})); + jest.mock('@deriv-com/translations'); jest.mock('@deriv/shared', () => ({ ...jest.requireActual('@deriv/shared'), - isMobile: jest.fn(() => false), TranslationFlag: { EN: () =>
Language 1 Flag
, VI: () =>
Language 2 Flag
}, })); @@ -27,9 +42,6 @@ describe('LanguageSettings', () => { common: { current_language: 'lang_1', }, - ui: { - is_mobile: false, - }, }); (useTranslations as jest.Mock).mockReturnValue({ currentLang: 'EN', @@ -47,7 +59,7 @@ describe('LanguageSettings', () => { it('should render LanguageSettings', () => { renderLanguageSettings(); - expect(screen.getByText('Select Language')).toBeInTheDocument(); + expect(screen.getByText('Select language')).toBeInTheDocument(); const lang_1 = screen.getByText('English'); const lang_2 = screen.getByText('Tiếng Việt'); @@ -67,8 +79,8 @@ describe('LanguageSettings', () => { expect(mockRootStore.common.changeSelectedLanguage).toHaveBeenCalled(); }); - it('should redirect in mobile view when the user tries to reach `/account/languages` route', () => { - mockRootStore.ui.is_mobile = true; + it('should redirect in responsive view when the user tries to reach `/account/languages` route', () => { + (useDevice as jest.Mock).mockReturnValue({ isDesktop: false }); Object.defineProperty(window, 'location', { configurable: true, value: { pathname: routes.languages }, @@ -76,7 +88,7 @@ describe('LanguageSettings', () => { renderLanguageSettings(); - expect(screen.queryByText('Select Language')).not.toBeInTheDocument(); + expect(screen.queryByText('Select language')).not.toBeInTheDocument(); expect(screen.getByText('Redirect')).toBeInTheDocument(); }); diff --git a/packages/account/src/Sections/Profile/LanguageSettings/language-settings.tsx b/packages/account/src/Sections/Profile/LanguageSettings/language-settings.tsx index d6190105256a..d87327c38515 100644 --- a/packages/account/src/Sections/Profile/LanguageSettings/language-settings.tsx +++ b/packages/account/src/Sections/Profile/LanguageSettings/language-settings.tsx @@ -5,15 +5,15 @@ import { useTranslations, getAllowedLanguages } from '@deriv-com/translations'; import FormSubHeader from '../../../Components/form-sub-header'; import LanguageRadioButton from '../../../Components/language-settings'; import { useEffect } from 'react'; +import { useDevice } from '@deriv-com/ui'; const LanguageSettings = observer(() => { - const { client, common, ui } = useStore(); + const { client, common } = useStore(); const { switchLanguage, currentLang, localize } = useTranslations(); const { has_wallet } = client; // [TODO]: Remove changeSelectedLanguage() when whole app starts to use @deriv-com/translations const { changeSelectedLanguage, current_language } = common; - - const { is_mobile } = ui; + const { isDesktop } = useDevice(); // [TODO]: Remove useEffect() when whole app starts to use @deriv-com/translations // This is required to sync language state b/w footer language icon and Language settings @@ -21,14 +21,14 @@ const LanguageSettings = observer(() => { switchLanguage(current_language); }, [current_language, switchLanguage]); - if (is_mobile || has_wallet) { + if (!isDesktop || has_wallet) { return ; } const allowed_languages: Record = getAllowedLanguages(UNSUPPORTED_LANGUAGES); return (
- +
{Object.entries(allowed_languages).map(([language_key, value]) => { return ( diff --git a/packages/account/src/Sections/Profile/PersonalDetails/personal-details-form.tsx b/packages/account/src/Sections/Profile/PersonalDetails/personal-details-form.tsx index 4051acea592a..8ac9321ec2f2 100644 --- a/packages/account/src/Sections/Profile/PersonalDetails/personal-details-form.tsx +++ b/packages/account/src/Sections/Profile/PersonalDetails/personal-details-form.tsx @@ -225,7 +225,7 @@ const PersonalDetailsForm = observer(() => { dirty, }) => ( - + {show_form && ( { onSubmit={handleSubmit} data-testid='dt_account_personal_details_section' > - + {!is_virtual && ( @@ -648,7 +648,7 @@ const PersonalDetailsForm = observer(() => { className='account-form__footer-note' size='xxs' color='prominent' - align={!isDesktop ? 'center' : 'right'} + align={isDesktop ? 'right' : 'center'} > {localize( 'Please make sure your information is correct or it may affect your trading experience.' diff --git a/packages/account/src/Sections/Security/ApiToken/__tests__/api-token.spec.tsx b/packages/account/src/Sections/Security/ApiToken/__tests__/api-token.spec.tsx index d1273ceb989e..c0a8ba82fdf9 100644 --- a/packages/account/src/Sections/Security/ApiToken/__tests__/api-token.spec.tsx +++ b/packages/account/src/Sections/Security/ApiToken/__tests__/api-token.spec.tsx @@ -4,8 +4,14 @@ import { render, screen, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { getPropertyValue, WS } from '@deriv/shared'; import { mockStore, StoreProvider } from '@deriv/stores'; +import { useDevice } from '@deriv-com/ui'; import ApiToken from '../api-token'; +jest.mock('@deriv-com/ui', () => ({ + ...jest.requireActual('@deriv-com/ui'), + useDevice: jest.fn(() => ({ isDesktop: true })), +})); + jest.mock('@deriv/components', () => ({ ...jest.requireActual('@deriv/components'), Loading: () =>
Loading
, @@ -73,10 +79,6 @@ describe('', () => { client: { is_switching: false, }, - ui: { - is_desktop: true, - is_mobile: false, - }, }); const renderComponent = ({ store = mock_store }) => @@ -103,13 +105,8 @@ describe('', () => { expect(WS.authorized.apiToken).toHaveBeenCalled(); }); - it('should render ApiToken component for mobile', async () => { - const mock_store = mockStore({ - ui: { - is_desktop: false, - is_mobile: true, - }, - }); + it('should render ApiToken component for responsive', async () => { + (useDevice as jest.Mock).mockReturnValueOnce({ isDesktop: false }); renderComponent({ store: mock_store }); @@ -180,14 +177,11 @@ describe('', () => { }); it('should not render ApiToken component if data is still loading', async () => { + (useDevice as jest.Mock).mockReturnValueOnce({ isDesktop: false }); const new_store = mockStore({ client: { is_switching: true, }, - ui: { - is_desktop: false, - is_mobile: true, - }, }); renderComponent({ store: new_store }); @@ -257,7 +251,7 @@ describe('', () => { const warning_msg = 'Be careful who you share this token with. Anyone with this token can perform the following actions on your account behalf'; - (getPropertyValue as jest.Mock).mockReturnValue([ + (getPropertyValue as jest.Mock).mockReturnValueOnce([ { display_name: 'First test token', last_used: '', @@ -306,13 +300,8 @@ describe('', () => { jest.clearAllMocks(); }); - it('should render created tokens for mobile', async () => { - const new_store = mockStore({ - ui: { - is_desktop: false, - is_mobile: true, - }, - }); + it('should render created tokens for responsive', async () => { + (useDevice as jest.Mock).mockReturnValueOnce({ isDesktop: false }); (getPropertyValue as jest.Mock).mockReturnValue([ { display_name: 'First test token', @@ -337,14 +326,15 @@ describe('', () => { }, ]); - renderComponent({ store: new_store }); + renderComponent({}); - expect(await screen.findAllByText('Name')).toHaveLength(3); - expect(await screen.findAllByText('Last Used')).toHaveLength(3); - expect(await screen.findAllByText('Token')).toHaveLength(3); - expect(await screen.findAllByText('Scopes')).toHaveLength(3); + expect(await screen.findByText('Name')).toBeInTheDocument(); + expect(await screen.findByText('Token')).toBeInTheDocument(); + expect(await screen.findByText('Last used')).toBeInTheDocument(); + expect(await screen.findByText('Scopes')).toBeInTheDocument(); expect(await screen.findByText('First test token')).toBeInTheDocument(); expect(await screen.findByText('Second test token')).toBeInTheDocument(); + expect(await screen.findByText('Third test token')).toBeInTheDocument(); expect(screen.queryByText('Action')).not.toBeInTheDocument(); expect(screen.queryByText('SecondTokenID')).not.toBeInTheDocument(); const never_used = await screen.findAllByText('Never'); diff --git a/packages/account/src/Sections/Security/ApiToken/api-token.scss b/packages/account/src/Sections/Security/ApiToken/api-token.scss index 6ce3f105e0ec..09ed7f626e01 100644 --- a/packages/account/src/Sections/Security/ApiToken/api-token.scss +++ b/packages/account/src/Sections/Security/ApiToken/api-token.scss @@ -21,7 +21,7 @@ width: 100%; height: 100%; - @include mobile { + @include mobile-or-tablet-screen { flex-direction: column; } } @@ -45,7 +45,7 @@ grid-gap: 1.6rem; padding-bottom: 1.1rem; - @include mobile { + @include mobile-screen { grid-template-columns: 1fr; } } @@ -56,7 +56,7 @@ gap: 1rem; padding-right: 1.3rem; height: 2.1rem; - @media screen and (max-width: 926px) { + @include mobile-or-tablet-screen { padding-left: 0; } } @@ -94,7 +94,7 @@ gap: 0.4rem; max-width: 22rem; margin-right: 1rem; - @media screen and (max-width: 926px) { + @include mobile-or-tablet-screen { margin-top: 0.4rem; } } @@ -111,7 +111,7 @@ &__timeline { padding: 0 1.4rem 1.6rem; - @include mobile { + @include mobile-screen { margin: 1.2rem; } } @@ -122,6 +122,7 @@ background-color: var(--general-section-1); padding: 0.8rem; margin-bottom: 1.6rem; + border-radius: 0.8rem; &-item { margin-bottom: 0.8rem; @@ -154,9 +155,6 @@ } &__delete-icon { margin: 0 1.6rem; - @media screen and (max-width: 926px) { - margin-top: calc(50% - 3.3rem); - } } &__bullet { background-color: var(--text-prominent); diff --git a/packages/account/src/Sections/Security/ApiToken/api-token.tsx b/packages/account/src/Sections/Security/ApiToken/api-token.tsx index 64674b6d6c3e..75f8ab5986a1 100644 --- a/packages/account/src/Sections/Security/ApiToken/api-token.tsx +++ b/packages/account/src/Sections/Security/ApiToken/api-token.tsx @@ -3,6 +3,7 @@ import clsx from 'clsx'; import { Formik, Form, Field, FormikErrors, FieldProps, FormikHelpers } from 'formik'; import { ApiToken as TApitoken, APITokenResponse as TAPITokenResponse } from '@deriv/api-types'; import { Timeline, Input, Button, ThemedScrollbars, Loading } from '@deriv/components'; +import { useDevice } from '@deriv-com/ui'; import { getPropertyValue, WS } from '@deriv/shared'; import { observer, useStore } from '@deriv/stores'; import { Localize, localize } from '@deriv/translations'; @@ -33,10 +34,10 @@ type TApiTokenForm = { }; const ApiToken = observer(() => { - const { client, ui } = useStore(); + const { client } = useStore(); const { is_switching } = client; - const { is_desktop, is_mobile } = ui; const prev_is_switching = React.useRef(is_switching); + const { isDesktop } = useDevice(); const [state, setState] = React.useReducer( (prev_state: Partial, value: Partial) => ({ @@ -190,8 +191,8 @@ const ApiToken = observer(() => {
- - {is_mobile && } + + {!isDesktop && } {({ values, @@ -297,7 +298,7 @@ const ApiToken = observer(() => { )} - {is_desktop && } + {isDesktop && }
diff --git a/packages/account/src/Sections/Security/ConnectedApps/__tests__/connected-apps.spec.tsx b/packages/account/src/Sections/Security/ConnectedApps/__tests__/connected-apps.spec.tsx index 903061e7642f..34df116a5b5e 100644 --- a/packages/account/src/Sections/Security/ConnectedApps/__tests__/connected-apps.spec.tsx +++ b/packages/account/src/Sections/Security/ConnectedApps/__tests__/connected-apps.spec.tsx @@ -6,6 +6,12 @@ import userEvent from '@testing-library/user-event'; import ConnectedApps from '../connected-apps'; import { WS } from '@deriv/shared'; import { getConnectedAppsScopes } from '../template-helper'; +import { useDevice } from '@deriv-com/ui'; + +jest.mock('@deriv-com/ui', () => ({ + ...jest.requireActual('@deriv-com/ui'), + useDevice: jest.fn(() => ({ isDesktop: true })), +})); const mock_connected_apps: OauthApps = [ { @@ -111,8 +117,9 @@ describe('ConnectedApps', () => { }); }); - it('should render the app list in Mobile view', async () => { - renderComponent(mockStore({ ui: { is_mobile: true } })); + it('should render the app list in responsive view', async () => { + (useDevice as jest.Mock).mockReturnValueOnce({ isDesktop: false }); + renderComponent(); const mock_permissions = getConnectedAppsScopes(mock_connected_apps[0]?.scopes); await waitFor(() => { diff --git a/packages/account/src/Sections/Security/ConnectedApps/connected-apps-empty.tsx b/packages/account/src/Sections/Security/ConnectedApps/connected-apps-empty.tsx index 3b2c98efc12e..baddacfb5cb0 100644 --- a/packages/account/src/Sections/Security/ConnectedApps/connected-apps-empty.tsx +++ b/packages/account/src/Sections/Security/ConnectedApps/connected-apps-empty.tsx @@ -1,14 +1,12 @@ -import React from 'react'; import { Text } from '@deriv/components'; -import { observer, useStore } from '@deriv/stores'; import { Localize } from '@deriv/translations'; +import { useDevice } from '@deriv-com/ui'; import ConnectedAppsInfoBullets from './connected-apps-info-bullets'; -const ConnectedAppsEmpty = observer(() => { - const { ui } = useStore(); - const { is_mobile } = ui; +const ConnectedAppsEmpty = () => { + const { isDesktop } = useDevice(); - const text_size = is_mobile ? 'xxs' : 'xs'; + const text_size = isDesktop ? 'xs' : 'xxs'; return (
@@ -18,6 +16,6 @@ const ConnectedAppsEmpty = observer(() => {
); -}); +}; export default ConnectedAppsEmpty; diff --git a/packages/account/src/Sections/Security/ConnectedApps/connected-apps-info-bullets.tsx b/packages/account/src/Sections/Security/ConnectedApps/connected-apps-info-bullets.tsx index 211e8c709ccd..3cb5a882552e 100644 --- a/packages/account/src/Sections/Security/ConnectedApps/connected-apps-info-bullets.tsx +++ b/packages/account/src/Sections/Security/ConnectedApps/connected-apps-info-bullets.tsx @@ -1,6 +1,6 @@ import clsx from 'clsx'; import { Text } from '@deriv/components'; -import { observer, useStore } from '@deriv/stores'; +import { useDevice } from '@deriv-com/ui'; import { CONNECTED_APPS_INFO_BULLETS } from '../../../Constants/connected-apps-config'; type TConnectedAppsInfoBulletsProps = { @@ -8,11 +8,10 @@ type TConnectedAppsInfoBulletsProps = { text_color?: string; }; -const ConnectedAppsInfoBullets = observer(({ class_name, text_color }: TConnectedAppsInfoBulletsProps) => { - const { ui } = useStore(); - const { is_mobile } = ui; +const ConnectedAppsInfoBullets = ({ class_name, text_color }: TConnectedAppsInfoBulletsProps) => { + const { isDesktop } = useDevice(); - const text_size = is_mobile ? 'xxxs' : 'xxs'; + const text_size = isDesktop ? 'xxs' : 'xxxs'; return ( @@ -21,6 +20,6 @@ const ConnectedAppsInfoBullets = observer(({ class_name, text_color }: TConnecte ))} ); -}); +}; export default ConnectedAppsInfoBullets; diff --git a/packages/account/src/Sections/Security/ConnectedApps/connected-apps-info.tsx b/packages/account/src/Sections/Security/ConnectedApps/connected-apps-info.tsx index 498bcc9efccf..21595cac83d8 100644 --- a/packages/account/src/Sections/Security/ConnectedApps/connected-apps-info.tsx +++ b/packages/account/src/Sections/Security/ConnectedApps/connected-apps-info.tsx @@ -1,14 +1,14 @@ import React from 'react'; import { InlineMessage, Text } from '@deriv/components'; import { Localize } from '@deriv/translations'; -import { observer, useStore } from '@deriv/stores'; +import { observer } from '@deriv/stores'; +import { useDevice } from '@deriv-com/ui'; import ConnectedAppsInfoBullets from './connected-apps-info-bullets'; const ConnectedAppsInfo = observer(() => { - const { ui } = useStore(); - const { is_mobile } = ui; + const { isDesktop } = useDevice(); - const text_size = is_mobile ? 'xxxs' : 'xxs'; + const text_size = isDesktop ? 'xxs' : 'xxxs'; return ( { - const { ui } = useStore(); - const { is_mobile } = ui; - + const { isDesktop } = useDevice(); const [is_loading, setLoading] = React.useState(true); const [is_modal_open, setIsModalOpen] = React.useState(false); const [selected_app_id, setSelectedAppId] = React.useState(null); @@ -68,7 +67,7 @@ const ConnectedApps = observer(() => { {connected_apps.length ? (
- {is_mobile ? ( + {!isDesktop ? ( ) : ( diff --git a/packages/account/src/Sections/Security/LoginHistory/__test__/login-history-list-row.spec.tsx b/packages/account/src/Sections/Security/LoginHistory/__test__/login-history-list-row.spec.tsx index 96e0d0706875..ff257cd38ae8 100644 --- a/packages/account/src/Sections/Security/LoginHistory/__test__/login-history-list-row.spec.tsx +++ b/packages/account/src/Sections/Security/LoginHistory/__test__/login-history-list-row.spec.tsx @@ -1,12 +1,15 @@ import React from 'react'; import { screen, render } from '@testing-library/react'; -import { StoreProvider, mockStore } from '@deriv/stores'; import { APIProvider } from '@deriv/api'; +import { useDevice } from '@deriv-com/ui'; import LoginHistoryListRow from '../login-history-list-row'; -describe('LoginHistoryListRow', () => { - let mock_store: ReturnType; +jest.mock('@deriv-com/ui', () => ({ + ...jest.requireActual('@deriv-com/ui'), + useDevice: jest.fn(() => ({ isDesktop: true })), +})); +describe('LoginHistoryListRow', () => { const mock_props: React.ComponentProps = { id: 0, date: '2023-08-29 07:05:35 GMT', @@ -17,21 +20,10 @@ describe('LoginHistoryListRow', () => { }; const renderComponent = () => { - const wrapper = ({ children }: { children: JSX.Element }) => ( - - {children} - - ); + const wrapper = ({ children }: { children: JSX.Element }) => {children}; render(, { wrapper }); }; - beforeEach(() => { - mock_store = mockStore({ - ui: { - is_desktop: true, - }, - }); - }); it('should render LoginHistoryListRow Table Title', () => { const titles = [/date and time/i, /browser/i, /ip address/i, /action/i, /status/i]; renderComponent(); @@ -55,7 +47,7 @@ describe('LoginHistoryListRow', () => { }); it('should not render Status if is not desktop', () => { - mock_store.ui.is_desktop = false; + (useDevice as jest.Mock).mockReturnValueOnce({ isDesktop: false }); renderComponent(); expect(screen.queryByText('status')).not.toBeInTheDocument(); expect(screen.queryByText('successful')).not.toBeInTheDocument(); diff --git a/packages/account/src/Sections/Security/LoginHistory/__test__/login-history.spec.tsx b/packages/account/src/Sections/Security/LoginHistory/__test__/login-history.spec.tsx index adf89a858dea..9a3a989a69c9 100644 --- a/packages/account/src/Sections/Security/LoginHistory/__test__/login-history.spec.tsx +++ b/packages/account/src/Sections/Security/LoginHistory/__test__/login-history.spec.tsx @@ -2,9 +2,15 @@ import React from 'react'; import { screen, render, waitFor } from '@testing-library/react'; import { WS } from '@deriv/shared'; import { StoreProvider, mockStore } from '@deriv/stores'; +import { useDevice } from '@deriv-com/ui'; import LoginHistory from '../login-history'; import { getLoginHistoryFormattedData } from '@deriv/utils'; +jest.mock('@deriv-com/ui', () => ({ + ...jest.requireActual('@deriv-com/ui'), + useDevice: jest.fn(() => ({ isDesktop: true })), +})); + jest.mock('@deriv/components', () => ({ ...jest.requireActual('@deriv/components'), Loading: jest.fn(() => 'mockedLoading'), @@ -64,18 +70,11 @@ describe('', () => { is_switching: false, is_authorize: true, }, - ui: { - is_mobile: false, - }, }); }); - it('should render Login History List when is_mobile is true', async () => { - mock_store.ui.is_mobile = true; - renderComponent(); - await waitFor(() => { - expect(screen.getByText(/date and time/i)).toHaveClass('dc-text login-history__list__row__cell--title'); - }); + afterEach(() => { + jest.clearAllMocks(); }); it('should render Login History Table', async () => { @@ -155,6 +154,14 @@ describe('', () => { }); }); + it('should render Login History List for responsive screen', async () => { + (useDevice as jest.Mock).mockReturnValue({ isDesktop: false }); + renderComponent(); + await waitFor(() => { + expect(screen.getByText(/date and time/i)).toHaveClass('dc-text login-history__list__row__cell--title'); + }); + }); + it('should render Error with error message', async () => { WS.authorized.fetchLoginHistory = jest.fn(() => Promise.resolve({ diff --git a/packages/account/src/Sections/Security/LoginHistory/login-history-content.tsx b/packages/account/src/Sections/Security/LoginHistory/login-history-content.tsx index 04ed7942d671..10a8a62e83bd 100644 --- a/packages/account/src/Sections/Security/LoginHistory/login-history-content.tsx +++ b/packages/account/src/Sections/Security/LoginHistory/login-history-content.tsx @@ -1,5 +1,5 @@ import { Table } from '@deriv/components'; -import { observer, useStore } from '@deriv/stores'; +import { useDevice } from '@deriv-com/ui'; import getLoginHistoryTableHeaders from '../../../Constants/get-login-history-table-headers'; import LoginHistoryTableRow from './login-history-table-row'; import LoginHistoryListRow from './login-history-list-row'; @@ -21,12 +21,11 @@ type TLoginHistoryContent = { data: TLoginHistoryData; }; -const LoginHistoryContent = observer(({ data }: TLoginHistoryContent) => { - const { ui } = useStore(); - const { is_mobile } = ui; +const LoginHistoryContent = ({ data }: TLoginHistoryContent) => { + const { isDesktop } = useDevice(); - return is_mobile ? renderList(data) : renderTable(getLoginHistoryTableHeaders(), data); -}); + return isDesktop ? renderTable(getLoginHistoryTableHeaders(), data) : renderList(data); +}; const renderTable = (fields: TGetFields, login_history: TLoginHistoryData) => (
diff --git a/packages/account/src/Sections/Security/LoginHistory/login-history-list-row.tsx b/packages/account/src/Sections/Security/LoginHistory/login-history-list-row.tsx index 6688c8d16fa6..928e80bae998 100644 --- a/packages/account/src/Sections/Security/LoginHistory/login-history-list-row.tsx +++ b/packages/account/src/Sections/Security/LoginHistory/login-history-list-row.tsx @@ -2,14 +2,14 @@ import clsx from 'clsx'; import { TLoginHistoryItems } from '../../../Types'; import { Table } from '@deriv/components'; import { Localize } from '@deriv/translations'; +import { useDevice } from '@deriv-com/ui'; import getLoginHistoryTableHeaders from '../../../Constants/get-login-history-table-headers'; import ListCell from './list-cell'; -import { observer, useStore } from '@deriv/stores'; -const LoginHistoryListRow = observer(({ id, date, action, browser, ip, status }: TLoginHistoryItems) => { +const LoginHistoryListRow = ({ id, date, action, browser, ip, status }: TLoginHistoryItems) => { const { date_title, browser_title, action_title, ip_title, status_title } = getLoginHistoryTableHeaders(); - const { ui } = useStore(); - const { is_desktop } = ui; + const { isDesktop } = useDevice(); + return (
@@ -37,7 +37,7 @@ const LoginHistoryListRow = observer(({ id, date, action, browser, ip, status }: - {is_desktop && ( + {isDesktop && (
); -}); +}; export default LoginHistoryListRow; diff --git a/packages/account/src/Sections/Security/LoginHistory/login-history.tsx b/packages/account/src/Sections/Security/LoginHistory/login-history.tsx index c5ab5b0e5b94..f9def8ebee5d 100644 --- a/packages/account/src/Sections/Security/LoginHistory/login-history.tsx +++ b/packages/account/src/Sections/Security/LoginHistory/login-history.tsx @@ -2,6 +2,7 @@ import React from 'react'; import { Loading, ThemedScrollbars } from '@deriv/components'; import { observer, useStore } from '@deriv/stores'; import { WS, useIsMounted } from '@deriv/shared'; +import { useDevice } from '@deriv-com/ui'; import LoadErrorMessage from '../../../Components/load-error-message'; import LoginHistoryContent from './login-history-content'; import { getLoginHistoryFormattedData } from '@deriv/utils'; @@ -9,9 +10,9 @@ import { getLoginHistoryFormattedData } from '@deriv/utils'; type TLoginData = { id: number; date: string; action: string; browser: string; ip: string; status: string }[]; const LoginHistory = observer(() => { - const { client, ui } = useStore(); + const { client } = useStore(); + const { isDesktop } = useDevice(); const { is_switching } = client; - const { is_mobile } = ui; const [is_loading, setLoading] = React.useState(true); const [error, setError] = React.useState(''); const [data, setData] = React.useState([]); @@ -39,7 +40,7 @@ const LoginHistory = observer(() => { if (error) return ; return ( - + {data.length > 0 ? : null} ); diff --git a/packages/account/src/Sections/Security/Passkeys/__tests__/passkeys.spec.tsx b/packages/account/src/Sections/Security/Passkeys/__tests__/passkeys.spec.tsx index 25b93b94e976..bde4ce705c08 100644 --- a/packages/account/src/Sections/Security/Passkeys/__tests__/passkeys.spec.tsx +++ b/packages/account/src/Sections/Security/Passkeys/__tests__/passkeys.spec.tsx @@ -5,6 +5,7 @@ import userEvent from '@testing-library/user-event'; import { Analytics } from '@deriv-com/analytics'; import { APIProvider } from '@deriv/api'; import { useGetPasskeysList, useRegisterPasskey } from '@deriv/hooks'; +import { useDevice } from '@deriv-com/ui'; import { routes } from '@deriv/shared'; import { mockStore, StoreProvider } from '@deriv/stores'; import Passkeys from '../passkeys'; @@ -13,7 +14,7 @@ import { PasskeysList } from '../components/passkeys-list'; const passkey_name_1 = 'Test Passkey 1'; const passkey_name_2 = 'Test Passkey 2'; -export const mock_passkeys_list: React.ComponentProps['passkeys_list'] = [ +const mock_passkeys_list: React.ComponentProps['passkeys_list'] = [ { id: 1, name: passkey_name_1, @@ -59,6 +60,11 @@ jest.mock('@deriv/shared', () => ({ getOSNameWithUAParser: () => 'test OS', })); +jest.mock('@deriv-com/ui', () => ({ + ...jest.requireActual('@deriv-com/ui'), + useDevice: jest.fn(() => ({ isMobile: true })), +})); + describe('Passkeys', () => { let mock_store: ReturnType, modal_root_el: HTMLElement; const create_passkey = 'Create passkey'; @@ -86,7 +92,6 @@ describe('Passkeys', () => { beforeEach(() => { mock_store = mockStore({ - ui: { is_mobile: true }, client: { is_passkey_supported: true }, common: { network_status: { class: 'online' } }, }); @@ -117,12 +122,12 @@ describe('Passkeys', () => { const mockClearPasskeyRegistrationError = jest.fn(); const mockReloadPasskeysList = jest.fn(); - it("doesn't render existed passkeys for desktop", () => { + it("doesn't render existed passkeys for desktop and tablet", () => { (useGetPasskeysList as jest.Mock).mockReturnValue({ passkeys_list: mock_passkeys_list, }); + (useDevice as jest.Mock).mockReturnValueOnce({ isMobile: false }); - mock_store.ui.is_mobile = false; renderComponent(); expect(screen.queryByText(passkey_name_1)).not.toBeInTheDocument(); @@ -131,7 +136,6 @@ describe('Passkeys', () => { }); it('renders loader if passkeys list is loading', () => { - mock_store.ui.is_mobile = true; (useGetPasskeysList as jest.Mock).mockReturnValue({ is_passkeys_list_loading: true, }); diff --git a/packages/account/src/Sections/Security/Passkeys/components/__tests__/passkey-card.spec.tsx b/packages/account/src/Sections/Security/Passkeys/components/__tests__/passkey-card.spec.tsx index c0e4fe33266d..c0e635c64aff 100644 --- a/packages/account/src/Sections/Security/Passkeys/components/__tests__/passkey-card.spec.tsx +++ b/packages/account/src/Sections/Security/Passkeys/components/__tests__/passkey-card.spec.tsx @@ -2,7 +2,31 @@ import React from 'react'; import { screen, render } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { PasskeyCard } from '../passkey-card'; -import { mock_passkeys_list } from '../../__tests__/passkeys.spec'; +import { PasskeysList } from '../passkeys-list'; + +const passkey_name_1 = 'Test Passkey 1'; +const passkey_name_2 = 'Test Passkey 2'; + +const mock_passkeys_list: React.ComponentProps['passkeys_list'] = [ + { + id: 1, + name: passkey_name_1, + last_used: 1633024800000, + created_at: 1633024800000, + stored_on: 'Test device 1', + icon: 'Test Icon 1', + passkey_id: 'mock-id-1', + }, + { + id: 2, + name: passkey_name_2, + last_used: 1633124800000, + created_at: 1634024800000, + stored_on: 'Test device 2', + icon: 'Test Icon 2', + passkey_id: 'mock-id-2', + }, +]; jest.mock('@deriv/shared', () => ({ ...jest.requireActual('@deriv/shared'), diff --git a/packages/account/src/Sections/Security/Passkeys/components/__tests__/passkeys-list.spec.tsx b/packages/account/src/Sections/Security/Passkeys/components/__tests__/passkeys-list.spec.tsx index 80a8dd2f88ff..8e14a2f61068 100644 --- a/packages/account/src/Sections/Security/Passkeys/components/__tests__/passkeys-list.spec.tsx +++ b/packages/account/src/Sections/Security/Passkeys/components/__tests__/passkeys-list.spec.tsx @@ -2,7 +2,30 @@ import React from 'react'; import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { PasskeysList } from '../passkeys-list'; -import { mock_passkeys_list } from '../../__tests__/passkeys.spec'; + +const passkey_name_1 = 'Test Passkey 1'; +const passkey_name_2 = 'Test Passkey 2'; + +const mock_passkeys_list: React.ComponentProps['passkeys_list'] = [ + { + id: 1, + name: passkey_name_1, + last_used: 1633024800000, + created_at: 1633024800000, + stored_on: '', + icon: 'Test Icon 1', + passkey_id: 'mock-id-1', + }, + { + id: 2, + name: passkey_name_2, + last_used: 1633124800000, + created_at: 1634024800000, + stored_on: '', + icon: 'Test Icon 2', + passkey_id: 'mock-id-2', + }, +]; jest.mock('@deriv/shared', () => ({ ...jest.requireActual('@deriv/shared'), diff --git a/packages/account/src/Sections/Security/Passkeys/passkeys.tsx b/packages/account/src/Sections/Security/Passkeys/passkeys.tsx index 557a75ce906f..20f98ce3d8cb 100644 --- a/packages/account/src/Sections/Security/Passkeys/passkeys.tsx +++ b/packages/account/src/Sections/Security/Passkeys/passkeys.tsx @@ -3,6 +3,7 @@ import { Redirect, useHistory } from 'react-router-dom'; import { InlineMessage, Loading } from '@deriv/components'; import { useGetPasskeysList, useRegisterPasskey, useRenamePasskey } from '@deriv/hooks'; import { routes } from '@deriv/shared'; +import { useDevice } from '@deriv-com/ui'; import { observer, useStore } from '@deriv/stores'; import { Localize } from '@deriv/translations'; import { PasskeyErrorModal } from './components/passkey-error-modal'; @@ -30,9 +31,9 @@ export type TCurrentManagedPasskey = { }; const Passkeys = observer(() => { - const { client, ui, common } = useStore(); + const { client, common } = useStore(); + const { isMobile } = useDevice(); const { is_passkey_supported } = client; - const { is_mobile } = ui; const is_network_on = common.network_status.class === 'online'; const error_modal_timeout = useRef | null>(null); @@ -41,7 +42,7 @@ const Passkeys = observer(() => { const history = useHistory(); - const { passkeys_list, is_passkeys_list_loading, passkeys_list_error, reloadPasskeysList } = useGetPasskeysList(); + const { passkeys_list, is_passkeys_list_loading, passkeys_list_error } = useGetPasskeysList(); const { createPasskey, clearPasskeyRegistrationError, @@ -60,7 +61,7 @@ const Passkeys = observer(() => { name: '', }); - const should_show_passkeys = is_passkey_supported && is_mobile; + const should_show_passkeys = is_passkey_supported && isMobile; const error = passkeys_list_error || passkey_registration_error || passkey_renaming_error; useEffect(() => { diff --git a/packages/account/src/Sections/Security/TwoFactorAuthentication/__test__/two-factor-disabled.spec.tsx b/packages/account/src/Sections/Security/TwoFactorAuthentication/__test__/two-factor-disabled.spec.tsx index 2c5e9a6c7c04..2349ab7d28f1 100644 --- a/packages/account/src/Sections/Security/TwoFactorAuthentication/__test__/two-factor-disabled.spec.tsx +++ b/packages/account/src/Sections/Security/TwoFactorAuthentication/__test__/two-factor-disabled.spec.tsx @@ -1,8 +1,14 @@ import React from 'react'; import { render, screen } from '@testing-library/react'; import { StoreProvider, mockStore } from '@deriv/stores'; +import { useDevice } from '@deriv-com/ui'; import TwoFactorDisabled from '../two-factor-disabled'; +jest.mock('@deriv-com/ui', () => ({ + ...jest.requireActual('@deriv-com/ui'), + useDevice: jest.fn(() => ({ isDesktop: true })), +})); + jest.mock('@deriv/components', () => ({ ...jest.requireActual('@deriv/components'), Loading: jest.fn(() => 'mockedLoading'), @@ -17,11 +23,7 @@ describe('', () => { is_qr_loading: false, }; - const store = mockStore({ - ui: { - is_mobile: true, - }, - }); + const store = mockStore({}); const renderComponent = ({ store_config = store, mock = mock_props }) => { render( @@ -88,16 +90,10 @@ describe('', () => { expect(digitform).toBeInTheDocument(); }); - it('should render 2FA article component for mobile', () => { - const new_store = { - ...store, - ui: { - ...store.ui, - is_mobile: true, - }, - }; + it('should render 2FA article component for responsive view', () => { + (useDevice as jest.Mock).mockReturnValueOnce({ isDesktop: false }); - renderComponent({ store_config: new_store }); + renderComponent({ store_config: store }); const article_component = screen.getByText('Two-factor authentication (2FA)'); expect(article_component).toBeInTheDocument(); diff --git a/packages/account/src/Sections/Security/TwoFactorAuthentication/__test__/two-factor-enabled.spec.tsx b/packages/account/src/Sections/Security/TwoFactorAuthentication/__test__/two-factor-enabled.spec.tsx index 21997b9ad952..d9aeaabe18a6 100644 --- a/packages/account/src/Sections/Security/TwoFactorAuthentication/__test__/two-factor-enabled.spec.tsx +++ b/packages/account/src/Sections/Security/TwoFactorAuthentication/__test__/two-factor-enabled.spec.tsx @@ -3,6 +3,11 @@ import { render, screen } from '@testing-library/react'; import { StoreProvider, mockStore } from '@deriv/stores'; import TwoFactorEnabled from '../two-factor-enabled'; +jest.mock('@deriv-com/ui', () => ({ + ...jest.requireActual('@deriv-com/ui'), + useDevice: jest.fn(() => ({ isDesktop: true })), +})); + describe('', () => { const store = mockStore({}); diff --git a/packages/account/src/Sections/Security/TwoFactorAuthentication/two-factor-disabled.tsx b/packages/account/src/Sections/Security/TwoFactorAuthentication/two-factor-disabled.tsx index ff1ba4e46b4d..95dd4099d5ba 100644 --- a/packages/account/src/Sections/Security/TwoFactorAuthentication/two-factor-disabled.tsx +++ b/packages/account/src/Sections/Security/TwoFactorAuthentication/two-factor-disabled.tsx @@ -3,8 +3,8 @@ import QRCodeSVG from 'qrcode.react'; import { ThemedScrollbars, Text, Timeline, Loading, Clipboard } from '@deriv/components'; import TwoFactorAuthenticationArticle from './two-factor-authentication-article'; import { Localize, localize } from '@deriv/translations'; +import { useDevice } from '@deriv-com/ui'; import DigitForm from './digit-form'; -import { useStore } from '@deriv/stores'; type TTwoFactorDisabled = { secret_key: string; @@ -13,12 +13,11 @@ type TTwoFactorDisabled = { }; const TwoFactorDisabled = ({ secret_key, qr_secret_key, is_qr_loading }: TTwoFactorDisabled) => { - const { ui } = useStore(); - const { is_mobile, is_desktop } = ui; + const { isDesktop } = useDevice(); return ( - - {is_mobile && } + + {!isDesktop && } @@ -88,7 +87,7 @@ const TwoFactorDisabled = ({ secret_key, qr_secret_key, is_qr_loading }: TTwoFac - {is_desktop && } + {isDesktop && } ); }; diff --git a/packages/account/src/Sections/Security/TwoFactorAuthentication/two-factor-enabled.tsx b/packages/account/src/Sections/Security/TwoFactorAuthentication/two-factor-enabled.tsx index d130b7349b40..d531d3a5338f 100644 --- a/packages/account/src/Sections/Security/TwoFactorAuthentication/two-factor-enabled.tsx +++ b/packages/account/src/Sections/Security/TwoFactorAuthentication/two-factor-enabled.tsx @@ -1,14 +1,13 @@ import React from 'react'; import { Icon, ThemedScrollbars, Text } from '@deriv/components'; +import { useDevice } from '@deriv-com/ui'; import DigitForm from './digit-form'; -import { useStore } from '@deriv/stores'; import { Localize } from '@deriv/translations'; const TwoFactorEnabled = () => { - const { ui } = useStore(); - const { is_mobile } = ui; + const { isDesktop } = useDevice(); return ( - +
diff --git a/packages/account/src/Sections/Verification/ProofOfAddress/proof-of-address-form.tsx b/packages/account/src/Sections/Verification/ProofOfAddress/proof-of-address-form.tsx index 87e4709c15db..c0737403b0eb 100644 --- a/packages/account/src/Sections/Verification/ProofOfAddress/proof-of-address-form.tsx +++ b/packages/account/src/Sections/Verification/ProofOfAddress/proof-of-address-form.tsx @@ -293,7 +293,7 @@ const ProofOfAddressForm = observer( is_bypassed={!is_for_cfd_modal || !isDesktop} className={className} > - + {(status?.msg || is_resubmit) && ( +
{component_to_load || ( { return ( - + {({ setRef, height }) => (
diff --git a/packages/account/src/Sections/Verification/ProofOfIncome/proof-of-income-form.tsx b/packages/account/src/Sections/Verification/ProofOfIncome/proof-of-income-form.tsx index b0246434f0bb..c603f27dd326 100644 --- a/packages/account/src/Sections/Verification/ProofOfIncome/proof-of-income-form.tsx +++ b/packages/account/src/Sections/Verification/ProofOfIncome/proof-of-income-form.tsx @@ -21,6 +21,7 @@ import FileUploaderContainer from '../../../Components/file-uploader-container'; import { getFileUploaderDescriptions } from '../../../Constants/file-uploader'; import { isServerError } from 'Helpers/utils'; import { income_status_codes, getPoincDocumentsList } from 'Sections/Verification/ProofOfIncome/proof-of-income-utils'; +import { useDevice } from '@deriv-com/ui'; type TProofOfIncomeForm = { onSubmit: (status: typeof income_status_codes[keyof typeof income_status_codes]) => void; @@ -37,9 +38,9 @@ const ProofOfIncomeForm = observer(({ onSubmit }: TProofOfIncomeForm) => { const poinc_documents_list = React.useMemo(() => getPoincDocumentsList(), []); const poinc_uploader_files_descriptions = React.useMemo(() => getFileUploaderDescriptions('poinc'), []); - const { notifications, ui } = useStore(); + const { notifications } = useStore(); const { addNotificationMessageByKey, removeNotificationMessage, removeNotificationByKey } = notifications; - const { is_mobile, is_desktop } = ui; + const { isMobile, isDesktop } = useDevice(); const { upload } = useFileUploader(); @@ -116,11 +117,11 @@ const ProofOfIncomeForm = observer(({ onSubmit }: TProofOfIncomeForm) => { values, }) => ( - +
{({ field }: FormikValues) => ( @@ -173,7 +174,7 @@ const ProofOfIncomeForm = observer(({ onSubmit }: TProofOfIncomeForm) => {
{ diff --git a/packages/account/src/Sections/Verification/ProofOfOwnership/proof-of-ownership-form.tsx b/packages/account/src/Sections/Verification/ProofOfOwnership/proof-of-ownership-form.tsx index 10cb82bf4805..69f6b5878dd8 100644 --- a/packages/account/src/Sections/Verification/ProofOfOwnership/proof-of-ownership-form.tsx +++ b/packages/account/src/Sections/Verification/ProofOfOwnership/proof-of-ownership-form.tsx @@ -6,6 +6,7 @@ import { Form, Formik, FormikHelpers } from 'formik'; import DocumentUploader from '@binary-com/binary-document-uploader'; import { Button } from '@deriv/components'; import { readFiles, WS, UPLOAD_FILE_TYPE } from '@deriv/shared'; +import { useDevice } from '@deriv-com/ui'; import { observer, useStore } from '@deriv/stores'; import { Localize, localize } from '@deriv/translations'; import FormFooter from '../../../Components/form-footer'; @@ -28,10 +29,10 @@ type TProofOfOwnershipFormProps = { }; const ProofOfOwnershipForm = observer(({ grouped_payment_method_data }: TProofOfOwnershipFormProps) => { - const { client, notifications, ui } = useStore(); + const { client, notifications } = useStore(); const { refreshNotifications } = notifications; const { email: client_email, updateAccountStatus } = client; - const { is_mobile } = ui; + const { isDesktop } = useDevice(); const grouped_payment_method_data_keys = Object.keys(grouped_payment_method_data) as Array; @@ -41,11 +42,11 @@ const ProofOfOwnershipForm = observer(({ grouped_payment_method_data }: TProofOf const getScrollOffset = React.useCallback( (items_count = 0) => { - if (is_mobile) return '20rem'; + if (!isDesktop) return '20rem'; if (items_count <= 2) return '0rem'; return '8rem'; }, - [is_mobile] + [isDesktop] ); const initial_values = React.useMemo(() => { diff --git a/packages/account/src/Styles/account.scss b/packages/account/src/Styles/account.scss index 26b3c4177012..6a6715f27fb4 100644 --- a/packages/account/src/Styles/account.scss +++ b/packages/account/src/Styles/account.scss @@ -6,12 +6,19 @@ $MIN_HEIGHT_FLOATING: calc( .account { margin: 0 16px; + @include mobile-or-tablet-screen { + height: 100%; + } .dc-page-overlay__content { @include mobile-or-tablet-screen { overflow-x: hidden; overflow-y: auto; } + @include tablet-screen { + width: 60rem; + height: 100%; + } } .dc-vertical-tab { @@ -70,7 +77,7 @@ $MIN_HEIGHT_FLOATING: calc( .account__scrollbars_container { width: 68.5rem; margin-inline-start: 6rem; - padding-top: 0; + height: 100%; } } @@ -217,6 +224,25 @@ $MIN_HEIGHT_FLOATING: calc( } } } + @include mobile-or-tablet-screen { + &__financial-assessment { + .account-form__fieldset { + margin-top: 0.8rem; + margin-bottom: 2rem; + } + } + } + + @include tablet-screen { + .account-form__fieldset { + max-width: 100%; + } + .account-form__footer-note { + width: auto; + text-align: center; + align-self: center; + } + } &__header { font-size: var(--text-size-xs); @@ -286,6 +312,7 @@ $MIN_HEIGHT_FLOATING: calc( .dc-list { .dc-themed-scrollbars__autohide { top: 1px; + height: 100%; } } } @@ -294,7 +321,10 @@ $MIN_HEIGHT_FLOATING: calc( &__fieldset { position: relative; max-width: 400px; - + @include mobile-or-tablet-screen { + max-width: 100%; + width: 100%; + } .cfd-personal-details-modal__form & { margin: unset; max-width: unset; @@ -383,7 +413,6 @@ $MIN_HEIGHT_FLOATING: calc( &__personal-details { @include desktop-screen { .account__scrollbars_container { - padding-top: 2.4rem; padding-bottom: 2.4rem; } } @@ -417,6 +446,13 @@ $MIN_HEIGHT_FLOATING: calc( } } } + + @include tablet-screen { + .dc-form-submit-error-message { + width: 100%; + justify-content: center; + } + } } &__trading-assessment, @@ -502,7 +538,7 @@ $MIN_HEIGHT_FLOATING: calc( @include mobile-or-tablet-screen { width: 100%; - margin-right: unset; + margin-inline-end: unset; margin-bottom: 2.4rem; } @@ -518,6 +554,9 @@ $MIN_HEIGHT_FLOATING: calc( &-btn { min-width: 14.9rem; + @include tablet-screen { + margin: 0; + } } } @@ -603,6 +642,12 @@ $MIN_HEIGHT_FLOATING: calc( } .account-management { + &__container { + @include mobile-or-tablet-screen { + margin-inline: auto; + margin-block-start: 1.6rem; + } + } &__list { &-container { margin-top: 1.6rem; @@ -689,6 +734,9 @@ $MIN_HEIGHT_FLOATING: calc( display: flex; justify-content: center; width: 100%; + @include mobile-or-tablet-screen { + margin-block-start: 1.6rem; + } &-full-width { width: calc(100vw - 33rem); @@ -858,10 +906,10 @@ $MIN_HEIGHT_FLOATING: calc( &__title { margin-bottom: 1.5rem; - margin-left: 1.2rem; + margin-inline-start: 1.2rem; @include mobile-or-tablet-screen { - margin-right: 1.2rem; + margin-inline-end: 1.2rem; } } @@ -885,7 +933,7 @@ $MIN_HEIGHT_FLOATING: calc( &__button { border-top-left-radius: 0; border-bottom-left-radius: 0; - margin-left: -1px; + margin-inline-start: -1px; } &__link { @@ -896,7 +944,7 @@ $MIN_HEIGHT_FLOATING: calc( padding: 0 1.4rem; @include mobile-or-tablet-screen { - margin-left: 1.2rem; + margin-inline-start: 1.2rem; } } @@ -936,7 +984,7 @@ $MIN_HEIGHT_FLOATING: calc( align-items: center; span { - margin-right: 0.8rem; + margin-inline-end: 0.8rem; } } } @@ -1527,9 +1575,9 @@ $MIN_HEIGHT_FLOATING: calc( .proof-of-income { width: 100%; - &, .account-form__footer { - max-width: 68rem; + max-width: 100%; + align-items: center; } .account__scrollbars_container { @@ -1580,11 +1628,11 @@ $MIN_HEIGHT_FLOATING: calc( line-height: 1.43; & > ul { - padding-left: 3%; + padding-inline-start: 3%; list-style-type: disc; @include mobile-or-tablet-screen { - padding-left: 5%; + padding-inline-start: 5%; } @include rtl { @@ -1593,6 +1641,10 @@ $MIN_HEIGHT_FLOATING: calc( } } } + + @include mobile-or-tablet-screen { + margin-top: 0.8rem; + } } &__title { @@ -1613,7 +1665,7 @@ $MIN_HEIGHT_FLOATING: calc( background-color: transparent; @include mobile-or-tablet-screen { - align-self: center; + align-self: flex-start; } } @@ -1621,18 +1673,18 @@ $MIN_HEIGHT_FLOATING: calc( &--cancel { margin-top: 2.4rem; margin-inline-end: 10px; - float: right; + float: inline-end; @include mobile-or-tablet-screen { margin-top: -8px; margin-inline-end: 10px; - float: right; + float: inline-end; } } &--close-account { margin-top: 2.4rem; - float: right; + float: inline-end; @include mobile-or-tablet-screen { float: none; @@ -1712,7 +1764,6 @@ $MIN_HEIGHT_FLOATING: calc( @include mobile-or-tablet-screen { position: fixed; bottom: 0; - left: 0; background: var(--general-main-1); width: 100vw; margin: unset; @@ -1915,11 +1966,11 @@ $MIN_HEIGHT_FLOATING: calc( &-text { line-height: 2.4rem; - padding-left: 1.6rem; + padding-inline-start: 1.6rem; } &-icon { - margin-left: auto; + margin-inline-start: auto; transition: transform 0.3s cubic-bezier(0.25, 0.1, 0.25, 1); padding: 0; @@ -2000,7 +2051,7 @@ $MIN_HEIGHT_FLOATING: calc( box-sizing: border-box; border-radius: 4px; height: 4rem; - margin-right: 10px; + margin-inline-end: 10px; color: var(--text-less-prominent); -webkit-text-fill-color: var(--text-less-prominent); @@ -2014,7 +2065,7 @@ $MIN_HEIGHT_FLOATING: calc( @include mobile-or-tablet-screen { width: 100%; - margin-left: 0; + margin-inline-start: 0; margin-top: 1.6rem; } @@ -2025,7 +2076,7 @@ $MIN_HEIGHT_FLOATING: calc( } &-btn { - margin-left: 1rem; + margin-inline-start: 1rem; padding: 10px 16px; position: static; height: 40px; @@ -2050,11 +2101,11 @@ $MIN_HEIGHT_FLOATING: calc( display: flex; flex-direction: column; align-items: center; - margin-right: 25px; + margin-inline-end: 2.5rem; overflow: visible; @include mobile-or-tablet-screen { - margin-right: 8px; + margin-inline-end: 0.8rem; } &-number { diff --git a/packages/components/src/components/form-submit-error-message/form-submit-error-message.scss b/packages/components/src/components/form-submit-error-message/form-submit-error-message.scss index 0069cd3da244..1ed5a80f47d8 100644 --- a/packages/components/src/components/form-submit-error-message/form-submit-error-message.scss +++ b/packages/components/src/components/form-submit-error-message/form-submit-error-message.scss @@ -8,12 +8,12 @@ p { padding-left: 0.8rem; - @include mobile { + @include mobile-or-tablet-screen { line-height: 20px; } } - @include mobile { + @include mobile-or-tablet-screen { padding: 0 1.6rem 1rem; position: absolute; bottom: 7rem; diff --git a/packages/components/src/components/modal/modal.scss b/packages/components/src/components/modal/modal.scss index 11bb17b3f329..7d61fe4ba019 100644 --- a/packages/components/src/components/modal/modal.scss +++ b/packages/components/src/components/modal/modal.scss @@ -79,7 +79,7 @@ } } } - @include desktop-screen { + @include tablet-or-desktop-screen { min-width: 440px !important; max-height: calc(100vh - #{$HEADER_HEIGHT} - #{$FOOTER_HEIGHT}) !important; } @@ -88,7 +88,7 @@ } } &__container_sent-email__modal { - @include mobile { + @include mobile-or-tablet-screen { height: 42rem !important; overflow-y: scroll !important; } diff --git a/packages/components/src/components/select-native/select-native.scss b/packages/components/src/components/select-native/select-native.scss index b297aab9323a..720111a15efc 100644 --- a/packages/components/src/components/select-native/select-native.scss +++ b/packages/components/src/components/select-native/select-native.scss @@ -55,6 +55,10 @@ justify-content: flex-start; padding-left: 1.2rem; + @include tablet-screen { + max-width: 56.8rem; + } + &-text { color: var(--text-prominent); font-size: 1.4rem; diff --git a/packages/components/src/components/themed-scrollbars/themed-scrollbars.scss b/packages/components/src/components/themed-scrollbars/themed-scrollbars.scss index eb61dcefa1ec..9c3d9061e158 100644 --- a/packages/components/src/components/themed-scrollbars/themed-scrollbars.scss +++ b/packages/components/src/components/themed-scrollbars/themed-scrollbars.scss @@ -7,6 +7,9 @@ /* Firefox only */ scrollbar-color: var(--state-active) var(--general-main-1); scrollbar-width: thin; + @include mobile-or-tablet-screen { + height: 100%; + } &__autohide { &::-webkit-scrollbar-thumb { diff --git a/packages/core/src/App/AppContent.tsx b/packages/core/src/App/AppContent.tsx index e7007a27188b..e90875499383 100644 --- a/packages/core/src/App/AppContent.tsx +++ b/packages/core/src/App/AppContent.tsx @@ -1,5 +1,6 @@ import React from 'react'; import { useRemoteConfig } from '@deriv/api'; +import { useDevice } from '@deriv-com/ui'; import { useIsMounted } from '@deriv/shared'; import { observer, useStore } from '@deriv/stores'; import { browserSupportsWebAuthn } from '@simplewebauthn/browser'; @@ -22,6 +23,7 @@ import { useGrowthbookIsOn } from '@deriv/hooks'; const AppContent: React.FC<{ passthrough: unknown }> = observer(({ passthrough }) => { const store = useStore(); const { has_wallet } = store.client; + const { isMobile } = useDevice(); const [isWebPasskeysFFEnabled, isGBLoaded] = useGrowthbookIsOn({ featureFlag: 'web_passkeys', @@ -37,10 +39,10 @@ const AppContent: React.FC<{ passthrough: unknown }> = observer(({ passthrough } React.useEffect(() => { if (isGBLoaded && isWebPasskeysFFEnabled && isServicePasskeysFFEnabled) { store.client.setIsPasskeySupported( - is_passkeys_supported && isServicePasskeysFFEnabled && isWebPasskeysFFEnabled + is_passkeys_supported && isServicePasskeysFFEnabled && isWebPasskeysFFEnabled && isMobile ); } - }, [isServicePasskeysFFEnabled, isGBLoaded, isWebPasskeysFFEnabled, is_passkeys_supported]); + }, [isServicePasskeysFFEnabled, isGBLoaded, isWebPasskeysFFEnabled, is_passkeys_supported, isMobile, store.client]); React.useEffect(() => { initDatadog(tracking_datadog); diff --git a/packages/core/src/App/Components/Layout/Header/Components/ToggleMenu/mobile-language-menu.tsx b/packages/core/src/App/Components/Layout/Header/Components/ToggleMenu/mobile-language-menu.tsx index 6fee83e1b48f..15d220cebb72 100644 --- a/packages/core/src/App/Components/Layout/Header/Components/ToggleMenu/mobile-language-menu.tsx +++ b/packages/core/src/App/Components/Layout/Header/Components/ToggleMenu/mobile-language-menu.tsx @@ -20,7 +20,7 @@ const MobileLanguageMenu = observer(({ expandSubMenu, toggleDrawer }: TMobileLan { expandSubMenu(is_expanded); setMobileLanguageMenuOpen(false); diff --git a/packages/core/src/App/Components/Layout/Header/__tests__/menu-link.spec.tsx b/packages/core/src/App/Components/Layout/Header/__tests__/menu-link.spec.tsx index 949d759a7a0e..756b66c4ac95 100644 --- a/packages/core/src/App/Components/Layout/Header/__tests__/menu-link.spec.tsx +++ b/packages/core/src/App/Components/Layout/Header/__tests__/menu-link.spec.tsx @@ -4,8 +4,9 @@ import { createBrowserHistory } from 'history'; import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { useIsRealAccountNeededForCashier } from '@deriv/hooks'; -import { getStaticUrl, isMobile, routes } from '@deriv/shared'; +import { getStaticUrl, routes } from '@deriv/shared'; import { mockStore, StoreProvider } from '@deriv/stores'; +import { useDevice } from '@deriv-com/ui'; import MenuLink from 'App/Components/Layout/Header/menu-link'; jest.mock('@deriv/components', () => ({ @@ -20,7 +21,6 @@ jest.mock('@deriv/hooks', () => ({ jest.mock('@deriv/shared', () => ({ ...jest.requireActual('@deriv/shared'), - isMobile: jest.fn(() => false), getStaticUrl: jest.fn(() => 'MockUrl'), })); @@ -104,7 +104,7 @@ describe('MenuLink', () => { }); it('should render menu link for mobile and two icons with passed suffix_icon', () => { - (isMobile as jest.Mock).mockReturnValue(true); + (useDevice as jest.Mock).mockReturnValue({ isDesktop: false }); mock_props.link_to = '/account/languages'; mock_props.suffix_icon = 'suffix_icon'; diff --git a/packages/core/src/App/Components/Layout/Header/menu-link.tsx b/packages/core/src/App/Components/Layout/Header/menu-link.tsx index 4aa7f32b9dde..af6f2101ea19 100644 --- a/packages/core/src/App/Components/Layout/Header/menu-link.tsx +++ b/packages/core/src/App/Components/Layout/Header/menu-link.tsx @@ -2,11 +2,12 @@ import React from 'react'; import classNames from 'classnames'; import { Icon, Text } from '@deriv/components'; import { useIsRealAccountNeededForCashier } from '@deriv/hooks'; -import { isMobile, routes, getStaticUrl } from '@deriv/shared'; +import { routes, getStaticUrl } from '@deriv/shared'; import { isExternalLink } from '@deriv/utils'; import { observer, useStore } from '@deriv/stores'; import { localize } from '@deriv/translations'; import { BinaryLink } from 'App/Components/Routes'; +import { useDevice } from '@deriv-com/ui'; type TMenuLink = { data_testid: string; @@ -33,13 +34,14 @@ const MenuLink = observer( text, }: Partial) => { const { ui, client } = useStore(); + const { isDesktop } = useDevice(); const { has_any_real_account, is_virtual } = client; const { setMobileLanguageMenuOpen, toggleReadyToDepositModal, toggleNeedRealAccountForCashierModal } = ui; const real_account_needed_for_cashier = useIsRealAccountNeededForCashier(); const is_trade_text = text === localize('Trade'); const deriv_static_url = getStaticUrl(link_to); const traders_hub_path = window.location.pathname === routes.traders_hub; - const is_languages_link_on_mobile = isMobile() && link_to === routes.languages; + const is_languages_link_on_responsive = !isDesktop && link_to === routes.languages; const is_external_link = deriv_static_url && isExternalLink(link_to); const is_cashier_link = [ routes.cashier_deposit, @@ -49,7 +51,7 @@ const MenuLink = observer( if (is_hidden) return null; - if (is_languages_link_on_mobile) { + if (is_languages_link_on_responsive) { return (
moduleLoader(() => - import( - /* webpackChunkName: "trading-assessment-existing-user-modal" */ './trading-assessment-existing-user.jsx' - ) + import(/* webpackChunkName: "trading-assessment-existing-user-modal" */ './trading-assessment-existing-user') ) ); diff --git a/packages/core/src/App/Containers/Modals/trading-assessment-existing-user/index.js b/packages/core/src/App/Containers/Modals/trading-assessment-existing-user/index.js new file mode 100644 index 000000000000..9c842b78610a --- /dev/null +++ b/packages/core/src/App/Containers/Modals/trading-assessment-existing-user/index.js @@ -0,0 +1,3 @@ +import TradingAssessmentExistingUser from './trading-assessment-existing-user'; + +export default TradingAssessmentExistingUser; diff --git a/packages/core/src/App/Containers/Modals/trading-assessment-existing-user.jsx b/packages/core/src/App/Containers/Modals/trading-assessment-existing-user/trading-assessment-existing-user.jsx similarity index 94% rename from packages/core/src/App/Containers/Modals/trading-assessment-existing-user.jsx rename to packages/core/src/App/Containers/Modals/trading-assessment-existing-user/trading-assessment-existing-user.jsx index 14bc7e3be1ad..004a3e1dd2bb 100644 --- a/packages/core/src/App/Containers/Modals/trading-assessment-existing-user.jsx +++ b/packages/core/src/App/Containers/Modals/trading-assessment-existing-user/trading-assessment-existing-user.jsx @@ -1,16 +1,18 @@ import React from 'react'; -import { Modal, DesktopWrapper, MobileDialog, MobileWrapper } from '@deriv/components'; +import { Modal, MobileDialog } from '@deriv/components'; import { Localize, localize } from '@deriv/translations'; import TradingAssessmentForm from '@deriv/account/src/Components/trading-assessment/trading-assessment-form'; import tradingAssessmentConfig from '@deriv/account/src/Configs/trading-assessment-config'; import RiskToleranceWarningModal from '@deriv/account/src/Components/trading-assessment/risk-tolerance-warning-modal'; -import TradingExperienceModal from './trading-experience-modal.jsx'; +import TradingExperienceModal from '../trading-experience-modal'; +import './trading-assessment-existing-user.scss'; import { observer, useStore } from '@deriv/stores'; -import 'Sass/details-form.scss'; +import { useDevice } from '@deriv-com/ui'; const TradingAssessmentExistingUser = observer(() => { // Get the Trading assessment questions and initial_value const { client, ui } = useStore(); + const { isDesktop } = useDevice(); const { setFinancialAndTradingAssessment, updateAccountStatus, @@ -97,7 +99,7 @@ const TradingAssessmentExistingUser = observer(() => { } else if (should_show_trade_assessment_form) { return ( - + {isDesktop ? ( { should_move_to_next={should_move_to_next} /> - - + ) : ( { setSubSectionIndex={setSubSectionIndex} class_name='trading-assessment--existing-user' should_move_to_next={should_move_to_next} + is_responsive={!isDesktop} /> - + )} ); } diff --git a/packages/core/src/App/Containers/Modals/trading-assessment-existing-user/trading-assessment-existing-user.scss b/packages/core/src/App/Containers/Modals/trading-assessment-existing-user/trading-assessment-existing-user.scss new file mode 100644 index 000000000000..b22ee3d24261 --- /dev/null +++ b/packages/core/src/App/Containers/Modals/trading-assessment-existing-user/trading-assessment-existing-user.scss @@ -0,0 +1,210 @@ +.dc-modal__container { + &_real-account-signup-modal { + display: flex; + flex-direction: column; + transition: all 0.3s ease-in-out; + @include tablet-screen { + max-height: calc(100vh - 10.2rem) !important; // Header and footer + } + background-color: var(--general-main-1); + + .dc-modal-header__title { + text-transform: none; + border-top-left-radius: 1rem; + } + + & .dc-themed-scrollbars { + height: 100%; + } + } + &_center-risk-modal { + .dc-modal { + &-header { + border-bottom: 1px solid var(--general-section-1); + } + &-body { + text-align: center; + padding: 2.4rem 2.4rem 0rem; + @include mobile-or-tablet-screen { + padding: 1.6rem 1.6rem 0rem; + } + .risk-acceptance__text { + margin-top: 2.4rem; + } + .verified-account__text { + margin-top: 2.4rem; + } + } + &-footer { + justify-content: center; + } + } + } +} + +.dc-modal-header--real-account-signup-modal { + border-bottom: 1px solid var(--general-section-1); +} + +.dc-mobile-dialog--enter-done .dc-mobile-dialog__content { + transform: none; +} + +.trading-assessment { + display: flex; + flex-direction: column; + + .dc-radio-group { + flex-direction: column; + align-items: flex-start; + } + + @include mobile-or-tablet-screen { + height: calc(100vh - 16rem); + overflow: auto; + } + + &--existing-user { + @include desktop-screen { + margin-top: 9.2rem; + } + + @include mobile-or-tablet-screen { + height: calc(100vh - 12rem); + .trading-assessment__side-note { + padding: 2.2rem 1.6rem; + } + } + } + + &__wrapper__dropdown--list--display { + height: 4rem; + } + + &__side-note { + text-align: justify; + padding: 0 10rem; + + @include mobile-or-tablet-screen { + padding: 0 1.6rem; + } + } + + &__question-counter { + margin: 2.4rem 0 0; + padding-inline-start: 12rem; + + @include mobile-or-tablet-screen { + padding-inline-start: 1.6rem; + } + } + + &__form { + margin-top: 1.6rem; + display: grid; + grid-template-rows: 4.7fr 1fr; + + &--existing_user { + grid-template-rows: 5.8fr 1fr; + } + + &--layout { + grid-template-rows: 35rem 1fr !important; + } + + &--fields { + display: flex; + padding: 0 10rem; + + @include mobile-or-tablet-screen { + padding: 0 1.6rem; + } + } + + .dc-themed-scrollbars { + width: 100%; + } + + .dc-dropdown__display .dc-dropdown__display-placeholder-text-limit-fit { + max-width: initial; + padding-bottom: 0.5rem; + @include mobile-or-tablet-screen { + width: 90%; + white-space: normal; + } + } + } + + &__wrapper__question { + .dc-field--error { + padding-inline-start: 0; + margin: 1.6rem 0; + } + + @include desktop-screen { + padding: 0 2rem; + } + .dc-radio-group { + gap: 1.6rem; + } + @include mobile-or-tablet-screen { + .dc-radio-group__circle { + align-self: flex-start !important; + } + } + } + + &__wrapper__dropdown { + gap: 2.4rem; + display: flex; + flex-direction: column; + width: 100%; + @include desktop-screen { + padding: 0 3rem; + } + } + + .disable-pointer { + cursor: not-allowed; + } + + @include mobile-or-tablet-screen { + .dc-dropdown__display-placeholder { + width: 100%; + .trading-assessment__form .dc-dropdown__display .dc-dropdown__display-placeholder-text-limit-fit { + width: 90%; + } + } + + .dc-dropdown__display-placeholder--is-left-text.dc-dropdown__display-placeholder--is-title { + white-space: normal !important; + line-height: 1.6rem; + } + } + + &__existing_btn { + border-top: 2px solid var(--general-disabled); + display: flex; + justify-content: end; + padding: 1rem 2rem; + position: fixed; + bottom: 0; + width: 100%; + } + + &__btn-group { + @include mobile-or-tablet-screen { + position: fixed; + bottom: 0; + padding: 1.6rem; + border-top: 2px solid var(--general-disabled); + width: 100%; + display: flex; + background: var(--general-main-1); + + &--btn { + width: 100%; + } + } + } +} diff --git a/packages/core/src/sass/account-wizard.scss b/packages/core/src/sass/account-wizard.scss index d8a02dc16a49..17f7df531980 100644 --- a/packages/core/src/sass/account-wizard.scss +++ b/packages/core/src/sass/account-wizard.scss @@ -566,7 +566,7 @@ align-items: flex-start; } - @include mobile() { + @include mobile-or-tablet-screen { height: calc(100vh - 16rem); overflow: auto; } @@ -576,7 +576,7 @@ margin-top: 9.2rem; } - @include mobile() { + @include mobile-or-tablet-screen { height: calc(100vh - 12rem); .trading-assessment__side-note { padding: 2.2rem 1.6rem; @@ -592,7 +592,7 @@ text-align: justify; padding: 0 10rem; - @include mobile() { + @include mobile-or-tablet-screen { padding: 0 1.6rem; } } @@ -623,7 +623,7 @@ display: flex; padding: 0 10rem; - @include mobile() { + @include mobile-or-tablet-screen { padding: 0 1.6rem; } } @@ -635,7 +635,7 @@ .dc-dropdown__display .dc-dropdown__display-placeholder-text-limit-fit { max-width: initial; padding-bottom: 0.5rem; - @include mobile() { + @include mobile-or-tablet-screen { width: 90%; white-space: normal; } @@ -654,7 +654,7 @@ .dc-radio-group { gap: 1.6rem; } - @include mobile() { + @include mobile-or-tablet-screen { .dc-radio-group__circle { align-self: flex-start !important; } @@ -675,7 +675,7 @@ cursor: not-allowed; } - @include mobile() { + @include mobile-or-tablet-screen { .dc-dropdown__display-placeholder { width: 100%; .trading-assessment__form .dc-dropdown__display .dc-dropdown__display-placeholder-text-limit-fit { @@ -700,7 +700,7 @@ } &__btn-group { - @include mobile() { + @include mobile-or-tablet-screen { position: fixed; bottom: 0; padding: 1.6rem; diff --git a/packages/core/src/sass/app/_common/components/account-common.scss b/packages/core/src/sass/app/_common/components/account-common.scss index c7f6152710a1..15b65af14a6a 100644 --- a/packages/core/src/sass/app/_common/components/account-common.scss +++ b/packages/core/src/sass/app/_common/components/account-common.scss @@ -13,7 +13,7 @@ min-width: 32.8rem; min-height: 50rem; margin: auto; - @include mobile { + @include mobile-or-tablet-screen { height: 100%; } } @@ -117,7 +117,13 @@ } } } - + &__financial-assessment { + @include mobile-or-tablet-screen { + .dc-select-native { + margin-bottom: 0; + } + } + } &__poi-inline-message { margin-bottom: 1.6rem; } @@ -162,6 +168,7 @@ @include mobile-or-tablet-screen { padding-inline: 0; + height: 100%; } &--exit { @@ -286,11 +293,23 @@ } } + &__trading-assessment { + .dc-form-submit-button { + @include mobile-or-tablet-screen { + justify-content: center; + .dc-btn { + max-width: 56.8rem; + width: 100%; + } + } + } + } + &__footer { height: 8rem; position: absolute; bottom: 0; - left: 0; + inset-inline-start: 0; display: flex; width: 100%; padding: 1.6rem 2.4rem; @@ -301,15 +320,31 @@ border-top: 1px solid var(--general-section-1); background-color: var(--general-main-1); + @include desktop-screen { + max-width: 100%; + } + + @include mobile-or-tablet-screen { + flex-direction: row; + justify-content: center; + width: 100%; + inset-inline-start: 0; + align-items: center; + } + .back-btn { - margin-right: 8px; + margin-inline-end: 0.8rem; - @include mobile-or-tablet-screen { + @include tablet-screen { + width: 56.8rem; + } + + @include mobile-screen { width: 100%; } .back-btn-icon { - margin-right: 0.8rem; + margin-inline-end: 0.8rem; } span { @@ -341,7 +376,6 @@ &-btn { height: 4rem; - &-wrapper { align-items: normal; display: flex; @@ -371,11 +405,20 @@ } } - @include mobile-or-tablet-screen { + @include tablet-screen { + width: 100%; + } + + @include mobile-screen { &--has-bottom-margin { margin-bottom: 1.6rem; } } + + @include tablet-screen { + width: 56.8rem; + margin: auto; + } } &--dashboard { @@ -411,16 +454,21 @@ } @include mobile-or-tablet-screen { + position: fixed; flex-direction: column; height: auto; align-items: initial; border-top: 2px solid var(--general-section-1); + width: 100vw; + } + + @include tablet-screen { + padding: 1.6rem 0; } } } &__scrollbars_container { height: 100%; - padding-top: 2.4rem; padding-bottom: 6.4rem; &-wrapper { @@ -454,11 +502,15 @@ } @include desktop-screen { - padding-left: 16px; - padding-right: 16px; + padding-inline-start: 16px; + padding-inline-end: 16px; + } + @include tablet-screen { + padding-inline-start: 0; + padding-inline-end: 0; } - @include mobile-or-tablet-screen { + @include mobile-screen { height: unset; padding-top: unset; padding-bottom: unset; @@ -674,6 +726,10 @@ height: 100%; &__main-container { + @include mobile-or-tablet-screen { + max-width: 100%; + overflow: hidden; + } position: relative; max-width: 68.2rem; height: 100%; @@ -698,9 +754,8 @@ padding-bottom: 1.6rem; @include mobile-or-tablet-screen { - min-height: unset; overflow-y: scroll; - padding: 0 1.6rem; + padding: 2.4rem; &--status { height: 100%; @@ -719,9 +774,7 @@ .proof-of-identity__submit-button { @include mobile-or-tablet-screen { - margin: unset; width: 100%; - margin-inline: 1.6rem; } } @@ -787,6 +840,7 @@ .proof-of-identity__dropdown-container { margin-top: 0; + overflow: visible; } } } @@ -837,16 +891,22 @@ } &__footer { + display: flex; + align-items: center; + justify-content: flex-end; + bottom: 0; + @include mobile-or-tablet-screen { - display: flex; flex-direction: row; - align-items: center; - justify-content: flex-end; - position: fixed; - bottom: 0; + width: 100%; + justify-content: center; + } - .proof-of-identity__submit-button { - width: 100%; + .proof-of-identity__submit-button { + @include mobile-or-tablet-screen { + width: 55.2rem; + align-items: center; + justify-content: center; } } } @@ -864,7 +924,7 @@ } .country-dropdown { - min-height: 35.2rem; + height: 100%; } } @@ -904,7 +964,7 @@ &__image-container { width: fit-content; height: fit-content; - padding: 8px; + padding: 0.8rem; border-radius: 4px; background-color: $color-grey-2; } diff --git a/packages/core/src/sass/app/_common/components/account-switcher.scss b/packages/core/src/sass/app/_common/components/account-switcher.scss index f9f24e64d5d2..8c9898641345 100644 --- a/packages/core/src/sass/app/_common/components/account-switcher.scss +++ b/packages/core/src/sass/app/_common/components/account-switcher.scss @@ -266,7 +266,7 @@ margin: 0.2rem 0.8rem 0.8rem; height: 4rem; } - @include mobile-screen { + @include mobile-or-tablet-screen { position: relative; top: unset; left: unset; @@ -572,7 +572,6 @@ .dc-modal__container_accounts-switcher { @include tablet-screen { - width: unset !important; - right: 0; + inset-inline-start: 1.6rem; } } diff --git a/packages/core/src/sass/app/_common/components/settings-language.scss b/packages/core/src/sass/app/_common/components/settings-language.scss index d48a1e07d1c5..dc780e4934f5 100644 --- a/packages/core/src/sass/app/_common/components/settings-language.scss +++ b/packages/core/src/sass/app/_common/components/settings-language.scss @@ -3,7 +3,7 @@ margin-left: 1.6rem; width: fit-content; - @include mobile { + @include mobile-or-tablet-screen { display: flex; flex-direction: column; padding: 1.6rem 2.2rem 8rem; @@ -17,14 +17,14 @@ grid-gap: 0.8rem; margin: 1.6rem 0; - @include mobile { + @include mobile-or-tablet-screen { grid-template-columns: repeat(2, minmax(40%, 1fr)); grid-template-rows: auto; grid-gap: initial; margin: 0 auto; padding: 0 0.8rem; - @include mobile { + @include mobile-or-tablet-screen { &--disabled { opacity: 0.5; pointer-events: none; @@ -49,7 +49,7 @@ width: 13.6rem; height: 8.8rem; - @include mobile { + @include mobile-or-tablet-screen { padding: 8px; &--pre-appstore { @@ -76,7 +76,7 @@ width: 3.6rem; height: 2.8rem; - @include mobile { + @include mobile-or-tablet-screen { margin-top: 1rem; } } @@ -90,7 +90,7 @@ color: var(--text-prominent); } - @include mobile { + @include mobile-or-tablet-screen { font-size: 1.4rem; } } diff --git a/packages/core/src/sass/app/_common/layout/header.scss b/packages/core/src/sass/app/_common/layout/header.scss index 936c0b344a44..3fc350a25458 100644 --- a/packages/core/src/sass/app/_common/layout/header.scss +++ b/packages/core/src/sass/app/_common/layout/header.scss @@ -372,7 +372,7 @@ margin-right: 0.8rem; vertical-align: middle; } - @include mobile { + @include mobile-or-tablet-screen { height: $MOBILE_HEADER_HEIGHT; .header__menu-left, diff --git a/packages/core/src/sass/details-form.scss b/packages/core/src/sass/details-form.scss index 81c42e7b05fa..0d344aa71623 100644 --- a/packages/core/src/sass/details-form.scss +++ b/packages/core/src/sass/details-form.scss @@ -26,6 +26,10 @@ @include mobile-or-tablet-screen { padding: 0 1.6rem; } + + @include tablet-screen { + display: inline; + } } &__sub-header { diff --git a/packages/shared/src/utils/routes/routes.ts b/packages/shared/src/utils/routes/routes.ts index 70d1c298234d..f5e501e057bd 100644 --- a/packages/shared/src/utils/routes/routes.ts +++ b/packages/shared/src/utils/routes/routes.ts @@ -107,6 +107,8 @@ export const DISABLE_LANDSCAPE_BLOCKER_ROUTES = [ routes.onboarding, routes.compare_cfds, routes.reports, + routes.account, + routes.endpoint, /** because contract route has dynamic id */ '/contract', ];