Skip to content

Commit

Permalink
[wallets] WALL-2240: Feature/wall AppLinked card (binary-com#11078)
Browse files Browse the repository at this point in the history
* feat: wall-2240: applinkedwith wallet component draft

* feat: wall-2240: updated icons to avoid duplication

* feat: added tests to component

* feat: types, extra unit case, rename

* feat: fixed eslint

* feat: fixed eslint #2

* feat: eslint fix
  • Loading branch information
wojciech-deriv committed Nov 2, 2023
1 parent 898e50d commit e6f5568
Show file tree
Hide file tree
Showing 24 changed files with 348 additions and 1 deletion.
4 changes: 4 additions & 0 deletions packages/wallets/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,8 @@ const baseConfigForPackages = require('../../jest.config.base');

module.exports = {
...baseConfigForPackages,
moduleNameMapper: {
'\\.s(c|a)ss$': '<rootDir>/../../__mocks__/styleMock.js',
'^.+\\.svg$': '<rootDir>/../../__mocks__/fileMock.js',
},
};
1 change: 1 addition & 0 deletions packages/wallets/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"@types/react-dom": "^18.0.0",
"@typescript-eslint/eslint-plugin": "5.45.0",
"@typescript-eslint/parser": "5.45.0",
"@testing-library/react": "^12.0.0",
"eslint-plugin-local-rules": "2.0.0",
"eslint-plugin-react": "^7.22.0",
"eslint-plugin-react-hooks": "^4.2.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const WalletGradientBackground: React.FC<TProps> = ({
};

