Skip to main content
This guide helps you upgrade from @metalayer/widget v0.x to v1.x, which introduces a cleaner API, improved naming conventions, and a powerful new theme system.

Breaking Changes

1. Widget Props Structure

The widget no longer uses a nested config object. Props are now passed directly to the component.
<Widget
  config={{
    onOpenConnectModal: openModal,
    onDisconnectWallet: disconnect,
    onSubmitTransaction: handleSubmit,
    onSelectToken: handleTokenSelect,
    className: 'custom-class',
    source: sourceConfig,
    destination: destinationConfig,
  }}
/>

2. Callback Naming Changes

All callbacks have been renamed for clarity and consistency with React conventions:
Old Name (v0.x)New Name (v1.x)Description
onOpenConnectModalonConnectClickHandler when user clicks connect
onDisconnectWalletonDisconnectClickHandler when user clicks disconnect
onSubmitTransactiononTransactionSubmittedFired after transaction submission
onSelectTokenonTokenSelectedFired after token selection

3. Theme System

The brandColor prop has been removed in favor of the new comprehensive theme system.
<WidgetProvider
  sdkConfig={{ apiKey: 'key', environment: 'mainnet' }}
  brandColor="#6750A4"
>
Note: brandColor has been completely removed in v1.x. You must use the new theme prop. See the New Theme System Features section below for comprehensive theming options.

4. WidgetProvider Props Update

The chains prop has been renamed to enabledChains for clarity:
<WidgetProvider
  sdkConfig={{ apiKey: 'key', environment: 'mainnet' }}
  chains={supportedChains}
>

Step-by-Step Migration

Step 1: Update Package Version

pnpm update @metalayer/widget@^1.0.0

Step 2: Update Widget Component Usage

Find all <Widget> components and update the props:
- <Widget
-   config={{
-     onOpenConnectModal: openConnectModal,
-     onDisconnectWallet: () => disconnect(),
-     onSubmitTransaction: (source, dest, amount) => {
-       console.log('Transaction submitted', { source, dest, amount });
-     },
-     className: 'rounded-xl',
-   }}
- />
+ <Widget
+   onConnectClick={openConnectModal}
+   onDisconnectClick={() => disconnect()}
+   onTransactionSubmitted={(source, dest, amount) => {
+     console.log('Transaction submitted', { source, dest, amount });
+   }}
+   className="rounded-xl"
+ />

Step 3: Update WidgetProvider Theme

Replace brandColor with the new theme configuration:
  <WidgetProvider
    sdkConfig={{ apiKey: 'your-key', environment: 'mainnet' }}
-   brandColor="#6750A4"
+   theme={{
+     colors: { primary: '#6750A4' }
+   }}
  >

Step 4: Update Token Selection Callbacks

If you’re using token selection callbacks, update the naming:
  <Widget
-   config={{
-     onSelectToken: (direction, chainId, tokenAddress) => {
-       console.log('Token selected', { direction, chainId, tokenAddress });
-     }
-   }}
+   onTokenSelected={(direction, chainId, tokenAddress) => {
+     console.log('Token selected', { direction, chainId, tokenAddress });
+   }}
  />

Step 5: Update Controlled Token Selection

If using controlled source/destination props:
  <Widget
-   config={{
-     source: { chainId: 1, tokenAddress: '0x...' },
-     destination: { chainId: 42161, tokenAddress: '0x...' },
-     onOpenConnectModal: openModal,
-   }}
+   source={{ chainId: 1, tokenAddress: '0x...' }}
+   destination={{ chainId: 42161, tokenAddress: '0x...' }}
+   onConnectClick={openModal}
  />

New Theme System Features

Take advantage of the new theming capabilities:

Predefined Themes

<WidgetProvider
  sdkConfig={sdkConfig}
  theme={{ predefined: 'modern' }} // 'comfy' | 'modern'
>

Custom Color Palette

<WidgetProvider
  sdkConfig={sdkConfig}
  theme={{
    mode: 'light',       // 'light' | 'dark'
    colors: {
      primary: '#6750A4',
      neutral: '#5E5E5E',
      success: '#00C853',
      warning: '#FFB300',
      info: '#2196F3',
      failure: '#F44336',
    },
    corners: 'rounded',  // 'none' | 'minimal' | 'soft' | 'medium' | 'rounded'
    shadow: 'light',     // 'none' | 'sharp' | 'light' | 'heavy'
  }}
