> ## Documentation Index
> Fetch the complete documentation index at: https://docs.yield.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Widget Pro

> Turn on the dashboard layout of @stakekit/widget: Earn by category, Borrow, Manage and Activity in one embedded app.

export const ExpandableDemo = ({src, title, desktopWidth = 1440, desktopHeight = 900, caption}) => {
  const [open, setOpen] = useState(false);
  const [scale, setScale] = useState(0.5);
  const boxRef = useRef(null);
  useEffect(() => {
    const box = boxRef.current;
    if (!box) return undefined;
    const update = () => setScale(Math.min(1, box.clientWidth / desktopWidth));
    update();
    const observer = new ResizeObserver(update);
    observer.observe(box);
    return () => observer.disconnect();
  }, [desktopWidth]);
  const dialogRef = useRef(null);
  const closeRef = useRef(null);
  useEffect(() => {
    const dialog = dialogRef.current;
    if (!dialog) return undefined;
    if (open && !dialog.open) {
      dialog.showModal();
      closeRef.current?.focus();
    }
    if (!open && dialog.open) dialog.close();
    const previousOverflow = document.body.style.overflow;
    if (open) document.body.style.overflow = "hidden";
    return () => {
      document.body.style.overflow = previousOverflow;
    };
  }, [open]);
  return <figure style={{
    margin: "24px 0"
  }}>
      <div ref={boxRef} style={{
    position: "relative",
    width: "100%",
    height: `${Math.round(desktopHeight * scale)}px`,
    overflow: "hidden",
    borderRadius: "16px",
    border: "1px solid rgba(127, 127, 127, 0.25)"
  }}>
        <iframe src={src} title={`${title} (preview)`} width={desktopWidth} height={desktopHeight} loading="lazy" tabIndex={-1} aria-hidden="true" style={{
    border: 0,
    width: `${desktopWidth}px`,
    height: `${desktopHeight}px`,
    transform: `scale(${scale})`,
    transformOrigin: "0 0",
    pointerEvents: "none"
  }} />
        <button type="button" onClick={() => setOpen(true)} aria-label={`Open the ${title} live demo`} style={{
    position: "absolute",
    inset: 0,
    width: "100%",
    height: "100%",
    display: "flex",
    alignItems: "center",
    justifyContent: "center",
    background: "rgba(0, 0, 0, 0.12)",
    border: 0,
    cursor: "pointer"
  }}>
          <span style={{
    padding: "10px 18px",
    borderRadius: "999px",
    background: "#111827",
    color: "#ffffff",
    fontSize: "15px",
    fontWeight: 600,
    boxShadow: "0 4px 16px rgba(0, 0, 0, 0.25)"
  }}>
            Open live demo
          </span>
        </button>
      </div>
      <figcaption style={{
    marginTop: "8px",
    fontSize: "14px",
    opacity: 0.75,
    textAlign: "center"
  }}>
        {caption ? `${caption} ` : ""}
        <a href={src} target="_blank" rel="noopener noreferrer">
          Open in a new tab
        </a>
      </figcaption>

      <dialog ref={dialogRef} aria-label={title} onClose={() => setOpen(false)} onClick={event => {
    if (event.target === event.currentTarget) setOpen(false);
  }} style={{
    width: "100vw",
    height: "100vh",
    maxWidth: "100vw",
    maxHeight: "100vh",
    margin: 0,
    padding: "24px",
    border: 0,
    background: "rgba(0, 0, 0, 0.75)",
    display: open ? "flex" : "none",
    alignItems: "center",
    justifyContent: "center",
    boxSizing: "border-box"
  }}>
        {open && <div style={{
    position: "relative",
    width: "min(94vw, 1600px)",
    height: "88vh",
    borderRadius: "16px",
    overflow: "hidden",
    background: "#ffffff",
    boxShadow: "0 24px 64px rgba(0, 0, 0, 0.4)"
  }}>
            <iframe src={src} title={title} allow="clipboard-read; clipboard-write" style={{
    border: 0,
    width: "100%",
    height: "100%"
  }} />
            <button ref={closeRef} type="button" onClick={() => setOpen(false)} aria-label="Close the demo" style={{
    position: "fixed",
    top: "8px",
    right: "8px",
    width: "36px",
    height: "36px",
    borderRadius: "999px",
    border: 0,
    background: "#111827",
    color: "#ffffff",
    fontSize: "18px",
    lineHeight: "36px",
    cursor: "pointer"
  }}>
              ✕
            </button>
          </div>}
      </dialog>
    </figure>;
};

Widget Pro is the dashboard layout of the [yield widget](/guides/widgets-dashboard/yield-widget). It is the same `@stakekit/widget` package with one prop, `dashboardVariant`, turned on. Instead of the compact single-flow widget, users get a full app: yields grouped by category, a details pane, positions and activity, and Borrow when you enable it.

<ExpandableDemo src="https://widget-pro.yield.xyz/" title="Widget Pro" caption="Widget Pro with Borrow on." />

## Widget or Widget Pro

| | Yield widget | Widget Pro |
| - | - | - |
| Package | `@stakekit/widget` | `@stakekit/widget` with `dashboardVariant` |
| Layout | Compact, one flow at a time | Full dashboard with a tab bar and a details pane |
| Yields | One list | Grouped by category: Stake, DeFi and RWA |
| Positions and activity | Inside the flow | Manage and Activity tabs |
| Borrow | No | Yes, with `borrowEnabled` |
| Best for | A panel inside an existing page | A standalone Earn and Borrow page in your app |

