> For the complete documentation index, see [llms.txt](https://docs.transientlabs.xyz/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.transientlabs.xyz/integrations/embeddable-components.md).

# Embeddable Components

Drop-in Web3 building blocks for any website.

These are small, ready-made HTML elements (web components) that add blockchain features — connecting a wallet, running an auction, minting an NFT, redeeming tokens — to any web page. You add two lines to your page's `<head>`, then place the elements you want in the page like regular HTML tags. No React or build step required: they work in plain HTML and inside any framework (React, Vue, Svelte, WordPress, Webflow, etc.).\
\
`Latest Version: 1.9.0`

### What's included

| Element                     | What it does                                                               |
| --------------------------- | -------------------------------------------------------------------------- |
| `<tl-connect-button>`       | A "Connect Wallet" button.                                                 |
| `<tl-siwe-button>`          | "Sign in with Ethereum" — proves a user owns their wallet.                 |
| `<tl-auction>`              | A live NFT auction (bid, buy now, settle).                                 |
| `<tl-mint-page-721>`        | A mint page for a 1-of-1 / ERC-721 NFT collection.                         |
| `<tl-mint-page-1155>`       | A mint page for an edition / ERC-1155 token.                               |
| `<tl-snr-erc1155tl-raffle>` | "Send and receive" raffle: send tokens in, get a raffle entry.             |
| `<tl-snr-erc1155tl>`        | Send tokens in, receive a fixed ERC-1155 token back.                       |
| `<tl-snr-erc721tl>`         | Send tokens in, receive a freshly minted ERC-721 NFT back (with a reveal). |
| `<tl-snr-currency>`         | Send currency in, redeem according to the contract's rules.                |

### Usage

Use in any webpage!

#### 1. Configure and load (in the `<head>`)

`window.tlConfig` is optional — every field has a sensible default — but setting `appName` and a `walletConnectProjectId` is recommended for a polished wallet flow.

```
<head>
  <script>
    window.tlConfig = {
      mode: "light",                          // "light" or "dark"
      appName: "My Cool App",                 // shown in the wallet connect dialog
      appDescription: "My cool app's description",
      walletConnectProjectId: "wallet-connect-id",
      testnet: false,                         // set true to use test networks (Sepolia, etc.)

      // Optional: override the default RPC URL per chain. Any you leave out use
      // the public default shown below. Testnet keys are only used when testnet: true.
      rpcUrls: {
        // Mainnets
        ethereum: "",       // defaults to https://ethereum-rpc.publicnode.com
        shape: "",          // defaults to https://mainnet.shape.network
        base: "",           // defaults to https://base-rpc.publicnode.com
        arbitrum: "",       // defaults to https://arbitrum-one-rpc.publicnode.com
        // Testnets (used when testnet: true)
        sepolia: "",        // defaults to https://ethereum-sepolia-rpc.publicnode.com
        shapeSepolia: "",   // defaults to https://sepolia.shape.network
        baseSepolia: "",    // defaults to https://base-sepolia-rpc.publicnode.com
        arbitrumSepolia: "" // defaults to https://arbitrum-sepolia-rpc.publicnode.com
      }
    }
  </script>
  <script type="module" src="https://cdn.transientlabs.xyz/embeds/v1.9.0/index.js"></script>
  <link rel="stylesheet" href="https://cdn.transientlabs.xyz/embeds/v1.9.0/index.css">
</head>
```

#### 2. Add the elements you want (in the `<body>`)

Each element is configured with HTML attributes (`chain-id`, `contract-address`, etc.). Use only the elements you need — you don't have to include all of them.

```
<body>
  <style>
    /* add any style overrides here*/
  </style>
  <!-- Omit any of the components you don't need below -->
  <tl-connect-button variant="default"></tl-connect-button>

  <tl-siwe-button chain-id="1" site-name="My Site name" terms-url="https://my-site.com/terms"></tl-siwe-button>

  <tl-auction chain-id="1" contract-address="0x2b4b2d47c8db371b006e3df14245c12193a185dc" token-id="1"
    auction-house-address="0x6f66b95a0c512f3497fb46660e0bc3b94b989f8d" refresh-interval="10000"></tl-auction>

  <tl-mint-page-721 chain-id="1" contract-address="0xb38bd444399cd76c3f91aa2455052834e3451911"
    mint-contract-address="0x384092784cfaa91efaa77870c04d958e20840242"
    allowlist-url="https://dv0xp0uwyoh8r.cloudfront.net/stacks/c8aeee8f-7d14-4403-a8b2-fe06f97a79cc/allowlist"
    slug="shape-study" refresh-interval="10000"></tl-mint-page-721>

  <tl-mint-page-1155 chain-id="1" contract-address="0xb38bd444399cd76c3f91aa2455052834e3451911" token-id="1"
    mint-contract-address="0x32953d7ae37b05075b88c34e800ae80c1cb1b794"
    allowlist-url="https://dv0xp0uwyoh8r.cloudfront.net/stacks/c8aeee8f-7d14-4403-a8b2-fe06f97a79cc/allowlist"
    slug="shape-study" refresh-interval="10000"></tl-mint-page-1155>

  <tl-snr-erc1155tl-raffle chain-id="1" raffle-contract-address="0xE9D8123BF045158B2b7608Cc48A4562770246902"
    refresh-interval="5000"></tl-snr-erc1155tl-raffle>

  <tl-snr-erc1155tl chain-id="1" contract-address="0x98d90d88632fEB8b6fF509c5bE4c598174Cd2A14"
    input-contract-address="0xa9e448617188458ff7e2e9ef31596494f7a8ac68" input-token-id="1"
    refresh-interval="5000"></tl-snr-erc1155tl>

  <tl-snr-erc721tl chain-id="1" contract-address="0x98d90d88632fEB8b6fF509c5bE4c598174Cd2A14"
    input-contract-address="0xa9e448617188458ff7e2e9ef31596494f7a8ac68" input-token-id="1"
    refresh-interval="5000"></tl-snr-erc721tl>

  <tl-snr-currency chain-id="1" contract-address="0xe08B3174D495E04491f9Dd8Ae3d684564A95710C"
    refresh-interval="5000"></tl-snr-currency>
</body>
```

### Component Inputs

Use kebab-case attributes in HTML. For example, the React prop `chainId` is the HTML attribute `chain-id`, and `contractAddress` is `contract-address`.

Boolean attributes should be set explicitly, for example `view-on-transient="false"`. Number inputs are parsed from their attribute values.

#### `<tl-connect-button>`

| Attribute | Type   | Required | Default   | Description                                                                                 |
| --------- | ------ | -------- | --------- | ------------------------------------------------------------------------------------------- |
| `variant` | string | No       | `default` | Button style variant: `default`, `destructive`, `outline`, `secondary`, `ghost`, or `link`. |

#### `<tl-siwe-button>`

| Attribute      | Type   | Required | Default          | Description                                                                                                                                  |
| -------------- | ------ | -------- | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| `chain-id`     | number | Yes      | -                | Chain ID to use for the SIWE message and signature flow.                                                                                     |
| `site-name`    | string | Yes      | -                | Site name shown in the SIWE message.                                                                                                         |
| `terms-url`    | string | Yes      | -                | Terms URL included in the SIWE message.                                                                                                      |
| `nonce-source` | string | No       | block hash nonce | Set to `transient` to fetch a nonce from the Transient API. Otherwise the nonce is derived locally from the latest block and wallet address. |

#### `<tl-auction>`

| Attribute               | Type    | Required | Default | Description                                   |
| ----------------------- | ------- | -------- | ------- | --------------------------------------------- |
| `chain-id`              | number  | Yes      | -       | Chain ID where the auction contracts live.    |
| `contract-address`      | address | Yes      | -       | NFT contract address.                         |
| `token-id`              | number  | Yes      | -       | Token ID being auctioned.                     |
| `auction-house-address` | address | Yes      | -       | Auction house contract address.               |
| `refresh-interval`      | number  | Yes      | -       | Polling interval in milliseconds.             |
| `view-on-transient`     | boolean | No       | `true`  | Whether to show the "View on Transient" link. |

#### `<tl-mint-page-721>`

| Attribute               | Type    | Required | Default | Description                                                |
| ----------------------- | ------- | -------- | ------- | ---------------------------------------------------------- |
| `chain-id`              | number  | Yes      | -       | Chain ID where the mint contracts live.                    |
| `contract-address`      | address | Yes      | -       | ERC-721 collection contract address.                       |
| `mint-contract-address` | address | Yes      | -       | Mint contract address.                                     |
| `allowlist-url`         | string  | Yes      | -       | URL for allowlist data used during presale checks.         |
| `slug`                  | string  | Yes      | -       | Transient collection or drop slug used for external links. |
| `refresh-interval`      | number  | Yes      | -       | Polling interval in milliseconds.                          |
| `view-on-transient`     | boolean | No       | `true`  | Whether to show the "View on Transient" link.              |

#### `<tl-mint-page-1155>`

| Attribute               | Type    | Required | Default | Description                                                |
| ----------------------- | ------- | -------- | ------- | ---------------------------------------------------------- |
| `chain-id`              | number  | Yes      | -       | Chain ID where the mint contracts live.                    |
| `contract-address`      | address | Yes      | -       | ERC-1155 collection contract address.                      |
| `token-id`              | number  | Yes      | -       | ERC-1155 token ID to mint.                                 |
| `mint-contract-address` | address | Yes      | -       | Mint contract address.                                     |
| `allowlist-url`         | string  | Yes      | -       | URL for allowlist data used during presale checks.         |
| `slug`                  | string  | Yes      | -       | Transient collection or drop slug used for external links. |
| `refresh-interval`      | number  | Yes      | -       | Polling interval in milliseconds.                          |
| `view-on-transient`     | boolean | No       | `true`  | Whether to show the "View on Transient" link.              |

#### `<tl-snr-erc1155tl-raffle>`

| Attribute                 | Type    | Required | Default | Description                               |
| ------------------------- | ------- | -------- | ------- | ----------------------------------------- |
| `chain-id`                | number  | Yes      | -       | Chain ID where the raffle contract lives. |
| `raffle-contract-address` | address | Yes      | -       | Send-and-receive raffle contract address. |
| `refresh-interval`        | number  | Yes      | -       | Polling interval in milliseconds.         |

#### `<tl-snr-erc1155tl>`

| Attribute                | Type    | Required | Default | Description                                   |
| ------------------------ | ------- | -------- | ------- | --------------------------------------------- |
| `chain-id`               | number  | Yes      | -       | Chain ID where the redemption contract lives. |
| `contract-address`       | address | Yes      | -       | Send-and-receive redemption contract address. |
| `input-contract-address` | address | Yes      | -       | ERC-1155 token contract users send in.        |
| `input-token-id`         | number  | Yes      | -       | ERC-1155 token ID users send in.              |
| `refresh-interval`       | number  | Yes      | -       | Polling interval in milliseconds.             |

#### `<tl-snr-erc721tl>`

| Attribute                | Type    | Required | Default | Description                                   |
| ------------------------ | ------- | -------- | ------- | --------------------------------------------- |
| `chain-id`               | number  | Yes      | -       | Chain ID where the redemption contract lives. |
| `contract-address`       | address | Yes      | -       | Send-and-receive redemption contract address. |
| `input-contract-address` | address | Yes      | -       | ERC-721 token contract users send in.         |
| `input-token-id`         | number  | Yes      | -       | ERC-721 token ID users send in.               |
| `refresh-interval`       | number  | Yes      | -       | Polling interval in milliseconds.             |

#### `<tl-snr-currency>`

| Attribute          | Type    | Required | Default | Description                                            |
| ------------------ | ------- | -------- | ------- | ------------------------------------------------------ |
| `chain-id`         | number  | Yes      | -       | Chain ID where the redemption contract lives.          |
| `contract-address` | address | Yes      | -       | Send-and-receive currency redemption contract address. |
| `refresh-interval` | number  | Yes      | -       | Polling interval in milliseconds.                      |

### Lazy Loading

Embeds lazy-mount by default. Each element first renders a lightweight placeholder, then mounts the full React/Web3 component when it enters the viewport. Blockchain reads and polling do not start until that mount happens.

After an embed mounts once, it stays mounted even if the user scrolls away. This keeps wallet state, open dialogs, form input, and cached query data stable. It also means polling continues for embeds that have already been viewed.

The bundled stylesheet sets all `<tl-...>` custom elements to `display: block` so they behave like normal page sections and reserve predictable layout space. Keep the stylesheet loaded, or add equivalent host-page CSS if you are replacing the default styles.

### Style Overrides

You need to add the style overrides in the body

The components are built with tailwindcss v4 and Shadcn/ui. You'll override css variables for main colors and style. There are also classes that you can override for more control (advanced).

CSS Variables:

```
:root {
  --radius: 0.5rem;
  --title-font: "Inter";
  --body-font: "Inter";
  --mono-font: "Roboto Mono";
  --border-width: 2px;
  --background: oklch(1 0 0);
  --foreground: oklch(0.141 0.005 285.823);
  --card: oklch(1 0 0);
  --card-foreground: oklch(0.141 0.005 285.823);
  --popover: oklch(1 0 0);
  --popover-foreground: oklch(0.141 0.005 285.823);
  --primary: oklch(0.21 0.006 285.885);
  --primary-foreground: oklch(0.985 0 0);
  --secondary: oklch(0.967 0.001 286.375);
  --secondary-foreground: oklch(0.21 0.006 285.885);
  --muted: oklch(0.967 0.001 286.375);
  --muted-foreground: oklch(0.552 0.016 285.938);
  --accent: oklch(0.967 0.001 286.375);
  --accent-foreground: oklch(0.21 0.006 285.885);
  --destructive: oklch(0.577 0.245 27.325);
  --border: oklch(0.21 0.006 285.885);
  --input: oklch(0.92 0.004 286.32);
  --dialog: oklch(0.21 0.006 285.885);
  --ring: oklch(0.705 0.015 286.067);
  --chart-1: oklch(0.646 0.222 41.116);
  --chart-2: oklch(0.6 0.118 184.704);
  --chart-3: oklch(0.398 0.07 227.392);
  --chart-4: oklch(0.828 0.189 84.429);
  --chart-5: oklch(0.769 0.188 70.08);
  --sidebar: oklch(0.985 0 0);
  --sidebar-foreground: oklch(0.141 0.005 285.823);
  --sidebar-primary: oklch(0.21 0.006 285.885);
  --sidebar-primary-foreground: oklch(0.985 0 0);
  --sidebar-accent: oklch(0.967 0.001 286.375);
  --sidebar-accent-foreground: oklch(0.21 0.006 285.885);
  --sidebar-border: oklch(0.92 0.004 286.32);
  --sidebar-ring: oklch(0.705 0.015 286.067);
}

.dark {
  --background: oklch(0.141 0.005 285.823);
  --foreground: oklch(0.985 0 0);
  --card: oklch(0.21 0.006 285.885);
  --card-foreground: oklch(0.985 0 0);
  --popover: oklch(0.21 0.006 285.885);
  --popover-foreground: oklch(0.985 0 0);
  --primary: oklch(0.92 0.004 286.32);
  --primary-foreground: oklch(0.21 0.006 285.885);
  --secondary: oklch(0.274 0.006 286.033);
  --secondary-foreground: oklch(0.985 0 0);
  --muted: oklch(0.274 0.006 286.033);
  --muted-foreground: oklch(0.705 0.015 286.067);
  --accent: oklch(0.274 0.006 286.033);
  --accent-foreground: oklch(0.985 0 0);
  --destructive: oklch(0.704 0.191 22.216);
  --border: oklch(0.985 0 0);
  --input: oklch(1 0 0 / 15%);
  --dialog: oklch(0.985 0 0);
  --ring: oklch(0.552 0.016 285.938);
  --chart-1: oklch(0.488 0.243 264.376);
  --chart-2: oklch(0.696 0.17 162.48);
  --chart-3: oklch(0.769 0.188 70.08);
  --chart-4: oklch(0.627 0.265 303.9);
  --chart-5: oklch(0.645 0.246 16.439);
  --sidebar: oklch(0.21 0.006 285.885);
  --sidebar-foreground: oklch(0.985 0 0);
  --sidebar-primary: oklch(0.488 0.243 264.376);
  --sidebar-primary-foreground: oklch(0.985 0 0);
  --sidebar-accent: oklch(0.274 0.006 286.033);
  --sidebar-accent-foreground: oklch(0.985 0 0);
  --sidebar-border: oklch(1 0 0 / 10%);
  --sidebar-ring: oklch(0.552 0.016 285.938);
}
```

Custom Class Overrides:

```
.tl-root
.tl-lazy-placeholder
.tl-address-display
.tl-dialog-overlay
.tl-dialog-content
.tl-dialog-header
.tl-dialog-footer
.tl-dialog-title
.tl-dialog-description
.tl-dialog-action
.tl-dialog-cancel
.tl-dialog-close
.tl-input
.tl-title-3
.tl-title-4
.tl-paragraph
.tl-caption
.tl-button-default
.tl-button-destructive
.tl-button-outline
.tl-button-secondary
.tl-button-ghost
.tl-button-link
.tl-button-size-default
.tl-button-size-sm
.tl-button-size-lg
.tl-button-size-icon
.tl-toaster
.tl-countdown-root
.tl-countdown-text-group
.tl-countdown-label
.tl-countdown-time
.tl-tx-dialog-title
.tl-tx-dialog-root
.tl-tx-dialog-spinner
.tl-tx-dialog-text
.tl-wrapper
.tl-connect-button
.tl-siwe-button
.tl-siwe-connect-button
.tl-auction-root
.tl-auction-top-section
.tl-auction-price-label
.tl-auction-price-display
.tl-auction-highest-bidder-section
.tl-auction-highest-bidder-display
.tl-auction-button-group
.tl-auction-submit-bid-button
.tl-auction-buy-now-button
.tl-auction-settle-button
.tl-auction-connect-button
.tl-auction-duration-caption
.tl-auction-bottom-text-section
.tl-auction-view-on-transient-text
.tl-auction-bids-caption
.tl-auction-history-title
.tl-auction-history-group
.tl-auction-history-bid
.tl-auction-history-list-entry
.tl-auction-history-cancel-entry
.tl-auction-history-bid-entry
.tl-auction-history-settle-entry
.tl-auction-history-buy-now-entry
.tl-auction-empty-state-container
.tl-auction-bid-title
.tl-auction-bid-root
.tl-auction-bid-input-group
.tl-auction-bid-input
.tl-auction-bid-button
.tl-auction-min-bid
.tl-mint-root
.tl-mint-top-section
.tl-mint-phase
.tl-mint-supply
.tl-mint-middle-section
.tl-mint-middle-left-section
.tl-mint-allowance-caption
.tl-mint-price-caption
.tl-mint-price
.tl-mint-protocol-fee-caption
.tl-mint-middle-right-section
.tl-mint-bottom-section
.tl-mint-button
.tl-mint-connect-button
.tl-mint-recipient-section
.tl-mint-recipient-display
.tl-mint-to-other-button
.tl-mint-disabled-text
.tl-mint-recipient-dialog
.tl-mint-recipient-input
.tl-mint-save-recipient
.tl-mint-success-dialog-root
.tl-mint-recipient-dialog
.tl-mint-success-token-root
.tl-mint-success-token-image
.tl-mint-success-token-placeholder
.tl-mint-success-token-text
.tl-mint-success-token-title
.tl-mint-success-view-on-opensea-text
.tl-mint-success-loading-text
.tl-mint-view-on-transient-text
.tl-snr-root
.tl-snr-redemption-data-container
.tl-snr-user-data-container
.tl-snr-connect-button
.tl-snr-section-title
.tl-snr-data-span
.tl-snr-link
.tl-snr-counter-container
.tl-snr-actions-container
.tl-snr-redemption-disabled-text
.tl-snr-action-button
.tl-snr-success-dialog-root
.tl-snr-success-dialog
.tl-snr-success-token-root
.tl-snr-success-token-image
.tl-snr-success-token-text
.tl-snr-success-token-title
.tl-snr-success-view-on-opensea-text
.tl-snr-success-loading-text
```

### Custom Events

The components dispatch events on `document` so you can hook in your own logic (analytics, confirmations, redirects, etc.). Each event carries its data on the standard `event.detail` field:

```
document.addEventListener("tl-mint-721", (event) => {
  console.log("Minted!", event.detail);
  // e.g. { sender, chainId, contractAddress, logs }
});
```

Wallet status is also exposed as a global snapshot for synchronous checks, including after page refresh/reconnect flows:

```
window.tlWallet?.isConnected;
window.tlWallet?.address;
window.tlWallet?.chainId;
window.tlWallet?.status;
```

`window.tlWallet` is updated from the shared Wagmi account state whenever an embed with Web3 support mounts and whenever the wallet status, address, or chain changes. It is a snapshot, so read it again when you need the latest value.

The snapshot shape is:

```
type TLWalletStatus = {
  status: "connected" | "connecting" | "reconnecting" | "disconnected";
  isConnected: boolean;
  address?: `0x${string}`;
  chainId?: number;
};
```

For refresh-safe integrations, read the current snapshot once and then listen for future changes:

```
function handleWalletStatus(wallet) {
  if (!wallet?.isConnected) {
    console.log("No wallet connected");
    return;
  }

  console.log("Connected wallet:", wallet.address);
  console.log("Connected chain:", wallet.chainId);
}

handleWalletStatus(window.tlWallet);

document.addEventListener("tl-wallet-status-change", (event) => {
  handleWalletStatus(event.detail);
});
```

The legacy `tl-wallet-connect` and `tl-wallet-disconnect` events are still emitted for compatibility. Prefer `window.tlWallet` plus `tl-wallet-status-change` when your page needs to know the current wallet state after a refresh, reconnect, account switch, or chain switch.

| Event                           | Fired when                               | `event.detail` contains                                  |
| ------------------------------- | ---------------------------------------- | -------------------------------------------------------- |
| `tl-wallet-connect`             | A wallet connects                        | `address`                                                |
| `tl-wallet-disconnect`          | A wallet disconnects                     | *(none)*                                                 |
| `tl-wallet-status-change`       | Wallet status, address, or chain changes | `status, isConnected, address?, chainId?`                |
| `tl-auction-bid`                | A bid is placed                          | `sender, chainId, contractAddress, tokenId, listing?`    |
| `tl-buy-now`                    | An item is bought now                    | `sender, chainId, contractAddress, tokenId, listing?`    |
| `tl-auction-settle`             | An auction is settled                    | `sender, chainId, contractAddress, tokenId, listing?`    |
| `tl-mint-721`                   | An ERC-721 is minted                     | `sender, chainId, contractAddress, logs`                 |
| `tl-mint-1155`                  | An ERC-1155 is minted                    | `sender, chainId, contractAddress, tokenId`              |
| `tl-siwe`                       | A user signs in with Ethereum            | `message, signature`                                     |
| `tl-snr-erc1155tl-raffle-entry` | A raffle entry is submitted              | `sender, chainId, raffleContractAddress`                 |
| `tl-snr-erc1155tl-raffle-claim` | A raffle prize is claimed                | `sender, chainId, raffleContractAddress, isWinner`       |
| `tl-snr-currency-redemption`    | A currency redemption succeeds           | `sender, chainId, contractAddress, numRedemptions`       |
| `tl-snr-erc1155tl-redemption`   | An ERC-1155 redemption succeeds          | `sender, chainId, contractAddress, numRedemptions`       |
| `tl-snr-erc721tl-redemption`    | An ERC-721 redemption succeeds           | `sender, chainId, contractAddress, numRedemptions, logs` |
