Token Picker

Responsive modal for picking a crypto asset. Renders as a Dialog on desktop and a bottom Drawer on mobile, with three modes — Pay, Receive, and Pay-With — that swap which sections appear (recent, owned, trending, cash, payment methods).

Install

import { TokenPicker } from '$lib/components/ui/token-picker';
Custom

Pay mode

The default. Shows Recent, Your tokens, and Trending. The owned section ranks by USD value (balance × price) descending and only renders rows where the balance is non-zero — perfect for the "spend from" leg of a swap.

Selected Ethereum (ETH)

Receive mode

Hides the owned section, hides per-token balances, and turns rows that ship multiple chains into an expandable chain list — so the user can pick USDC on Base rather than just "USDC". The onSelect callback receives both the token and the chosen chain id.

Click to open the receive picker.

Pay-with mode (mixed surface)

Prepends a Pay with cash section listing the supplied paymentMethods alongside the crypto rows — used inside the Buy flow where the funding source can be a card, a wire, or one of the user's owned tokens. The onMethodSelect callback fires when the user picks a fiat method instead of a token.

No source selected.

Inline body

When the modal frame is wrong — e.g. the picker lives inside a multi-step flow that already owns its surface — import TokenPickerBody directly and skip the Dialog/Drawer wrapper. Pass hideHeader to drop the centered title bar, and the body becomes a plain column that fits whatever container holds it.

⌘K

API reference

The default TokenPicker switches between Dialog (desktop) and Drawer (mobile) via the IsMobile rune. For ad-hoc surfaces, compose TokenPickerBody yourself and supply onClose.

PropTypeDescription
TokenInfo[]Source token catalog. Each token may declare a chainList + per-chain balances; the picker reads balance × price to rank owned tokens.
boolean (bindable)Two-way bindable visibility. Selecting a token sets open back to false.
'pay' | 'receive' | 'pay-with'Controls which sections render. Pay shows owned + recent + trending; Receive expands chain lists and hides balances; Pay-With prepends a payment-methods section.
stringHeader text inside the modal and the screen-reader-only Drawer.Title / Dialog.Title.
string | undefinedPre-highlights the matching row with the selected state.
string | undefinedWhen receive mode is active and the selected token has a chain list, marks the active chain row.
booleanRenders a disabled "Cash" preview group keyed on FIAT_CURRENCIES — a placeholder for the upcoming on-ramp.
PaymentMethod[] | undefinedRequired when mode="pay-with". Each method is rendered as a row above the token sections.
(token: TokenInfo, chainId?: string) => voidFires on token selection. The chainId is populated when the user expands a multi-chain row in receive mode.
(method: PaymentMethod) => voidFires when the user picks a row from the Pay-with-cash section in pay-with mode.