Skip to content

Vue

Vue works well with Web Components. For simple embeds, use <tokenflight-widget> directly. For dynamic config, use the TokenFlightWidget class.

Live projectOpen in StackBlitz

Should you read this?

Read this page if your app uses Vue 3 or Nuxt.

If you only need plain HTML, read Getting Started. If you need React, read React Integration.

Declarative Vue component

Use this when the widget config can be expressed as attributes.

vue
<script setup lang="ts">
import { registerWidgetElement } from '@tokenflight/swap/widget';

registerWidgetElement();
</script>

<template>
  <tokenflight-widget
    theme="dark"
    to-token="eip155:8453:0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"
    trade-type="EXACT_OUTPUT"
    amount="100"
  />
</template>

Tell Vue that TokenFlight tags are custom elements.

ts
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';

export default defineConfig({
  plugins: [
    vue({
      template: {
        compilerOptions: {
          isCustomElement: (tag) => tag.startsWith('tokenflight-'),
        },
      },
    }),
  ],
});

Imperative Vue component

Use this when you need callbacks, wallet adapters, or object config.

vue
<script setup lang="ts">
import { onBeforeUnmount, onMounted, ref } from 'vue';
import { TokenFlightWidget } from '@tokenflight/swap';

const containerRef = ref<HTMLDivElement | null>(null);
let widget: TokenFlightWidget | null = null;

onMounted(() => {
  if (!containerRef.value) return;

  widget = new TokenFlightWidget({
    container: containerRef.value,
    config: {
      theme: 'dark',
      toToken: {
        chainId: 8453,
        address: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
      },
      tradeType: 'EXACT_OUTPUT',
      amount: '100',
    },
    callbacks: {
      onDepositSuccess: (data) => {
        console.log('Payment complete:', data.orderId);
      },
      onDepositError: (error) => {
        console.error(`[${error.code}] ${error.message}`);
      },
    },
  });

  widget.initialize();
});

onBeforeUnmount(() => {
  widget?.destroy();
  widget = null;
});
</script>

<template>
  <div ref="containerRef" style="min-height: 560px"></div>
</template>

Nuxt

Use a client-only component. Either put the widget in a .client.vue file or wrap it with <ClientOnly>.

vue
<script setup lang="ts">
import PaymentWidget from '~/components/PaymentWidget.client.vue';
</script>

<template>
  <ClientOnly>
    <PaymentWidget />
  </ClientOnly>
</template>

See SSR / Next.js / Nuxt for more server-rendering notes.

Which Vue style should I use?

NeedUse
Shortest static embedDeclarative custom element
CallbacksImperative class
Wallet adapterImperative class
Runtime config from app stateImperative class
Simple theme or amount attributesDeclarative custom element

Next step