Superbridge
Start typing to search...
You need a Rollie to use the Superbridge Widget.

Guides

Embedding

Size the widget, order its stylesheet, and choose where its modals open

<Widget /> drops into a page and works. This page is about the three things a host decides around it: how much room it gets, where its stylesheet sits, and where its modals open.

Size and position

The widget renders at its natural height and fills the width of its container, up to 540px — beyond that it centres itself. Narrow viewports get the full width with a small gutter.

Everything outside that is yours: viewport height, vertical rhythm, whether it sits in a card.

<div className="mx-auto max-w-lg py-24">
  <Widget />
</div>
<div className="rounded-xl border p-4">
  <Widget />
</div>

The widget never sets page height and never scrolls the page for you. If you want it centred in the viewport, centre it in the viewport.

Don't give the widget a container narrower than about 440px. Its modals are up to 440px wide, and in the default (scoped) overlay mode they render inside the widget's own box — a narrower container clips them. See popouts and panels.

The stylesheet

import "@superbridge/widget/styles.css";

Every rule in it is scoped to the widget's own root, so nothing in the stylesheet can match your markup.

One ordering rule remains. The scoped rules can't reach you, but the theme variables the stylesheet declares are global by necessity — the widget itself has to resolve them wherever it renders, including in a portal outside its own tree. Those live on :root, and some of the names are ones your own Tailwind theme also uses. Link the widget's stylesheet before your own and your values win. How you express "before" is the part that differs:

// src/main.tsx
import "@superbridge/widget/styles.css";
import "./index.css";

createRoot(document.getElementById("root")).render(<App />);

A bare side-effect import is enough wherever your bundler controls the order of the emitted CSS. Server-rendered frameworks that build the document head themselves need the URL form, or the first paint arrives unstyled. Integration covers each one, including React Router and Astro.

Where modals open

The widget's token pickers, wallet picker, settings and activity views are modals, and they render into a portal. Which portal is the one decision here, and it changes what the user sees:

DefaultWith portalTarget
PortalThe widget creates one inside its own boxThe element you pass
Positioningabsolute — confined to the widgetfixed — over the whole viewport
Rest of your pageStays visible and interactiveCovered by the backdrop
FitsEmbedded panels, popouts, dashboardsApps whose own modals are full-screen

Nothing to configure for the default:

<Widget />

For full-screen overlays, hand over an element:

function App() {
  const [portalTarget, setPortalTarget] = useState<HTMLDivElement | null>(null);

  return (
    <>
      <Widget portalTarget={portalTarget ?? undefined} />

      <div
        ref={setPortalTarget}
        className="sb-widget pointer-events-none fixed inset-0 z-50"
      />
    </>
  );
}

Three things about that element:

  • It must carry the .sb-widget class. The stylesheet is scoped to it, and your theme.cssVariables are written onto it — without the class, portaled content renders unstyled and untinted.
  • Give it pointer-events-none. It's a full-viewport layer that is empty most of the time; the widget's own backdrop and dialogs re-enable pointer events on themselves.
  • Hold it in state, not a ref. The widget needs the element on the render it reads portalTarget, and a ref assignment doesn't re-render.

Leave it empty — it's a layer, not a container.

Popouts and panels

A launcher button with the widget in a floating panel is the default overlay mode's best case: the modals stay inside the panel, and the page behind it is untouched.

{open ? (
  <div className="fixed bottom-20 right-6 w-[456px] rounded-2xl border bg-white shadow-xl">
    <div className="h-[620px] overflow-y-auto p-2">
      <Widget />
    </div>
  </div>
) : null}

Two measurements matter:

  • Width. Give the panel enough room for a 440px modal plus its own padding. 440px of usable width is the floor; below it, modals clip.
  • Height. The overlays fill the widget's box, so a panel with a fixed height gives them a stable one. A panel sized by its content will resize as the form grows and shrink modals with it.

Multiple widgets

One widget instance per page. The modal store and the active configuration are module-level, so a second instance shares them and the two fight over what's open.