From c1128924944b6327b05c7e5c2bdfb018511700d0 Mon Sep 17 00:00:00 2001 From: Emmanuelmelvin Date: Fri, 15 Aug 2025 01:38:49 -0700 Subject: [PATCH 1/2] feat(dapp-kit): add optional iconBefore and iconAfter props to ConnectButton Allow consumers to pass custom React nodes to be rendered before or after the connect button text. This enables more flexible UI designs, such as adding wallet icons or status indicators alongside the button label. --- .../dapp-kit/src/components/ConnectButton.tsx | 27 ++++++++++++++++++- packages/dapp-kit/tsconfig.json | 4 ++- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/packages/dapp-kit/src/components/ConnectButton.tsx b/packages/dapp-kit/src/components/ConnectButton.tsx index c48751022..e033ea308 100644 --- a/packages/dapp-kit/src/components/ConnectButton.tsx +++ b/packages/dapp-kit/src/components/ConnectButton.tsx @@ -9,19 +9,27 @@ import { AccountDropdownMenu } from './AccountDropdownMenu.js'; import { ConnectModal } from './connect-modal/ConnectModal.js'; import { StyleMarker } from './styling/StyleMarker.js'; import { Button } from './ui/Button.js'; +import { IconButton } from './ui/IconButton.js'; type ConnectButtonProps = { connectText?: ReactNode; /** Filter the wallets shown in the connect modal */ walletFilter?: (wallet: WalletWithRequiredFeatures) => boolean; + /** Optional icon to show before the text */ + iconBefore?: ReactNode; + /** Optional icon to show after the text */ + iconAfter?: ReactNode; } & ButtonHTMLAttributes; export function ConnectButton({ connectText = 'Connect Wallet', walletFilter, + iconBefore, + iconAfter, ...buttonProps }: ConnectButtonProps) { const currentAccount = useCurrentAccount(); + return currentAccount ? ( ) : ( @@ -29,9 +37,26 @@ export function ConnectButton({ walletFilter={walletFilter} trigger={ - + } /> ); } + diff --git a/packages/dapp-kit/tsconfig.json b/packages/dapp-kit/tsconfig.json index 5f7e189ab..945f32906 100644 --- a/packages/dapp-kit/tsconfig.json +++ b/packages/dapp-kit/tsconfig.json @@ -6,7 +6,9 @@ "outDir": "dist/cjs", "isolatedModules": true, "jsx": "react-jsx", - "rootDir": "src" + "rootDir": "src", + "types": ["react"], + "lib": ["dom", "esnext"] }, "references": [ { "path": "../typescript" }, From df418caae6eb23091ce7a6759a33057f3c33fc6c Mon Sep 17 00:00:00 2001 From: Emmanuelmelvin Date: Fri, 15 Aug 2025 02:06:43 -0700 Subject: [PATCH 2/2] test(ConnectButton): verify iconBefore and iconAfter props render correctly Adds a unit test to ensure that optional iconBefore and iconAfter props are rendered in the ConnectButton, in addition to the connectText. --- .../test/components/ConnectButton.test.tsx | 31 +++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/packages/dapp-kit/test/components/ConnectButton.test.tsx b/packages/dapp-kit/test/components/ConnectButton.test.tsx index 1c2347f4a..a291c9500 100644 --- a/packages/dapp-kit/test/components/ConnectButton.test.tsx +++ b/packages/dapp-kit/test/components/ConnectButton.test.tsx @@ -8,12 +8,39 @@ import { ConnectButton } from '../../src/components/ConnectButton'; import { createWalletProviderContextWrapper } from '../test-utils'; describe('ConnectButton', () => { + test('renders iconBefore and iconAfter', () => { + const wrapper = createWalletProviderContextWrapper(); + + render( + Icon Before} + iconAfter={Icon After} + />, + { wrapper } + ); + + // Check button text + expect(screen.getByRole('button', { name: /connect wallet/i })).toBeInTheDocument(); + + // Check iconBefore + expect(screen.getByTestId('icon-before')).toBeInTheDocument(); + expect(screen.getByTestId('icon-before')).toHaveTextContent('Icon Before'); + + // Check iconAfter + expect(screen.getByTestId('icon-after')).toBeInTheDocument(); + expect(screen.getByTestId('icon-after')).toHaveTextContent('Icon After'); + }); + test('clicking the button opens the connect modal', async () => { const wrapper = createWalletProviderContextWrapper(); - render(, { wrapper }); + render( + , + { wrapper } + ); - const connectButtonEl = screen.getByRole('button', { name: 'Connect Wallet' }); + const connectButtonEl = screen.getByRole('button', { name: /connect wallet/i }); expect(connectButtonEl).toBeInTheDocument(); const user = userEvent.setup();