@deloraprotocol/widget
v1.0.9
Published
A React widget component library with light/dark themes and CSS variable overrides
Readme
@deloraprotocol/widget
A React widget component library for crypto trading UI, migrated from delora-exchange (Angular). Includes Trade widget, token selection, network selection, and slippage panel. Consumers do not need Tailwind — the library ships compiled CSS.
Note: Wallet connection and transaction execution remain host-managed. The widget can request connect, emit quotes, and notify the host when the user clicks Approve or Swap.
Installation
npm install @deloraprotocol/widget react react-domImport styles
You must import the library CSS once in your app (e.g. in your root entry file):
import "@deloraprotocol/widget/styles.css";Usage
Trade Widget
import { TradeWidget } from "@deloraprotocol/widget";
<TradeWidget
theme="dark"
config={{
apiBase: "https://api.delora.build",
isWalletConnected: connected,
onConnectWallet: openWalletModal,
}}
initialBuyToken={{ chainId: 1, address: "0x..." }}
lockBuyToken
onQuote={(quote) => console.log("quote", quote)}
onApprove={(payload) => console.log("approve", payload)}
onSwap={(payload) => console.log("swap", payload)}
onError={(error) => console.error(error)}
/>apiBase is used for:
/v1/chains/v1/tokens/v1/quotes
If omitted, the widget defaults to https://api.delora.build.
dataBaseUrl is no longer required for metadata fetching. Keep it only if you need
to resolve relative image URLs from a custom source. For explicit control over image
resolution, pass assetBaseUrl.
Simple Widget (MyWidget)
import { MyWidget } from "@deloraprotocol/widget";
<MyWidget theme="light" />
<MyWidget theme="dark" />
<MyWidget vars={{ accent: "#22c55e", radius: "24px" }} />
<MyWidget className="max-w-md" style={{ marginLeft: "2rem" }} />API
Exports
MyWidget— the widget componentTradeWidget— trade widget with token/network selection and quote flowMyWidgetTheme—"light" | "dark"MyWidgetVars— typed object for token overridesMyWidgetProps— component propsTradeWidgetProps,TradeWidgetConfigTradeWidgetTokenSelectionTradeWidgetQuotePayloadTradeWidgetActionPayloadTradeWidgetErrorPayloadToken,Network
MyWidgetProps
| Prop | Type | Description |
|----------|-------------------|--------------------------------------------------|
| theme | "light" \| "dark" | Built-in theme (default: "light") |
| vars | Partial<MyWidgetVars> | Override theme tokens via CSS variables |
| className | string | Applied to root (for host layout/styling) |
| style | React.CSSProperties | Applied last for advanced overrides |
Extends React.HTMLAttributes<HTMLDivElement> for other div props.
TradeWidgetProps
TradeWidgetProps extends normal root div props except DOM onError, which is reserved for the widget error callback below.
| Prop | Type | Description |
|----------|-------------------|--------------------------------------------------|
| config | TradeWidgetConfig | Widget runtime config |
| theme | "light" \| "dark" | Built-in theme (default: "dark") |
| vars | Partial<MyWidgetVars> | Override theme tokens via CSS variables |
| initialSellToken | { chainId: number; address: string } | Preselect sell token |
| initialBuyToken | { chainId: number; address: string } | Preselect buy token |
| initialSellNetworkId | number | Preselect sell network |
| initialBuyNetworkId | number | Preselect buy network |
| lockSellToken | boolean | Prevent changing sell token |
| lockBuyToken | boolean | Prevent changing buy token |
| lockSellNetwork | boolean | Prevent changing sell network |
| lockBuyNetwork | boolean | Prevent changing buy network |
| onQuote | (payload) => void | Called when a new quote is resolved |
| onApprove | (payload) => void | Called when the user presses Approve |
| onSwap | (payload) => void | Called when the user presses Swap |
| onError | (payload) => void | Called for metadata, selection, and quote errors |
TradeWidgetConfig
| Prop | Type | Description |
|----------|-------------------|--------------------------------------------------|
| apiBase | string | Delora API base for /v1/chains, /v1/tokens, /v1/quotes |
| assetBaseUrl | string | Optional base for resolving relative image URLs |
| dataBaseUrl | string | Legacy image-base fallback |
| isWalletConnected | boolean | Controls the main action button state |
| onConnectWallet | () => void | Called when the user clicks Connect Wallet |
Callback payloads
onQuote(payload)returns selected sell/buy network, selected sell/buy token, current sell/buy amounts, slippage, and the raw Deloraquote.onApprove(payload)andonSwap(payload)return the current selection plusquote,txData,price, andgasCostUSD.onError(payload)returns{ source, message, status?, statusCode?, error? }, wheresourceis one ofmetadata,selection, orquote.
Locking behavior
lockBuyToken/lockSellTokendisable token picking and also freeze the related network, because the token already implies a chain.lockBuyNetwork/lockSellNetworkdisable network changes but keep token selection available within the locked chain.- Any lock also disables the center "swap sides" button to avoid silently breaking host-provided constraints.
Why no Tailwind required in host
The library uses Tailwind only at build time to author styles. The output is plain compiled CSS shipped in dist/styles.css. Your host app imports this CSS file and does not need Tailwind, PostCSS, or any build-time Tailwind configuration.
Style isolation
The library provides style isolation without Shadow DOM:
Our styles don't affect the host: We disable Tailwind preflight and do not emit global element selectors (e.g. no
button {}orh1 {}). All styling is class-based and scoped within the widget markup.Host styles have limited impact on us: We add a minimal scoped reset under
[data-delora-widget-root]:box-sizing: border-boxon root and descendants- Explicit
font-family,font-size,color,line-heighton the root
Limitations: Host global styles (e.g.
* { box-sizing: content-box; }orbutton { font-size: 30px; }) can still affect the widget in extreme cases. We mitigate by setting explicit values on the widget root and avoiding reliance on inherited defaults.
Build
npm run buildOutputs:
dist/index.js(ESM)dist/index.d.tsdist/styles.css
Publishing to npm
Prerequisites
- npm account
- For scoped packages like
@deloraprotocol/widget: create the org at npmjs.com/org/create (or change the scope inpackage.jsonto your username)
First-time publish
Build the package:
npm run buildLog in to npm:
npm loginEnter your username, password, and email. If 2FA is enabled, enter the one-time code.
Publish (scoped packages require
--access public):npm publish --access public
Publishing updates
Bump the version:
npm version patch # 1.0.0 → 1.0.1 (bug fixes) npm version minor # 1.0.0 → 1.1.0 (new features) npm version major # 1.0.0 → 2.0.0 (breaking changes)Build and publish:
npm run build npm publish --access public
Org members
- Add members under Organization → Members on npmjs.com
- Any member with publish rights can publish and update the package
- Only one person needs to create the org; others can be invited
Running the widget locally
One-time setup
npm install
npm run build
cd playground && npm installDevelopment
npm run playground:devThis runs the library watcher and the playground dev server together. The playground uses the built output from dist/.
When errors occur or the UI shows stale/broken code: run npm run build separately to rebuild the library, then restart or refresh the playground. The playground does not auto-rebuild the library.
Alternative: build then run
npm run build
cd playground && npm run devBuild the library first, then run only the playground dev server.
