Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

feat: optimize connect modal #591

Merged
merged 18 commits into from
Mar 14, 2024
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/little-cougars-smile.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@ant-design/web3-common': minor
'@ant-design/web3': minor
---

feat: optimize connect-modal component
1 change: 1 addition & 0 deletions packages/common/src/locale/en_US.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const localeValues: RequiredLocale = {
walletCardAppTitle: '{selectedWalletName} for Mobile',
walletCardAppDesc: 'Use the mobile wallet to explore the world of Ethereum.',
walletCardExtensionTitle: '{selectedWalletName} for {selectedExtensionBrowserName}',
walletPanelPlugin: 'PLUGIN',
},
NFTCard: {
actionText: 'Buy Now',
Expand Down
1 change: 1 addition & 0 deletions packages/common/src/locale/zh_CN.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ const localeValues: RequiredLocale = {
walletCardAppTitle: '在手机使用 {selectedWalletName}',
walletCardAppDesc: '使用移动钱包探索以太坊世界。',
walletCardExtensionTitle: '在 {selectedExtensionBrowserName} 浏览器中使用 {selectedWalletName}',
walletPanelPlugin: '插件',
},
NFTCard: {
actionText: '立即购买',
Expand Down
1 change: 1 addition & 0 deletions packages/common/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ export interface RequiredLocale {
walletCardAppTitle: string;
walletCardAppDesc: string;
walletCardExtensionTitle: string;
walletPanelPlugin: string;
};
NFTCard: {
actionText: string;
Expand Down
1,370 changes: 930 additions & 440 deletions packages/web3/src/connect-modal/__tests__/__snapshots__/basic.test.tsx.snap

Large diffs are not rendered by default.

Large diffs are not rendered by default.

138 changes: 138 additions & 0 deletions packages/web3/src/connect-modal/__tests__/pluginTag.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
import { ConnectModal } from '@ant-design/web3';
import { metadata_MetaMask } from '@ant-design/web3-assets';
import { Wallet } from '@ant-design/web3-common';
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
import { describe, expect, it } from 'vitest';

describe('ConnectModal with qcCode & plugin tag', () => {
it('show qcCode', async () => {
const wallet: Wallet = {
...metadata_MetaMask,
getQrCode: async () => {
return {
uri: '',
};
},
};

const App = () => (
<ConnectModal
open
title="ConnectModal"
footer="Powered by AntChain"
mode="normal"
walletList={[wallet]}
/>
);
const { baseElement } = render(<App />);
expect(baseElement.querySelector('.ant-web3-connect-modal-qc-icon')).toBeTruthy();
});

it('don not show qcCode', async () => {
const wallet: Wallet = {
...metadata_MetaMask,
};

const App = () => (
<ConnectModal
open
title="ConnectModal"
footer="Powered by AntChain"
mode="normal"
walletList={[wallet]}
/>
);
const { baseElement } = render(<App />);
expect(baseElement.querySelector('.ant-web3-connect-modal-qc-icon')).not.toBeTruthy();
});

it('not show plugin tag', async () => {
const wallet: Wallet = {
...metadata_MetaMask,
};

const App = () => (
<ConnectModal
open
title="ConnectModal"
footer="Powered by AntChain"
mode="normal"
walletList={[wallet]}
/>
);
render(<App />);
const span = screen.queryByText('PLUGIN');
expect(!!span?.parentElement === false).toBeTruthy();
});

it('show plugin tag when installed', async () => {
const wallet: Wallet = {
...metadata_MetaMask,
hasExtensionInstalled: async () => {
return true;
},
};

const App = () => (
<ConnectModal
open
title="ConnectModal"
footer="Powered by AntChain"
mode="normal"
walletList={[wallet]}
/>
);
render(<App />);
const span = screen.queryByText('PLUGIN');
expect(!!span?.parentElement?.getAttribute('disabled') === false).toBeTruthy();
});

it('show plugin tag when not installed', async () => {
const wallet: Wallet = {
...metadata_MetaMask,
hasExtensionInstalled: async () => {
return false;
},
};

const App = () => (
<ConnectModal
open
title="ConnectModal"
footer="Powered by AntChain"
mode="normal"
walletList={[wallet]}
/>
);
render(<App />);
const span = screen.queryByText('PLUGIN');
expect(span?.parentElement?.getAttribute('disabled') === '').toBeTruthy();
});

it('click event trigger', async () => {
const wallet: Wallet = {
...metadata_MetaMask,
getQrCode: async () => {
return {
uri: '',
};
},
};

const App = () => (
<ConnectModal
open
title="ConnectModal"
footer="Powered by AntChain"
mode="normal"
walletList={[wallet]}
/>
);
const { baseElement } = render(<App />);
const icon = baseElement.querySelector('.ant-web3-connect-modal-qc-icon');
fireEvent.click(icon!);
await waitFor(() => {
expect(baseElement.querySelector('.ant-web3-connect-modal-qr-code')).toBeTruthy();
});
});
});
32 changes: 32 additions & 0 deletions packages/web3/src/connect-modal/components/PluginTag.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import React from 'react';
import { Badge, Button } from 'antd';

import { connectModalContext } from '../context';
import type { Wallet } from '../interface';

const PluginTag: React.FC<{ wallet: Wallet }> = ({ wallet }) => {
const [extensionInstalled, setExtensionInstalled] = React.useState<boolean>(false);
const { getMessage, localeMessage } = React.useContext(connectModalContext);

const judgeExtensionInstalled = async () => {
const hasWalletReady = await wallet.hasWalletReady?.();
if (hasWalletReady) {
const hasInstalled = await wallet.hasExtensionInstalled?.();
setExtensionInstalled(!!hasInstalled);
}
};

React.useEffect(() => {
judgeExtensionInstalled();
}, [wallet]);

return wallet.hasExtensionInstalled ? (
<Badge dot={extensionInstalled} color="#52c41a">
<Button size="small" disabled={!extensionInstalled}>
{getMessage(localeMessage.walletPanelPlugin)}
</Button>
</Badge>
) : null;
LCJove marked this conversation as resolved.
Show resolved Hide resolved
};

export default PluginTag;
41 changes: 31 additions & 10 deletions packages/web3/src/connect-modal/components/WalletList.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import React, { useContext, useMemo } from 'react';
import { List } from 'antd';
import { QrcodeOutlined } from '@ant-design/icons';
import { Col, List, Row } from 'antd';
import classNames from 'classnames';

import { connectModalContext } from '../context';
import type { ConnectModalProps, Wallet } from '../interface';
import { defaultGroupOrder } from '../utils';
import PluginTag from './PluginTag';

export type WalletListProps = Pick<ConnectModalProps, 'walletList' | 'group' | 'groupOrder'>;

Expand Down Expand Up @@ -67,16 +69,35 @@ const WalletList: React.FC<WalletListProps> = (props) => {
updatePanelRoute('wallet', true);
}}
>
<div className={`${prefixCls}-content`}>
<div className={`${prefixCls}-icon`}>
{typeof item.icon === 'string' || item.icon === undefined ? (
<img src={item.icon} alt={item.name} />
) : (
item.icon
<Row align="middle" justify="center" className={`${prefixCls}-row`}>
LCJove marked this conversation as resolved.
Show resolved Hide resolved
<Col span={16}>
<div className={`${prefixCls}-content`}>
<div className={`${prefixCls}-icon`}>
{typeof item.icon === 'string' || item.icon === undefined ? (
<img src={item.icon} alt={item.name} />
) : (
item.icon
)}
</div>
<div className={`${prefixCls}-name`}>{item.name}</div>
</div>
</Col>
<Col span={6}>
<PluginTag wallet={item} />
</Col>
<Col span={2} className={`${prefixCls}-qc-icon-col`}>
{item.getQrCode && (
<QrcodeOutlined
className={`${prefixCls}-qc-icon`}
onClick={(e) => {
e.stopPropagation();
updateSelectedWallet(item, false);
updatePanelRoute('qrCode', true);
}}
/>
)}
</div>
<div className={`${prefixCls}-name`}>{item.name}</div>
</div>
</Col>
</Row>
</List.Item>
)}
/>
Expand Down
2 changes: 1 addition & 1 deletion packages/web3/src/connect-modal/demos/panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ const App: React.FC = () => {
return (
<Card
style={{
maxWidth: 737,
maxWidth: 797,
}}
bodyStyle={{
padding: 0,
Expand Down
2 changes: 1 addition & 1 deletion packages/web3/src/connect-modal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export const ConnectModal: React.FC<ConnectModalProps> & {
return wrapSSR(
<Modal
footer={null}
width={isSimple ? 380 : 737}
width={isSimple ? 380 : 797}
LCJove marked this conversation as resolved.
Show resolved Hide resolved
{...restProps}
className={classNames(prefixCls, className, hashId)}
rootClassName={classNames(`${prefixCls}-root`, rootClassName)}
Expand Down
27 changes: 22 additions & 5 deletions packages/web3/src/connect-modal/style/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ const getThemeStyle = (token: ConnectModalToken): CSSInterpolation => {
[`${componentCls}-list-panel`]: {
paddingInline: 18,
paddingBlock: 24,
width: 268,
width: 328,
flexShrink: 0,
borderRight: `1px solid ${token.splitColor}`,
display: 'flex',
Expand All @@ -100,6 +100,12 @@ const getThemeStyle = (token: ConnectModalToken): CSSInterpolation => {
marginBlock: token.marginSM,
overflow: 'auto',
[`${componentCls}-wallet-list`]: {
maxHeight: 390,
overflow: 'scroll',
'&::-webkit-scrollbar': {
display: 'none',
},
scrollbarWidth: 'none',
[`${componentCls}-group`]: {
marginBlockEnd: token.marginSM,
[`${componentCls}-group-title`]: {
Expand All @@ -120,6 +126,19 @@ const getThemeStyle = (token: ConnectModalToken): CSSInterpolation => {
fontSize: token.fontSizeSM,
color: token.colorTextDescription,
},
[`${componentCls}-row`]: {
width: '100%',
fontSize: token.fontSizeLG,
[`${componentCls}-qc-icon-col`]: {
fontSize: 16,
textAlign: 'right',
[`${componentCls}-qc-icon`]: {
'&:hover': {
color: token.colorPrimary,
},
},
},
},
[`${componentCls}-content`]: {
display: 'flex',
alignItems: 'center',
Expand All @@ -140,6 +159,7 @@ const getThemeStyle = (token: ConnectModalToken): CSSInterpolation => {
justifySelf: 'flex-start',
marginInlineStart: token.marginSM,
color: token.colorText,
wordBreak: 'break-word',
},
},
'&:last-child': {
Expand All @@ -149,10 +169,7 @@ const getThemeStyle = (token: ConnectModalToken): CSSInterpolation => {
background: token.hoverBg,
},
'&.selected': {
background: token.selectedBg,
[`${componentCls}-name`]: {
color: token.selectedColor,
},
background: 'rgba(0,0,0,0.03)',
LCJove marked this conversation as resolved.
Show resolved Hide resolved
},
},
},
Expand Down
Loading