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

# Leaderboard Page

> Interactive preview for the @agg-build/ui LeaderboardPage surface

export const StorybookEmbed = ({storyId, title = "Storybook preview", height = 320, baseUrl = "https://storybook.agg.market"}) => {
  const resolvedHeight = typeof height === "number" ? `${height}px` : height;
  const normalizedBaseUrl = baseUrl.endsWith("/") ? baseUrl.slice(0, -1) : baseUrl;
  const buildStorybookUrls = theme => {
    const iframeSearchParams = new URLSearchParams({
      id: storyId,
      viewMode: "story",
      singleStory: "true",
      shortcuts: "false",
      globals: `theme:${theme}`
    });
    const storybookSearchParams = new URLSearchParams({
      path: `/story/${storyId}`,
      globals: `theme:${theme}`
    });
    return {
      iframeSrc: `${normalizedBaseUrl}/iframe.html?${iframeSearchParams.toString()}`,
      storybookUrl: `${normalizedBaseUrl}/?${storybookSearchParams.toString()}`
    };
  };
  const lightUrls = buildStorybookUrls("light");
  const darkUrls = buildStorybookUrls("dark");
  return <div className="not-prose my-6 overflow-hidden rounded-2xl border border-zinc-200 bg-white dark:border-zinc-800 dark:bg-zinc-950">
      <div className="flex items-center justify-between gap-4 border-b border-zinc-200 px-4 py-3 dark:border-zinc-800">
        <p className="m-0 min-w-0 text-sm font-semibold text-zinc-900 dark:text-zinc-100">{title}</p>
        <div className="shrink-0">
          <a href={lightUrls.storybookUrl} target="_blank" rel="noreferrer" className="text-sm font-medium text-[#ED8200] hover:opacity-80 dark:hidden">
            Open in Storybook
          </a>
          <a href={darkUrls.storybookUrl} target="_blank" rel="noreferrer" className="hidden text-sm font-medium text-[#ED8200] hover:opacity-80 dark:inline">
            Open in Storybook
          </a>
        </div>
      </div>

      <iframe src={lightUrls.iframeSrc} title={`${title} light`} loading="lazy" className="block w-full border-0 bg-transparent dark:hidden" style={{
    height: resolvedHeight
  }} />
      <iframe src={darkUrls.iframeSrc} title={`${title} dark`} loading="lazy" className="hidden w-full border-0 bg-transparent dark:block" style={{
    height: resolvedHeight
  }} />
    </div>;
};

# Leaderboard Page

`LeaderboardPage` ranks your app's traders by realized P\&L or volume over a preset period
(24h, 7d, 30d, all time). Identity fields (username, avatar, wallet) follow the app's
`leaderboardIdentity` setting, which defaults to anonymous.

Use Storybook as the source of truth for controls, layout states, and composition details.

## Import

```tsx theme={null}
import "@agg-build/ui/styles.css";
import { LeaderboardPage } from "@agg-build/ui/pages";
```

Requires `<AggProvider>` from `@agg-build/hooks`.

## Props

| Prop                                                                       | Description                                                          |
| -------------------------------------------------------------------------- | -------------------------------------------------------------------- |
| `period`, `onPeriodChange`                                                 | Controlled preset: `"1d" \| "7d" \| "30d" \| "all"`                  |
| `metric`, `onMetricChange`                                                 | Controlled sort: `"realizedPnl" \| "volume"`                         |
| `rows`, `isLoading`, `error`, `hasNextPage`, `onLoadMore`, `isLoadingMore` | Supply your own data instead of the built-in `useLeaderboard` hook   |
| `currentUserId`                                                            | Row to highlight as "You" (defaults to the signed-in user)           |
| `appName`                                                                  | Shown in the subtitle                                                |
| `onError`                                                                  | Called with render errors caught by the page's error boundary        |
| `className`                                                                | Extra classes on the root element                                    |
| `classNames`                                                               | Slot overrides: `root`, `header`, `toolbar`, `list`, `row`, `footer` |

P\&L is realized only (sells and settled markets, before fees) and refreshes every 5 minutes. Each row
carries `volume` (buys and sells) and `spent` (buys only), so you can show either.

## Preview

<StorybookEmbed storyId="pages-leaderboard-page--playground" title="Leaderboard Page" height={900} />
