Ever wanted to customize your connect wallet?

Ever wanted to customize your connect wallet and found it hard, or you just don’t know how?

Now you have the answer you’ve been looking for.

You already own the CCC provider. What you have been missing is a connect flow you can shape: which wallets appear, how a single row looks, and what the person sees after they connect. Icon, name, address, balance, or a did:ckb profile. Your layout. Your classes.

What you get

  • A connect button that disappears once a wallet is connected, so your own layout can take its place

  • A dialog you fill yourself: wallet list, chain choice, connecting state, then the account

  • A wallet list you can narrow to the names you support, or leave open to every wallet CCC finds

  • One row you can restyle without touching the others

  • Icon only, name only, or both

  • An account view you compose: wallet profile, or a did:ckb avatar, name, and identifier

  • Disconnect and switch network, placed where you want them

  • Balance digits that truncate instead of round, and an address you shorten from both ends

Leave the dialog out and open() still opens CCC. Mount it, and that same click opens yours.

Install

npm install ckb-connect-wallet-kit @ckb-ccc/connector-react react react-dom

Tailwind v4 does not scan node_modules until you point it at the package:

@import "tailwindcss";
@source "../node_modules/ckb-connect-wallet-kit/dist";

Sit the kit under the ccc.Provider you already have. The kit never mounts CCC.

The dialog is yours

ConnectWalletDialog does not draw a popup by itself. You decide the chrome. ConnectWalletDialogOverlay is the centered modal. Skip it and the same steps can live in a drawer, a dropdown, or a page.

open below comes from useConnectWallet(). The connect button calls it. Any element you write can call it too.

<ConnectWalletContainer>
  <ConnectWalletButton />
  <ConnectWalletDialog>
    <ConnectWalletDialogOverlay>
      <ConnectWalletDialogWallets>
        <ConnectWalletDialogWalletsHeader>
          <h2>Connect Wallet</h2>
          <ConnectWalletDialogClose />
        </ConnectWalletDialogWalletsHeader>
        <ConnectWalletDialogWalletList />
        <ConnectWalletDialogWalletsFooter>
          <ConnectWalletDialogWalletsRefresh />
        </ConnectWalletDialogWalletsFooter>
      </ConnectWalletDialogWallets>
      <ConnectWalletDialogSigners />
      <ConnectWalletDialogConnecting />
      <ConnectWalletDialogAccount>
        <ConnectWalletDialogAccountHeader>
          <ConnectWalletName />
          <ConnectWalletDialogClose />
        </ConnectWalletDialogAccountHeader>
        <ConnectWalletAddress />
        <ConnectWalletBalance />
      </ConnectWalletDialogAccount>
    </ConnectWalletDialogOverlay>
  </ConnectWalletDialog>
</ConnectWalletContainer>

One signer connects immediately. Several signers move to the chain step. After a successful connect the dialog stays on the account step. Disconnect brings the wallet list back.

After they connect

This is the account step: the connected wallet dialog. Put the header, the profile, and the footer in the order your product needs.

With did:ckb

Wrap the account body in ConnectWalletDid. The avatar, display name, and identifier come from the lock’s did:ckb profile. Each piece takes a fallback, so a wallet with no DID still has something to show.

<ConnectWalletDialogAccount>
  <ConnectWalletDialogAccountHeader>
    <ConnectWalletName />
    <ConnectWalletDialogClose />
  </ConnectWalletDialogAccountHeader>
  <ConnectWalletDid>
    <ConnectWalletDidAvatar
      className="h-16 w-16"
      fallback={<ConnectWalletImage className="h-16 w-16 rounded-2xl" />}
    />
    <ConnectWalletDidName fallback={<ConnectWalletAddress frontChars={6} endChars={4} />} />
    <ConnectWalletDidId />
    <ConnectWalletBalance />
  </ConnectWalletDid>
  <ConnectWalletDialogAccountFooter>
    <ConnectWalletDisconnect />
    <ConnectWalletSwitchNetwork />
  </ConnectWalletDialogAccountFooter>
</ConnectWalletDialogAccount>

Nothing is fetched until you render ConnectWalletDid.

Wallet profile

Skip DID and show the wallet itself: icon, name, address, balance.

<ConnectWalletDialogAccount>
  <ConnectWalletDialogAccountHeader>
    <ConnectWalletImage />
    <ConnectWalletName />
    <ConnectWalletDialogClose />
  </ConnectWalletDialogAccountHeader>
  <ConnectWalletAddress frontChars={6} endChars={4} />
  <ConnectWalletBalance decimalPlaces={4} />
  <ConnectWalletDialogAccountFooter>
    <ConnectWalletDisconnect buttonText="Disconnect" />
    <ConnectWalletSwitchNetwork />
  </ConnectWalletDialogAccountFooter>
</ConnectWalletDialogAccount>

The same pieces work outside the dialog. A button that calls open() can be the profile on your page, and the dialog can be the place they manage the account.

Which wallets, and how they look

Omit wallets and the list is every wallet CCC discovers.

<ConnectWalletDialogWalletList />

Pass names when you only want the wallets you support, in that order. A name that is not installed is skipped.

<ConnectWalletDialogWalletList wallets={["JoyID", "MetaMask"]} />

show is "both", "icon", or "name". An icon-only row keeps the wallet name as its accessible label.

<ConnectWalletDialogWalletList show="icon" />

Style every row the same way with buttonClassName. Style one wallet with ConnectWalletDialogWallet, or with the class the list already puts on each row. That class is the CCC name, lowercased, with other characters turned into -, prefixed by ckb-wallet-. MetaMask is ckb-wallet-metamask. JoyID Passkey is ckb-wallet-joyid-passkey.

<ConnectWalletDialogWalletList className="[&_.ckb-wallet-joyid]:border-emerald-400 [&_.ckb-wallet-joyid]:bg-emerald-400/10" />

Or draw the rows yourself:

<div className="flex flex-col gap-2">
  <ConnectWalletDialogWallet name="JoyID" className="border-emerald-400 bg-emerald-400/10" />
  <ConnectWalletDialogWallet name="MetaMask" />
</div>

Links

If a snippet here does not click, open the usage page. Each row tells you whether you need to be connected or disconnected, then shows the result next to the code.

If something is awkward, missing, or wrong, say so. A short note on the usage page, or an issue, is enough: Issues · Victor-Okenwa/revamp-ckb-connect-wallet · GitHub

8 Likes

Great work, Victor! :green_heart:

I’ve been building several projects in the CKB ecosystem, including SkillPass, CellFlow, and CellGuard, and I think having a more flexible wallet connection UI is really useful for improving the user experience.

I especially like how this builds on the existing CCC provider while allowing developers to customize the wallet list, connection flow, and account layout without being locked into a predefined interface. The optional did integration is also a nice touch!

This could be particularly useful for SkillPass, where I want the wallet connection experience to feel like a natural part of the application rather than a separate blockchain interaction.

Thanks for sharing this with the community! Looking forward to exploring it further. :rocket:

3 Likes