Exploration: Wallet Discovery - UX/UI proposal - #2237
Draft
joel-da wants to merge 7 commits into
Draft
Conversation
Signed-off-by: Joel Lovera <joel.lovera@digitalasset.com>
Signed-off-by: Joel Lovera <joel.lovera@digitalasset.com>
Signed-off-by: Joel Lovera <joel.lovera@digitalasset.com>
Signed-off-by: Joel Lovera <joel.lovera@digitalasset.com>
- Add shared in-page modal picker (wallet-picker-modal) in core-wallet-ui-components, rendered in a Shadow DOM - Wire it as the dapp-sdk default walletPicker (replaces popup); support connect/error/retry, back-to-list during connecting, and WalletConnect QR - Render suggested wallets (from wallets.json) with hover-reveal install badge - Ordering: installed, WalletConnect, remote, then the rest - Scrollable list (~4.5 rows) with bottom shadow divider - Design tokens + prefers-color-scheme dark mode; type/shape refinements - Canton logo for Remote Wallet; Need a wallet link to wallet directory - Migrate ping example to the SDK default picker (remove custom modal) - Rename Send Connect -> Send; add test wallets Signed-off-by: Joel Lovera <joel.lovera@digitalasset.com>
…polish - Fade hints at top and bottom of the list that appear/disappear based on scroll position (hidden at their edge and when the list is not scrollable) - Remove footer divider line; tighten list-to-footer gap - Add horizontal padding around the component for more breathing room Signed-off-by: Joel Lovera <joel.lovera@digitalasset.com>
- Add Modal/Popup and Light/Dark toggles to the ping example - setWalletPickerModalTheme (light/dark/auto) with data-swk-theme override; refactor modal colors into shared light/dark token blocks - Route SDK connect notify/retry to the active picker (modal or popup) so the popup picker works when selected - Re-export pickWallet, setWalletPickerModalTheme, WalletPickerModalTheme - WalletConnect: header shows 'Scan with your phone'; add 'Or' divider label Signed-off-by: Joel Lovera <joel.lovera@digitalasset.com>
There was a problem hiding this comment.
Pull request overview
Explores a new wallet discovery UX by adding an in-page modal wallet picker (Shadow DOM–based) and making it the dapp-sdk default, while keeping the legacy popup picker available for comparison and fallback.
Changes:
- Adds an in-page wallet picker modal implementation (including WalletConnect QR/connect states and modal theme override hooks).
- Updates
DappSDKto default to the modal picker, addssetWalletPicker()override API, and routes connect/error/retry/back signals to the active picker. - Enhances WalletConnect adapter URI handling (QR generation + optional suppression of legacy popup) and updates the ping example to exercise modal vs popup and light vs dark.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| sdk/dapp-sdk/src/wallets.json | Updates bundled suggested wallets list (includes temporary placeholder entries). |
| sdk/dapp-sdk/src/sdk.ts | Defaults to modal picker, adds picker override API, and adds “back to abort” connect flow logic. |
| sdk/dapp-sdk/src/sdk.test.ts | Adjusts mocks/assertions for modal picker notifications and back handling. |
| sdk/dapp-sdk/src/index.ts | Re-exports wallet picker-related APIs and adds setWalletPicker to the public surface. |
| sdk/dapp-sdk/src/adapter/walletconnect-adapter.ts | Adds QR/URI pre-generation and openPopupForUri control; expands onUri signature. |
| examples/ping/src/index.css | Tweaks example styling (link/button colors). |
| examples/ping/src/hooks/useConnect.ts | Updates ping to use SDK modal picker plumbing + WalletConnect URI forwarding. |
| examples/ping/src/App.tsx | Adds UI toggles to compare modal vs popup and light vs dark modal theme. |
| examples/ping/src/App.css | Minor styling tweak. |
| examples/ping/.env.example | Documents optional WalletConnect chain ID override. |
| core/wallet-ui-components/src/windows/wallet-picker-modal.ts | Introduces the new in-page modal wallet picker implementation and public control APIs. |
| core/wallet-ui-components/src/index.ts | Exports the new modal picker module. |
Suppressed comments (1)
sdk/dapp-sdk/src/sdk.ts:703
- The module-level
setWalletPickerwrapper should accept and forward the optional picker kind so callers can reliably select the popup notification path when providing a wrapped picker function.
export const setWalletPicker = (picker: WalletPickerFn | undefined): void =>
sdk.setWalletPicker(picker)
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // ── Asset exports (icons for wallet adapters) ── | ||
| export { CANTON_LOGO_PNG, WALLET_GATEWAY_ICON } from './assets' | ||
|
|
||
| // ── Default wallet picker (in-page modal) ── |
| if (!parsed) return | ||
| const normalizedUrl = parsed.toString() | ||
| this.select({ | ||
| providerId: `custom:remote:${encodeURIComponent(normalizedUrl)}`, |
Comment on lines
+109
to
+112
| setWalletPicker(picker: WalletPickerFn | undefined): void { | ||
| this.walletPicker = picker ?? (pickWalletModal as WalletPickerFn) | ||
| this.pickerKind = this.resolvePickerKind(this.walletPicker) | ||
| } |
Comment on lines
16
to
23
| a { | ||
| font-weight: 500; | ||
| color: #646cff; | ||
| color: #000; | ||
| text-decoration: inherit; | ||
| } | ||
| a:hover { | ||
| color: #535bf2; | ||
| color: #000; | ||
| } |
Comment on lines
+420
to
+422
| async prepareUri(): Promise<void> { | ||
| if (this.session || this.pendingApproval) return | ||
| if (this.prepareUriPromise) return this.prepareUriPromise |
Comment on lines
158
to
170
| vi.mock('@canton-network/core-wallet-ui-components', async (importOriginal) => { | ||
| const actual = | ||
| await importOriginal< | ||
| typeof import('@canton-network/core-wallet-ui-components') | ||
| >() | ||
| return { | ||
| ...actual, | ||
| notifyWalletPickerConnected: mockNotifyWalletPickerConnected, | ||
| notifyWalletPickerError: mockNotifyWalletPickerError, | ||
| waitForWalletPickerRetrySelection: | ||
| notifyWalletPickerModalConnected: mockNotifyWalletPickerConnected, | ||
| notifyWalletPickerModalError: mockNotifyWalletPickerError, | ||
| waitForWalletPickerModalRetrySelection: | ||
| mockWaitForWalletPickerRetrySelection, | ||
| waitForWalletPickerModalBack: mockWaitForWalletPickerModalBack, | ||
| } |
Comment on lines
+15
to
+27
| { | ||
| "name": "Wallet 1", | ||
| "type": "browser", | ||
| "providerId": "browser:ext:test-wallet-1", | ||
| "description": "Connect via a browser extension wallet", | ||
| "icon": "https://info.send.it/img/favicon.svg", | ||
| "installUrls": [ | ||
| { | ||
| "platform": "chrome", | ||
| "url": "https://chromewebstore.google.com/detail/send-connect/ldmohiccoioolenadmogclhoklmanpgi" | ||
| } | ||
| ] | ||
| }, |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Wallet Discovery: in-page modal exploration
This is a UX/UI exploration for the wallet discovery flow. It is not intended to be merged as-is; it is meant to gather feedback on direction.
DC.demo.mov
Main changes
prefers-color-scheme, plus an explicit theme override so a dApp can force light or dark.Supporting changes
sdk.setWalletPicker()API so a dApp can inject a custom picker into the shared SDK singleton.setWalletPickerModalTheme('light' | 'dark' | 'auto')API (and aWalletPickerModalThemetype) to control the modal color scheme.setWalletPickerModalWalletConnectUri()to feed the WalletConnect pairing URI/QR into the modal's connecting view.openPopupForUrioption to suppress the legacy popup. The QR view header reads "Scan with your phone" and includes an "Or" divider label above the copy-link action.Open questions
Wallet picker: modal vs popup (decision needed)
This PR adds a new in-page modal picker and makes it the dapp-sdk default. The old popup picker is still present. They are separate implementations with separate markup/CSS, so they look different. Both work today (the SDK routes connect/error/retry to whichever is active; the ping example has a toggle to compare).
Why not shared: the popup is not rendered normally. Its component is serialized with
.toString()into a Blob and run in a separate window, so it cannot import shared modules or reference top-level constants (everything must be inlined). The modal has no such constraint. That is the blocker to a single shared component.Possible options:
toString()) and share one component: high effort.Known gaps / caveats
prefers-color-schemefollows the OS, not the host dApp's own theme; there is no wiring to the gateway theme variables yet.Wallet 1/2/3entries used to test the list; remove before merge.tsdownbuild fails locally with anunrunresolution error (environment/tooling, unrelated to these changes); thetsctype emit works.