## Turn it on

Install the widget as described in [Embed the yield widget](/guides/widgets-dashboard/yield-widget#install), then add `dashboardVariant`:

```tsx theme={null}
import "@stakekit/widget/style.css";
import { lightTheme, SKApp } from "@stakekit/widget";

export const WidgetPro = () => (
  <SKApp
    apiKey={YIELD_API_KEY}
    theme={lightTheme}
    dashboardVariant
    borrowEnabled
    institutionalWallets
  />
);
```

The demo uses this configuration. With the browser renderer, pass the same props to `renderSKWidget`.

## What the dashboard adds

* **Tab bar.** The Earn category tabs, then Borrow when it is enabled, then Manage and Activity.
* **Yields by category.** `dashboardVariant` sets `yieldGrouping` to `"category"`. Set `dashboardYieldCategoryOrder` to change the order, for example `["stake", "defi", "rwa"]`; categories you leave out follow in the default order. The `DashboardYieldCategory` export lists the valid values.
* **Details pane.** Selecting a yield, position or activity row opens its details beside the list. On narrow screens the panes collapse into one view.
* **Header.** Shows an account and chain selector. Hide it with `hideAccountAndChainSelector` when your app already shows the connected wallet.
* **Borrow.** Add `borrowEnabled` to show the Borrow tab and Borrow positions. See the [Borrow widget](/guides/borrow/widget) guide for the requirements.

## Common props

| Prop | Use |
| - | - |
| `dashboardVariant` | Turns on the dashboard layout. |
| `borrowEnabled` | Adds Borrow. Read at mount. |
| `institutionalWallets` | Offers institutional wallets instead of the regular wallet list. Read at mount. |
| `validatorsConfig` | Limits validators per network, for example `{ "*": { preferredOnly: true } }` to show only preferred validators everywhere. |
| `dashboardYieldCategoryOrder` | Sets the order of the category tabs. |
| `theme` | Your brand tokens. See [Theming](/guides/widgets-dashboard/yield-widget#theming). |
| `tracking` | Forwards events and page views to your analytics. |

`validatorsConfig` takes a network id, or `"*"` for every network without its own entry:

```ts theme={null}
validatorsConfig?: {
  [network: string]: {
    allowed?: string[];                  // show only these validator addresses
    blocked?: string[];                  // hide these, even when allowed
    preferred?: string[];                // mark these as preferred
    mergePreferredWithDefault?: boolean; // also keep the API's preferred validators (default true)
    preferredOnly?: boolean;             // show only preferred validators (default false)
  };
};
```

Every other prop works as it does in the classic layout; see the [configuration reference](/guides/widgets-dashboard/yield-widget#configuration-reference).

## Theme and analytics

To change a few tokens of a built-in theme, merge your overrides onto it:

```ts theme={null}
import { darkTheme, lightTheme } from "@stakekit/widget";
import merge from "lodash.merge";

export const brandLightTheme = merge(structuredClone(lightTheme), {
  space: { buttonMinHeight: "40px" },
  borderRadius: { baseContract: { primaryButton: "8px" } },
  color: {
    backgroundMuted: "#f5f5f6",
    stakeSectionBackground: "#f5f5f6",
    primaryButtonBackground: "#4A60FF",
    primaryButtonColor: "#FFFFFF",
  },
});

export const brandDarkTheme = merge(structuredClone(darkTheme), {
  color: { primaryButtonBackground: "#4A60FF" },
});
```

Pass `brandLightTheme` or `brandDarkTheme` to `theme` based on your app's color mode.

To send the widget's events to your analytics, pass a `tracking` object:

```ts theme={null}
import type { SKAppProps } from "@stakekit/widget";
import mixpanel from "mixpanel-browser";

export const tracking: SKAppProps["tracking"] = {
  trackEvent: (event, properties) => mixpanel.track(event, properties),
  trackPageView: (page, properties) => mixpanel.track_pageview({ page, ...properties }),
};
```

## Help links

`HelpModal` opens the widget's own help dialogs from any element you choose. Render it as a child of `SKApp`, so it shares the widget's runtime and tracking:

```tsx theme={null}
import { HelpModal, SKApp } from "@stakekit/widget";

<SKApp apiKey={YIELD_API_KEY} dashboardVariant>
  <HelpModal modal={{ type: "whatIsStakeKit" }} customTrigger={<a>What is Yield.xyz?</a>} />
  <HelpModal modal={{ type: "getInTouch" }} customTrigger={<a>Need help or have questions?</a>} />
</SKApp>;
```

## Verify

Open your page and check that:

* The category tabs show your project's yields, matching `GET /v1/yields` for the same API key.
* Connecting a wallet fills Manage with its positions.
* Activity lists past actions.
* With `borrowEnabled`, the Borrow tab lists markets on a Borrow network.

## Next steps

<Columns cols={2}>
  <Card title="Embed the yield widget" icon="code" href="/guides/widgets-dashboard/yield-widget">
    Install, wallets, theming and every prop.
  </Card>

  <Card title="Borrow widget" icon="window-maximize" href="/guides/borrow/widget">
    Requirements and the wallet adapter for Borrow.
  </Card>
</Columns>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.