Skip to content

Commit

Permalink
Merge pull request #335 from aptos-labs/antd-aptos-connect
Browse files Browse the repository at this point in the history
Update Ant Design wallet selector to new design
  • Loading branch information
blakezimmerman authored Jun 24, 2024
2 parents 1580df8 + 9f0d3de commit fbee96d
Show file tree
Hide file tree
Showing 8 changed files with 578 additions and 411 deletions.
5 changes: 5 additions & 0 deletions .changeset/fluffy-plums-clean.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@aptos-labs/wallet-adapter-ant-design": minor
---

Updated wallet selector modal to new design for Aptos Connect.
5 changes: 5 additions & 0 deletions .changeset/wicked-otters-call.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@aptos-labs/wallet-adapter-ant-design": minor
---

Added `sortDefaultWallets` and `sortMoreWallets` props for controlling the order of wallets in the modal.
5 changes: 4 additions & 1 deletion packages/wallet-adapter-ant-design/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,20 +38,23 @@ That would add a `Connect Wallet` button when clicked opens up a `wallet selecto
You can override these classes

```
.wallet-selector-modal
.wallet-selector-icon
.wallet-selector-text
.wallet-menu-wrapper
.wallet-name-wrapper
.wallet-connect-button
.wallet-connect-install
.wallet-button
.wallet-modal-title
aptos-connect-button
```

For example, to override the `connect wallet` button background color, you can use the `.wallet-button` class in your local `.css` file

```
.wallet-button{
background-color:red;
background-color: red;
}
```

Expand Down
2 changes: 1 addition & 1 deletion packages/wallet-adapter-ant-design/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
},
"dependencies": {
"@aptos-labs/wallet-adapter-react": "workspace:*",
"antd": "^5.1.2"
"antd": "^5.18.3"
},
"peerDependencies": {
"react": "^18",
Expand Down
235 changes: 147 additions & 88 deletions packages/wallet-adapter-ant-design/src/WalletSelector.tsx
Original file line number Diff line number Diff line change
@@ -1,36 +1,69 @@
import { Dispatch, SetStateAction, useEffect, useState } from "react";
import { Button, Menu, Modal, Typography } from "antd";
import {
isRedirectable,
useWallet,
Wallet,
WalletReadyState,
WalletName,
AptosStandardSupportedWallet,
AnyAptosWallet,
WalletItem,
getAptosConnectWallets,
isInstallRequired,
partitionWallets,
truncateAddress,
useWallet,
} from "@aptos-labs/wallet-adapter-react";
import { Button, Collapse, Divider, Flex, Modal, Typography } from "antd";
import { Dispatch, SetStateAction, useEffect, useState } from "react";
import "./styles.css";

const { Text } = Typography;

type WalletSelectorProps = {
isModalOpen?: boolean;
setModalOpen?: Dispatch<SetStateAction<boolean>>;
/**
* An optional function for sorting wallets that are currently installed or
* loadable in the wallet selector modal.
*/
sortDefaultWallets?: (a: AnyAptosWallet, b: AnyAptosWallet) => number;
/**
* An optional function for sorting wallets that are NOT currently installed or
* loadable in the wallet selector modal.
*/
sortMoreWallets?: (a: AnyAptosWallet, b: AnyAptosWallet) => number;
};

export function WalletSelector({
isModalOpen,
setModalOpen,
sortDefaultWallets,
sortMoreWallets,
}: WalletSelectorProps) {
const [walletSelectorModalOpen, setWalletSelectorModalOpen] = useState(false);

useEffect(() => {
// If the component is being used as a controlled component,
// sync the external and internal modal state.
if (isModalOpen !== undefined) {
setWalletSelectorModalOpen(isModalOpen);
}
}, [isModalOpen]);

const { connect, disconnect, account, wallets, connected } = useWallet();
const { account, connected, disconnect, wallets = [] } = useWallet();

const {
/** Wallets that use social login to create an account on the blockchain */
aptosConnectWallets,
/** Wallets that use traditional wallet extensions */
otherWallets,
} = getAptosConnectWallets(wallets);

const {
/** Wallets that are currently installed or loadable. */
defaultWallets,
/** Wallets that are NOT currently installed or loadable. */
moreWallets,
} = partitionWallets(otherWallets);

if (sortDefaultWallets) defaultWallets.sort(sortDefaultWallets);
if (sortMoreWallets) moreWallets.sort(sortMoreWallets);

const hasAptosConnectWallets = !!aptosConnectWallets.length;

const onWalletButtonClick = () => {
if (connected) {
Expand All @@ -40,107 +73,133 @@ export function WalletSelector({
}
};

const onWalletSelected = (wallet: WalletName) => {
connect(wallet);
const closeModal = () => {
setWalletSelectorModalOpen(false);
if (setModalOpen) {
setModalOpen(false);
}
};
const onCancel = () => {
setWalletSelectorModalOpen(false);
if (setModalOpen) {
setModalOpen(false);
}
};
const buttonText = account?.ansName
? account?.ansName
: truncateAddress(account?.address);

const buttonText =
account?.ansName || truncateAddress(account?.address) || "Unknown";

return (
<>
<Button className="wallet-button" onClick={() => onWalletButtonClick()}>
<Button className="wallet-button" onClick={onWalletButtonClick}>
{connected ? buttonText : "Connect Wallet"}
</Button>
<Modal
title={<div className="wallet-modal-title">Connect Wallet</div>}
title={
<div className="wallet-modal-title">
{hasAptosConnectWallets ? (
<>
<span>Log in or sign up</span>
<span>with Social + Aptos Connect</span>
</>
) : (
"Connect Wallet"
)}
</div>
}
centered
open={walletSelectorModalOpen}
onCancel={onCancel}
onCancel={closeModal}
footer={[]}
closable={false}
zIndex={9999}
className="wallet-selector-modal"
>
{!connected && (
<Menu>
{wallets?.map((wallet: Wallet | AptosStandardSupportedWallet) => {
return walletView(wallet, onWalletSelected);
})}
</Menu>
<>
{hasAptosConnectWallets && (
<>
<Flex vertical gap={12}>
{aptosConnectWallets.map((wallet) => (
<AptosConnectWalletRow
key={wallet.name}
wallet={wallet}
onConnect={closeModal}
/>
))}
</Flex>
<Divider>Or</Divider>
</>
)}
<Flex vertical gap={12}>
{defaultWallets.map((wallet) => (
<WalletRow
key={wallet.name}
wallet={wallet}
onConnect={closeModal}
/>
))}
</Flex>
{!!moreWallets.length && (
<Collapse
ghost
expandIconPosition="end"
items={[
{
key: "more-wallets",
label: "More Wallets",
children: (
<Flex vertical gap={12}>
{moreWallets.map((wallet) => (
<WalletRow
key={wallet.name}
wallet={wallet}
onConnect={closeModal}
/>
))}
</Flex>
),
},
]}
/>
)}
</>
)}
</Modal>
</>
);
}

const walletView = (
wallet: Wallet | AptosStandardSupportedWallet,
onWalletSelected: (wallet: WalletName) => void
) => {
const isWalletReady =
wallet.readyState === WalletReadyState.Installed ||
wallet.readyState === WalletReadyState.Loadable;

// The user is on a mobile device
if (!isWalletReady && isRedirectable()) {
const mobileSupport = (wallet as Wallet).deeplinkProvider;
// If the user has a deep linked app, show the wallet
if (mobileSupport) {
return (
<Menu.Item
key={wallet.name}
onClick={() => onWalletSelected(wallet.name)}
>
<div className="wallet-menu-wrapper">
<div className="wallet-name-wrapper">
<img src={wallet.icon} width={25} style={{ marginRight: 10 }} />
<Text className="wallet-selector-text">{wallet.name}</Text>
</div>
<Button className="wallet-connect-button">
<Text className="wallet-connect-button-text">Connect</Text>
</Button>
</div>
</Menu.Item>
);
}
// Otherwise don't show anything
return null;
} else {
// The user is on a desktop device
return (
<Menu.Item
key={wallet.name}
onClick={
wallet.readyState === WalletReadyState.Installed ||
wallet.readyState === WalletReadyState.Loadable
? () => onWalletSelected(wallet.name)
: () => window.open(wallet.url)
}
>
<div className="wallet-menu-wrapper">
<div className="wallet-name-wrapper">
<img src={wallet.icon} width={25} style={{ marginRight: 10 }} />
interface WalletRowProps {
wallet: AnyAptosWallet;
onConnect?: () => void;
}

function WalletRow({ wallet, onConnect }: WalletRowProps) {
return (
<WalletItem wallet={wallet} onConnect={onConnect} asChild>
<div className="wallet-menu-wrapper">
<div className="wallet-name-wrapper">
<WalletItem.Icon className="wallet-selector-icon" />
<WalletItem.Name asChild>
<Text className="wallet-selector-text">{wallet.name}</Text>
</div>
{wallet.readyState === WalletReadyState.Installed ||
wallet.readyState === WalletReadyState.Loadable ? (
<Button className="wallet-connect-button">
<Text className="wallet-connect-button-text">Connect</Text>
</Button>
) : (
<Text className="wallet-connect-install">Install</Text>
)}
</WalletItem.Name>
</div>
</Menu.Item>
);
}
};
{isInstallRequired(wallet) ? (
<WalletItem.InstallLink className="wallet-connect-install" />
) : (
<WalletItem.ConnectButton asChild>
<Button className="wallet-connect-button">Connect</Button>
</WalletItem.ConnectButton>
)}
</div>
</WalletItem>
);
}

function AptosConnectWalletRow({ wallet, onConnect }: WalletRowProps) {
return (
<WalletItem wallet={wallet} onConnect={onConnect} asChild>
<WalletItem.ConnectButton asChild>
<Button size="large" className="aptos-connect-button">
<WalletItem.Icon className="wallet-selector-icon" />
<WalletItem.Name />
</Button>
</WalletItem.ConnectButton>
</WalletItem>
);
}
Loading

0 comments on commit fbee96d

Please sign in to comment.