Swap form
A React component in Beamline's Trading category.
Exchange one token for another: type what you pay (or Max), pick each token from a searchable list with balances, and the form quotes what you receive with the rate, price impact, minimum after slippage and fees; the quote refreshes as it ages, the two sides trade places with one press, Review shows exactly what will happen, and the swap reports its progress, result or reason.
Use it for
- Swapping or converting between two assets at a quoted rate: a DEX, a wallet, a treasury converting currencies.
- Any 'you pay / you receive' exchange where the price is quoted, ages and can move before it is accepted.
Not for
- Orders on an order book with limit, stop and size (order-ticket).
- Moving money between your own accounts at a fixed 1:1 (a form with number-field).
- Showing the market (price-chart, order-book).
Anatomy
- root: a size container on the look's surface; a header with the title and the slippage setting
- pay panel: the amount (large, typed in the person's locale), its value in money, the token button (mark, symbol, chevron), the balance and Max
- flip: a round button between the panels; the two sides trade places
- receive panel: the quoted amount (a placeholder while quoting), its value, the token button
- rate line: 1 ETH = 3,412.20 USDC (press to read it the other way) and a hairline that drains as the quote ages, then refreshes
- details (fold): price impact (with a word: Low, High, Very high), minimum received after slippage, network fee, route
- action: a button that says what is missing (Enter an amount, Choose a token, Not enough ETH) until it can Review
- review: the same card grown in place: You pay, You receive at least, rate, impact, fee, Confirm swap and Back
- result: a drawn check and what was swapped with a link to the transaction, or the reason it failed with Try again
- token list: a search, the tokens with their balances and value, the chosen one checked; a sheet on a phone
States
- empty (no amount)
- quoting (receive shows a placeholder, the action waits)
- quoted (rate ageing; refreshed when it runs out; a changed rate flashes)
- no route (the quote's refusal, said under the panels)
- not enough balance (the pay panel and the action say so)
- high price impact (orange, the word High; over 5% red, Very high)
- reviewing
- swapping (Confirm shows progress; nothing can be changed)
- swapped (result with the transaction link and New swap)
- failed (the reason, Try again)
Keyboard
- Tab: amount, Max, pay token, flip, receive token, rate, details, action
- In the amount: digits and the locale's decimal sign; ↑/↓ do nothing (an amount is typed, not stepped)
- Token button opens the list with focus in its search; ↑/↓ move, Enter picks, Escape closes and returns focus
- Enter in the amount goes to Review when it is ready
Motion
The flip button turns half a turn while the two tokens slide to each other's panel (useFlip) and the amounts cross-fade. A new quote's amount rolls in; a changed rate flashes up or down. The age line drains on the compositor (one transform) and only while a quote is on screen. Review grows the card in place to the summary and Back shrinks it; the result's check draws itself. Reduced motion: no turn or slide; the age line is still shown as a still bar that refreshes.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
tokens (required) | SwapToken[] | — | { symbol, name, icon?, balance?, price? (in fiat), decimals? (display) }. |
from / defaultFrom / onFromChange | string | — | The symbol paid. |
to / defaultTo / onToChange | string | — | The symbol received. |
amount / defaultAmount / onAmountChange | string | — | The typed amount, as text (so “0.” survives typing). |
slippage / defaultSlippage / onSlippageChange | number | — | Fraction: 0.005 = 0.5%. Default 0.005. |
getQuote (required) | (request: SwapRequest, signal: AbortSignal) => Promise<SwapQuote> | — | Called as the amount, tokens or slippage settle and when a quote ages out; an older request is aborted. A rejection's message is shown (No route…). |
onSwap | (request: SwapRequest, quote: SwapQuote) => Promise<{ href?: string } | void> | — | A rejection shows its message with Try again; an href becomes View transaction. |
quoteTtl | number | — | Seconds a quote holds before it refreshes. Default 20. |
fiat | string | — | The money symbol for values. Default "$". |
title | ReactNode | — | Default “Swap”. |
className / classNames / style / ref | root | — |
Built from
- button
- popover
- segmented-control
- spinner
Dependencies
@radix-ui/react-popover, lucide-react
Import
import { SwapForm } from "@/components/swap-form/swap-form";
Get it
Swap form is part of Beamline: 200+ components and 50+ complete screens for React that your coding agent (Claude Code, Codex, Cursor or any MCP client) installs into your app through Beamline's MCP server, as a ready-built package or as plain React source you can change. $49 launch price, one payment, no subscription, lifetime updates, one licence for your whole team. Get Beamline · Connect your agent
More in Trading
- Price chart: Candles, line or area price chart with volume, OHLC legend and reference lines, built for live ticks.
- Market heatmap: Treemap of markets sized by weight and coloured by change, grouped by sector, with hatched no-data tiles.
- Order book: Asks, spread and bids with cumulative depth bars, grouping, change flashes and keyboard price picking.
- Options chain: Calls and puts for one expiry around a centre column of strikes: bid, ask, implied volatility, delta, volume and open interest, the money shaded in, a…
- Depth chart: Cumulative bid and ask depth as stepped areas around the mid, with hover readout.
- Ticker tape: A continuously scrolling row of symbols with price, change and mini trend; anyone can hold it: hover, keyboard focus or a tap.
- Watchlist: A selectable, sortable list of markets with mini trends, prices, changes and stars.
- Trades tape: Recent trades, newest first, with side glyphs, large-print marking and one-time arrival flashes.
- Order ticket: Buy/sell order entry with limit, market and stop types, % of balance, inline validation and a live cost summary.
- Positions table: Open positions with live unrealised PnL, liquidation warnings and close actions.
- P&L calendar: A trader's month at a glance: every trading day's profit or loss in its cell, shaded deeper the bigger it was in the gain or loss colour and marked ▲ or…
- Price ticker: Symbol, last price with a directional flash, 24h change and stats.
- Funding countdown: Perpetual funding rate with who pays, and a live countdown ring to the next funding.