From 9383ccdf4e6e16e0246ea1c7bc6b954c6d7dcf4b Mon Sep 17 00:00:00 2001 From: MananTank Date: Thu, 18 Dec 2025 18:08:11 +0000 Subject: [PATCH] Portal: Add bridge widget playground links (#8575) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ## PR-Codex overview This PR focuses on updating the `Bridge Widget` to enhance its integration options and improve user experience by adding a live playground feature. It modifies the integration types, updates the code logic, and introduces new UI components for better functionality. ### Detailed summary - Changed `href` in `sidebar.tsx` for the Playground link. - Updated `integrationType` options in `types.ts` to include "react". - Adjusted code language conditions in `code.tsx` based on `integrationType`. - Added `PlayIcon` and `ArticleIconCard` components in multiple `.mdx` files. - Introduced a "Try it out" section in several `.mdx` files for the Playground. - Modified the `Page` component to accept `searchParams` and determine the valid tab. - Enhanced `BridgeWidgetPlayground` to manage URL updates based on the selected integration type. > ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}` ## Summary by CodeRabbit * **New Features** * Playground now supports URL parameters to pre-select integration tabs and keeps the browser URL in sync when switching tabs * React integration tab standardized and labeled consistently with other tabs * **Documentation** * Added "Try it out" call-to-action cards throughout docs linking to the live playground * **Chores** * Sidebar playground link updated to point to the bridge-specific playground URL ✏️ Tip: You can customize this high-level summary in your review settings. --- .../components/bridge-playground.tsx | 32 +++++++++++++++---- .../bridge/bridge-widget/components/code.tsx | 4 +-- .../bridge/bridge-widget/components/types.ts | 2 +- .../src/app/bridge/bridge-widget/page.tsx | 19 +++++++++-- .../app/bridge/bridge-widget/iframe/page.mdx | 20 ++++++++++-- .../src/app/bridge/bridge-widget/page.mdx | 14 ++++++-- .../app/bridge/bridge-widget/react/page.mdx | 14 ++++++-- .../app/bridge/bridge-widget/script/page.mdx | 13 +++++++- apps/portal/src/app/bridge/sidebar.tsx | 2 +- 9 files changed, 99 insertions(+), 21 deletions(-) diff --git a/apps/playground-web/src/app/bridge/bridge-widget/components/bridge-playground.tsx b/apps/playground-web/src/app/bridge/bridge-widget/components/bridge-playground.tsx index f30185f0386..6362d322557 100644 --- a/apps/playground-web/src/app/bridge/bridge-widget/components/bridge-playground.tsx +++ b/apps/playground-web/src/app/bridge/bridge-widget/components/bridge-playground.tsx @@ -19,11 +19,28 @@ const defaultOptions: BridgeWidgetPlaygroundOptions = { }, }; -export function BridgeWidgetPlayground() { +function updatePageUrl(tab: BridgeWidgetPlaygroundOptions["integrationType"]) { + const url = new URL(window.location.href); + if (tab === defaultOptions.integrationType) { + url.searchParams.delete("tab"); + } else { + url.searchParams.set("tab", tab); + } + + window.history.replaceState({}, "", url.toString()); +} + +export function BridgeWidgetPlayground(props: { + defaultTab: "iframe" | "script" | "react" | undefined; +}) { const { theme } = useTheme(); - const [options, setOptions] = - useState(defaultOptions); + const [options, setOptions] = useState(() => { + return { + ...defaultOptions, + integrationType: props.defaultTab || defaultOptions.integrationType, + }; + }); // change theme on global theme change useEffect(() => { @@ -36,6 +53,10 @@ export function BridgeWidgetPlayground() { })); }, [theme]); + useEffect(() => { + updatePageUrl(options.integrationType); + }, [options.integrationType]); + return (
- setOptions({ ...options, integrationType: "component" }), - isActive: options.integrationType === "component", + onClick: () => setOptions({ ...options, integrationType: "react" }), + isActive: options.integrationType === "react", }, ]} /> diff --git a/apps/playground-web/src/app/bridge/bridge-widget/components/code.tsx b/apps/playground-web/src/app/bridge/bridge-widget/components/code.tsx index 6c6f87da978..b09084284fa 100644 --- a/apps/playground-web/src/app/bridge/bridge-widget/components/code.tsx +++ b/apps/playground-web/src/app/bridge/bridge-widget/components/code.tsx @@ -25,7 +25,7 @@ export function CodeGen(props: { options: BridgeWidgetPlaygroundOptions }) {
@@ -36,7 +36,7 @@ function getCode(options: BridgeWidgetPlaygroundOptions) { if (options.integrationType === "script") { return getCode_Script(options); } - if (options.integrationType === "component") { + if (options.integrationType === "react") { return getCode_ReactComponent(options); } if (options.integrationType === "iframe") { diff --git a/apps/playground-web/src/app/bridge/bridge-widget/components/types.ts b/apps/playground-web/src/app/bridge/bridge-widget/components/types.ts index 427549e17be..23d6ac65472 100644 --- a/apps/playground-web/src/app/bridge/bridge-widget/components/types.ts +++ b/apps/playground-web/src/app/bridge/bridge-widget/components/types.ts @@ -5,7 +5,7 @@ import type { } from "thirdweb/react"; export type BridgeWidgetPlaygroundOptions = { - integrationType: "script" | "component" | "iframe"; + integrationType: "iframe" | "script" | "react"; theme: { type: "dark" | "light"; darkColorOverrides: ThemeOverrides["colors"]; diff --git a/apps/playground-web/src/app/bridge/bridge-widget/page.tsx b/apps/playground-web/src/app/bridge/bridge-widget/page.tsx index 526b6be2a0b..157961cc634 100644 --- a/apps/playground-web/src/app/bridge/bridge-widget/page.tsx +++ b/apps/playground-web/src/app/bridge/bridge-widget/page.tsx @@ -8,6 +8,9 @@ const title = "Bridge Widget"; const description = "Easily embed cross-chain token swap and fiat onramp UI into your app"; +const validTabs = ["iframe", "script", "react"] as const; +type ValidTabs = (typeof validTabs)[number]; + export const metadata = createMetadata({ description: description, title, @@ -17,7 +20,19 @@ export const metadata = createMetadata({ }, }); -export default function Page() { +export default async function Page(props: { + searchParams: Promise<{ + tab?: string | undefined | string[]; + }>; +}) { + const searchParams = await props.searchParams; + const tab = + typeof searchParams.tab === "string" ? searchParams.tab : undefined; + + const validTab = validTabs.includes(tab as ValidTabs) + ? (tab as ValidTabs) + : undefined; + return ( - + ); diff --git a/apps/portal/src/app/bridge/bridge-widget/iframe/page.mdx b/apps/portal/src/app/bridge/bridge-widget/iframe/page.mdx index a1c538b47fe..9e74e17f9bc 100644 --- a/apps/portal/src/app/bridge/bridge-widget/iframe/page.mdx +++ b/apps/portal/src/app/bridge/bridge-widget/iframe/page.mdx @@ -1,12 +1,17 @@ +import bridgeWidgetDark from "../bridge-widget-dark.png"; +import bridgeWidgetLight from "../bridge-widget-light.png"; import { + Tabs, + TabsList, + TabsTrigger, + TabsContent, + ArticleIconCard, Details, createMetadata, DocImage } from "@doc"; -import bridgeWidgetDark from "../bridge-widget-dark.png"; -import bridgeWidgetLight from "../bridge-widget-light.png"; -import { Tabs, TabsList, TabsTrigger, TabsContent } from "@doc"; import { IframeCodePreview } from "./iframe-code-preview"; +import { PlayIcon } from "lucide-react"; export const metadata = createMetadata({ image: { @@ -42,6 +47,15 @@ The Bridge widget iframe makes it easy to embed cross-chain swaps and fiat onram +## Try it out + + + ## Options You can customize theme, currencies, token selections etc using query parameters as mentioned below diff --git a/apps/portal/src/app/bridge/bridge-widget/page.mdx b/apps/portal/src/app/bridge/bridge-widget/page.mdx index 84c413117c8..1b79c919cb6 100644 --- a/apps/portal/src/app/bridge/bridge-widget/page.mdx +++ b/apps/portal/src/app/bridge/bridge-widget/page.mdx @@ -6,7 +6,7 @@ import { import bridgeWidgetDark from "./bridge-widget-dark.png"; import bridgeWidgetLight from "./bridge-widget-light.png"; import { ArticleIconCard, Grid } from "@doc"; -import { CodeIcon, FrameIcon } from "lucide-react"; +import { CodeIcon, FrameIcon, PlayIcon } from "lucide-react"; import { ReactIcon } from "@/icons"; export const metadata = createMetadata({ @@ -58,4 +58,14 @@ You can integrate the bridge widget into your website using an iframe, a script href="/bridge/bridge-widget/react" /> - \ No newline at end of file + + + +## Try it out + + \ No newline at end of file diff --git a/apps/portal/src/app/bridge/bridge-widget/react/page.mdx b/apps/portal/src/app/bridge/bridge-widget/react/page.mdx index a7ea3d25ac9..66e39fa82b4 100644 --- a/apps/portal/src/app/bridge/bridge-widget/react/page.mdx +++ b/apps/portal/src/app/bridge/bridge-widget/react/page.mdx @@ -1,13 +1,12 @@ import { - Details, + ArticleIconCard, createMetadata, DocImage } from "@doc"; import bridgeWidgetDark from "../bridge-widget-dark.png"; import bridgeWidgetLight from "../bridge-widget-light.png"; -import { Tabs, TabsList, TabsTrigger, TabsContent } from "@doc"; +import { PlayIcon } from "lucide-react"; import { ReactIcon } from "@/icons"; -import { ArticleIconCard } from "@doc"; export const metadata = createMetadata({ image: { @@ -80,4 +79,13 @@ function Example() { description="View the API reference for the BridgeWidget component" icon={ReactIcon} href="/references/typescript/v5/BridgeWidget" +/> + +## Try it out + + \ No newline at end of file diff --git a/apps/portal/src/app/bridge/bridge-widget/script/page.mdx b/apps/portal/src/app/bridge/bridge-widget/script/page.mdx index 6073fbe374a..e2fe352e1df 100644 --- a/apps/portal/src/app/bridge/bridge-widget/script/page.mdx +++ b/apps/portal/src/app/bridge/bridge-widget/script/page.mdx @@ -1,10 +1,12 @@ import { - Details, + ArticleIconCard, + Details, createMetadata, DocImage } from "@doc"; import bridgeWidgetDark from "../bridge-widget-dark.png"; import bridgeWidgetLight from "../bridge-widget-light.png"; +import { PlayIcon } from "lucide-react"; export const metadata = createMetadata({ image: { @@ -56,6 +58,15 @@ The Bridge widget script makes it easy to embed cross-chain swaps and fiat onram ``` +## Try it out + + + ## Options diff --git a/apps/portal/src/app/bridge/sidebar.tsx b/apps/portal/src/app/bridge/sidebar.tsx index c22773d8a17..dc3aa31478a 100644 --- a/apps/portal/src/app/bridge/sidebar.tsx +++ b/apps/portal/src/app/bridge/sidebar.tsx @@ -13,7 +13,7 @@ export const sidebar: SideBar = { icon: , }, { - href: "https://playground.thirdweb.com", + href: "https://playground.thirdweb.com/bridge", name: "Playground", icon: , },