return (
<div className={`wallets-gradient ${bodyClassName} ${getClassName()}`}>
<div className={`wallets-gradient ${bodyClassName} ${getClassName()}`} data-testid='wallet-gradient-background'>
{hasShine && !isDemo && <span className='wallets-gradient__shine' />}
<div className='wallets-gradient__content'>{children}</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.wallets-responsive-svg {
border-radius: $BORDER_RADIUS;
overflow: hidden;

svg {
width: 100%;
height: 100%;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import React, { ComponentType, SVGAttributes } from 'react';
import './WalletResponsiveSvg.scss';

import IcWalletOptionsLight from '../../public/images/wallet/ic-wallet-options-light.svg';
import IcWalletOptionsDark from '../../public/images/wallet/ic-wallet-options-dark.svg';
import IcWalletDerivP2PLight from '../../public/images/wallet/ic-wallet-deriv-p2p-light.svg';
import IcWalletDerivP2PDark from '../../public/images/wallet/ic-wallet-deriv-p2p-dark.svg';

import IcWalletDerivDemoLight from '../../public/images/wallet/ic-wallet-deriv-demo-light.svg';
import IcWalletDerivDemoDark from '../../public/images/wallet/ic-wallet-deriv-demo-dark.svg';

import IcWalletCurrencyUsd from '../../public/images/currencies/usd.svg';
import IcWalletCurrencyEur from '../../public/images/currencies/eur.svg';
import IcWalletCurrencyAud from '../../public/images/currencies/aud.svg';
import IcWalletCurrencyGbp from '../../public/images/currencies/gbp.svg';

import IcWalletBitcoinLight from '../../public/images/currencies/btc.svg';
import IcWalletBitcoinDark from '../../public/images/currencies/btc-dark.svg';
import IcWalletEthereumLight from '../../public/images/currencies/eth.svg';
import IcWalletEthereumDark from '../../public/images/currencies/eth-dark.svg';
import IcWalletLiteCoinLight from '../../public/images/currencies/ltc.svg';
import IcWalletLiteCoinDark from '../../public/images/currencies/ltc-dark.svg';
import IcWalletUsdCoinLight from '../../public/images/currencies/usdc.svg';
import IcWalletUsdCoinDark from '../../public/images/currencies/usdc-dark.svg';
import IcWalletTetherLight from '../../public/images/currencies/usdt.svg';
import IcWalletTetherDark from '../../public/images/currencies/usdt-dark.svg';

interface IconTypes {
[key: string]: ComponentType<SVGAttributes<SVGElement>>;
}

const ICONS: IconTypes = {
IcWalletBitcoinDark,
IcWalletBitcoinLight,
IcWalletCurrencyAud,
IcWalletCurrencyEur,
IcWalletCurrencyGbp,
IcWalletCurrencyUsd,
IcWalletDerivDemoDark,
IcWalletDerivDemoLight,
IcWalletDerivP2PDark,
IcWalletDerivP2PLight,
IcWalletEthereumDark,
IcWalletEthereumLight,
IcWalletLiteCoinDark,
IcWalletLiteCoinLight,
IcWalletOptionsDark,
IcWalletOptionsLight,
IcWalletTetherDark,
IcWalletTetherLight,
IcWalletUsdCoinDark,
IcWalletUsdCoinLight,
} as const;

type TWalletIconProps = {
className?: string;
icon: keyof typeof ICONS;
};

const WalletResponsiveSvg = ({ className = '', icon }: TWalletIconProps) => {
const IconSvg: ComponentType<SVGAttributes<SVGElement>> = ICONS[icon];

if (!IconSvg) {
return null;
}

return (
<div className={`wallets-responsive-svg ${className}`} data-testid='dt_wallet_icon'>
<IconSvg preserveAspectRatio='xMidYMid meet' />
</div>
);
};

export default WalletResponsiveSvg;
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import React from 'react';
import { render, screen } from '@testing-library/react';
import WalletResponsiveSvg from '../WalletResponsiveSvg';

describe('<WalletResponsiveSvg/>', () => {
it('render container and svg properly', () => {
render(<WalletResponsiveSvg icon='IcWalletOptionsLight' />);

const divElement = screen.getByTestId('dt_wallet_icon');

// eslint-disable-next-line testing-library/no-node-access
const mockedSvgElement = divElement.querySelector('file-mock-stub');
expect(divElement).toBeInTheDocument();
expect(mockedSvgElement).not.toBeNull();
});

it('renders svg in responsive manner', () => {
render(<WalletResponsiveSvg icon='IcWalletOptionsLight' />);

const divElement = screen.getByTestId('dt_wallet_icon');

// eslint-disable-next-line testing-library/no-node-access
const mockedSvgElement = divElement.querySelector('file-mock-stub');

expect(mockedSvgElement).toHaveAttribute('preserveAspectRatio');
});

it('renders nothing when there is no svg provided', () => {
const { container } = render(<WalletResponsiveSvg icon='' />);

expect(container).toBeEmptyDOMElement();
});
});
3 changes: 3 additions & 0 deletions packages/wallets/src/components/WalletResponsiveSvg/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import WalletResponsiveSvg from './WalletResponsiveSvg';

export { WalletResponsiveSvg };
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
@mixin container-space($parent, $space) {
#{$parent}__app-icon {
top: $space * 1rem;
left: $space * 1rem;
}

#{$parent}__wallet-icon {
bottom: $space * 1rem;
right: $space * 1rem;
}
}

@mixin app-icon-container-size($parent, $width, $height) {
#{$parent}__app-icon {
width: $width;
height: $height;
}
}

@mixin wallet-icon-container-size($parent, $width, $height) {
#{$parent}__wallet-icon {
width: $width;
height: $height;
}
}

@mixin wallet-icon-size($parent, $width, $height) {
.wallets-app-linked-with-wallet-icon__wallet-base-icon {
width: $width;
height: $height;
}
}