>

Feature Toggles

<WidgetProvider
  sdkConfig={sdkConfig}
  theme={{
    colors: { primary: '#6750A4' },
    features: {
      headerIcons: true,
      headerBackground: false,
      background: true,
      outlineComponents: false,
    }
  }}
>

Advanced Overrides

<WidgetProvider
  sdkConfig={sdkConfig}
  theme={{
    colors: { primary: '#6750A4' },
    overrides: {
      background: {
        main: '#FFFFFF',
        layer1: '#F5F5F5',
        layer2: '#EEEEEE',
        layer3: '#E0E0E0',
      },
      text: {
        primary: '#1A1A1A',
        secondary: '#666666',
        disabled: '#9E9E9E',
      }
    }
  }}
>

Common Integration Updates

RainbowKit

  function BridgePage() {
    const { openConnectModal } = useConnectModal();
    const { disconnect } = useDisconnect();

    return (
      <Widget
-       config={{
-         onOpenConnectModal: openConnectModal,
-         onDisconnectWallet: disconnect,
-       }}
+       onConnectClick={openConnectModal}
+       onDisconnectClick={disconnect}
      />
    );
  }

Dynamic.xyz

  function BridgePage() {
    const { setShowAuthFlow } = useDynamicContext();

    return (
      <Widget
-       config={{
-         onOpenConnectModal: () => setShowAuthFlow(true),
-       }}
+       onConnectClick={() => setShowAuthFlow(true)}
      />
    );
  }

ConnectKit

  function BridgePage() {
    const { openConnectModal } = useModal();
    const { disconnect } = useDisconnect();

    return (
      <Widget
-       config={{
-         onOpenConnectModal: openConnectModal,
-         onDisconnectWallet: disconnect,
-       }}
+       onConnectClick={openConnectModal}
+       onDisconnectClick={disconnect}
      />
    );
  }

TypeScript Updates

The type definitions have changed significantly:
// Old types (v0.x)
import type { WidgetProps, WidgetConfig } from '@metalayer/widget';

// v0.x used nested config object
const props: WidgetProps = {
  config: {
    onOpenConnectModal: () => void,
    onDisconnectWallet?: () => void,
    onSubmitTransaction?: (sourceChainId?: number, destChainId?: number, amount?: string) => void,
    onSelectToken?: (direction: 'source' | 'destination', chainId: number, tokenAddress: string) => void,
    className?: string,
    source?: { chainId: number; tokenAddress?: string },
    destination?: { chainId: number; tokenAddress?: string },
  }
};

// New types (v1.x)
import type { WidgetProps } from '@metalayer/widget';

const props: WidgetProps = {
  // REQUIRED callback
  onConnectClick: () => void,

  // Optional callbacks
  onDisconnectClick?: () => void,
  onTransactionSubmitted?: (
    sourceChainId?: number,
    destChainId?: number,
    amount?: string
  ) => void,
  onTokenSelected?: (
    direction: 'source' | 'destination',
    chainId: number,
    tokenAddress: string
  ) => void,

  // Optional configuration
  source?: { chainId: number; tokenAddress?: string },
  destination?: { chainId: number; tokenAddress?: string },
  className?: string,
  isConnecting?: boolean,
};

Additional Exported Types

v1.x exports comprehensive TypeScript types for all configuration:
import type {
  // Widget types
  WidgetProps,

  // Provider types
  WidgetProviderProps,

  // Theme types
  ThemeConfig,
  Theme,
  ThemeMode,
  PredefinedTheme,
  ThemeFeatures,
  CornerRadiusStyle,
  ShadowStyle,
  FontFamilyConfig,
  GoogleFontsConfig,
  CustomFontConfig,

  // Solana types (if using Solana support)
  WidgetSolanaSigner,
  WidgetSolanaProps,
} from '@metalayer/widget';

Troubleshooting

Remove the config wrapper and pass props directly to <Widget>.
Use theme={{ colors: { primary: 'your-color' } }} instead.
Rename to onConnectClick.
Rename to onTokenSelected.

Best Practices

  1. Use the new theme system - It provides better customization and consistency
  2. Leverage TypeScript - The new types provide better autocomplete and type safety
  3. Optional disconnect - Only provide onDisconnectClick if your wallet library supports it
  4. Test callbacks - Ensure all renamed callbacks are working correctly after migration