.wallets-app-linked-with-wallet-icon {
$parent-selector: &;

position: relative;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;

&__app-icon {
position: absolute;
top: 0;
left: 0;
z-index: 1;
}

&__wallet-icon {
position: absolute;
bottom: 0;
right: 0;
}

&--small {
width: 4rem;
height: 2.4rem;

@include container-space($parent-selector, 0.1);
@include app-icon-container-size($parent-selector, 16px, 16px);
@include wallet-icon-container-size($parent-selector, 2.4rem, 1.4rem);
@include wallet-icon-size($parent-selector, 12px, 12px);
}

&--medium {
width: 6.4rem;
height: 4rem;

@include container-space($parent-selector, 0.2);
@include app-icon-container-size($parent-selector, 24px, 24px);
@include wallet-icon-container-size($parent-selector, 4rem, 2.4rem);
@include wallet-icon-size($parent-selector, 16px, 16px);
}

&--large {
width: 12.8rem;
height: 8rem;

@include container-space($parent-selector, 0.4);
@include app-icon-container-size($parent-selector, 48px, 48px);
@include wallet-icon-container-size($parent-selector, 8.4rem, 5.2rem);
@include wallet-icon-size($parent-selector, 32px, 32px);
}

.wallets-gradient {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
border-radius: $BORDER_RADIUS;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React from 'react';
import { WalletResponsiveSvg } from '../WalletResponsiveSvg';
import './WalletsAppLinkedWithWalletIcon.scss';
import { WalletGradientBackground } from '../WalletGradientBackground';

type TAppIconProps = {
appIcon: string;
currency: string;
size?: 'large' | 'medium' | 'small';
walletIcon: string;
};

const WalletsAppLinkedWithWalletIcon = ({ appIcon, currency, size = 'medium', walletIcon }: TAppIconProps) => {
return (
<div
className={`wallets-app-linked-with-wallet-icon wallets-app-linked-with-wallet-icon--${size}`}
data-testid='wallets-app-linked-with-wallet-icon'
>
{/* App Icon */}
<div className='wallets-app-linked-with-wallet-icon__app-icon'>
<WalletResponsiveSvg icon={appIcon} />
</div>

{/* Wallet Icon */}
<div className='wallets-app-linked-with-wallet-icon__wallet-icon'>
<WalletGradientBackground currency={currency && currency.toUpperCase()}>
<WalletResponsiveSvg
className='wallets-app-linked-with-wallet-icon__wallet-base-icon'
icon={walletIcon}
/>
</WalletGradientBackground>
</div>
</div>
);
};

export default WalletsAppLinkedWithWalletIcon;
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import React from 'react';
import { render, screen } from '@testing-library/react';
import WalletsAppLinkedWithWalletIcon from '../WalletsAppLinkedWithWalletIcon';

describe('<WalletsAppLinkedWithWalletIcon/>', () => {
it('renders', () => {
render(
<WalletsAppLinkedWithWalletIcon
appIcon='IcWalletOptionsLight'
currency='LTC'
size='large'
walletIcon='IcWalletLiteCoinDark'
/>
);

const divElement = screen.getByTestId('wallets-app-linked-with-wallet-icon');

expect(divElement).toBeInTheDocument();
});

it('renders both icons', () => {
render(
<WalletsAppLinkedWithWalletIcon
appIcon='IcWalletOptionsLight'
currency='LTC'
size='large'
walletIcon='IcWalletLiteCoinDark'
/>
);

const divElement = screen.getByTestId('wallets-app-linked-with-wallet-icon');

// eslint-disable-next-line testing-library/no-node-access
const mockAppIconSvgElement = divElement.querySelector(
'.wallets-app-linked-with-wallet-icon__app-icon file-mock-stub'
);
// eslint-disable-next-line testing-library/no-node-access
const mockWalletIconSvgElement = divElement.querySelector(
'.wallets-app-linked-with-wallet-icon__wallet-icon file-mock-stub'
);

expect(mockAppIconSvgElement).not.toBeNull();
expect(mockWalletIconSvgElement).not.toBeNull();
});

it('applies correct size', () => {
render(
<WalletsAppLinkedWithWalletIcon
appIcon='IcWalletOptionsLight'
currency='LTC'
size='large'
walletIcon='IcWalletLiteCoinDark'
/>
);

const divElement = screen.getByTestId('wallets-app-linked-with-wallet-icon');

expect(divElement).toHaveClass('wallets-app-linked-with-wallet-icon--large');
});

it('displays proper gradient inside wallet icon', () => {
render(
<WalletsAppLinkedWithWalletIcon
appIcon='IcWalletOptionsLight'
currency='LTC'
size='large'
walletIcon='IcWalletLiteCoinDark'
/>
);

const gradientElement = screen.getByTestId('wallet-gradient-background');

expect(gradientElement).toBeInTheDocument();
expect(gradientElement).toHaveClass('wallets-gradient--LTC-desktop-card-light');
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import WalletsAppLinkedWithWalletIcon from './WalletsAppLinkedWithWalletIcon';

export { WalletsAppLinkedWithWalletIcon };
1 change: 1 addition & 0 deletions packages/wallets/src/public/images/currencies/btc-dark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions packages/wallets/src/public/images/currencies/eth-dark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit e6f5568

Please sign in to comment.