Top X

Multi-game football score-prediction tournament with a multi-tab interface: Play, Leaderboard, Private Leagues, Rules, and Prizes. Matches are grouped into discrete games each with its own cutoff, golden-goal tiebreaker, and settlement. Includes consent gating, custom Play-tab banners, countdown timer, and first-class Betslip integration.

Import

import { TopX } from "fansunited-frontend-components";
import {
  TopXProps,
  TopXTab,
  TopXBetslipConfig,
  PlayTabBanner,
  ConsentDef,
} from "fansunited-frontend-core";

Required props

PropTypeDescription
entityIdstringTopX template identifier.
sdkFansUnitedSDKModelSDK instance.
languageLanguageTypeDisplay language.

TopX does not take a template prop — its layout is a fixed multi-tab interface.

Optional props

PropTypeDefaultDescription
themeOptionsCustomThemeOptionsSee Theming.
userIsLoggedInbooleanfalseHost auth state.
signInCTASignInCTADetailsSee Sign-in CTA.
tabsTopXTab[]all tabsWhich tabs to enable.
defaultImagePlaceholderUrlstringFallback image URL for the hero header.
playTabBannersPlayTabBanner[]Custom banners injected into the Play tab.
consentsConsentDef[]Consent definitions required before predicting.
matchCardBgImageUrlstringBackground image URL for match prediction cards.
showCountdownbooleantrueShow the kickoff countdown timer on match cards for open games.
betslipTopXBetslipConfigBetslip integration. See below.

Tabs

type TopXTab = "play" | "leaderboard" | "private-leagues" | "rules" | "prizes";
TabDescription
playMain prediction interface — browse games by day and submit score forecasts.
leaderboardGlobal rankings with pagination and user highlight.
private-leaguesCreate and join private leagues.
rulesSearchable game rules and scoring system.
prizesPrize distribution and rewards.

Pass tabs to limit the visible tabs:

<TopX {...otherProps} tabs={["play", "leaderboard"]} />

Play tab banners

Inject custom React content into specific slots inside the Play tab.

type PlayTabBannerPosition =
  | "above-group-nav"
  | "below-group-nav"
  | "below-matches"
  | "bottom"
  | "left"
  | "right";

interface PlayTabBanner {
  position: PlayTabBannerPosition;
  render: () => React.ReactNode;
}
PositionLocation
above-group-navAbove the game-day navigation.
below-group-navBelow the game-day navigation.
below-matchesBelow the list of match cards.
bottomVery bottom of the Play tab.
leftLeft sidebar (desktop only).
rightRight sidebar (desktop only).
<TopX
  {...otherProps}
  playTabBanners={[
    { position: "above-group-nav", render: () => <SponsorBanner /> },
    { position: "right", render: () => <AdSlot id="top-x-sidebar" /> },
  ]}
/>

Countdown timer

When showCountdown is true (the default), each match card displays a live kickoff countdown while the game is open. Set to false to hide it — only the kickoff time will be shown.

<TopX {...otherProps} showCountdown={false} />

Consent gating

interface ConsentDef {
  consentId: string;
  body: string;        // HTML allowed — links, formatting
  required: boolean;
  defaultChecked: boolean;
}
  • Required consents block prediction submission until accepted.
  • Optional consents appear in the same modal but do not block progression.
  • Once accepted, the modal does not reappear for that user.
<TopX
  {...otherProps}
  consents={[
    {
      consentId: "tos",
      body: 'I accept the <a href="https://example.com/tos" target="_blank">Terms of Service</a>.',
      required: true,
      defaultChecked: false,
    },
  ]}
/>

Betslip integration

When the betslip prop is provided, TopX renders a Betslip widget internally as a sibling — you do not add a separate <Betslip /> component to the page. See the Betslip component page for the standalone widget reference.

interface TopXBetslipConfig {
  trigger?: TopXBetslipTrigger; // "predictions-only" | "odds-only"
  position?: BetslipPosition;
  maxSelections?: number;
  stakePresets?: number[];
  oddsPollingInterval?: number;
  currency?: string;
  ctaUrlTemplate?: string;
  brandingLogoUrl?: string;
  labels?: BetslipLabels;
  themeOptions?: CustomThemeOptions;
}

Trigger modes

ModeWhen selections are sent to Betslip
"predictions-only" (default)Every time the user edits a score (home/away increment or decrement). Outcome derivation: "1" (home win), "X" (draw), "2" (away win).
"odds-only"Only when the user clicks an odds button on the post-submit odds display.

Theme inheritance

If betslip.themeOptions is not provided, the Betslip widget inherits TopX's own themeOptions. A single theme on TopX is enough to style both consistently.

Examples

Basic

<TopX
  entityId="top-x-template-123"
  sdk={sdk}
  language="en"
/>

Authenticated with selected tabs

<TopX
  entityId="top-x-template-123"
  sdk={sdk}
  language="en"
  userIsLoggedIn
  tabs={["play", "leaderboard", "private-leagues"]}
  matchCardBgImageUrl="https://your-cdn.com/stadium-bg.jpg"
  themeOptions={{ mode: "dark" }}
/>

Full setup with banners and consents

<TopX
  entityId="top-x-template-123"
  sdk={sdk}
  language="en"
  userIsLoggedIn={false}
  signInCTA={{ defaultLabel: "Sign in to Predict", onClick: handleSignIn }}
  tabs={["play", "leaderboard", "private-leagues", "rules", "prizes"]}
  matchCardBgImageUrl="https://your-cdn.com/matchcard-bg.jpg"
  showCountdown={true}
  playTabBanners={[
    { position: "above-group-nav", render: () => <SponsorBanner /> },
    { position: "right", render: () => <AdSlot id="top-x-sidebar" /> },
  ]}
  consents={[
    {
      consentId: "tos",
      body: 'I accept the <a href="https://example.com/tos" target="_blank">Terms of Service</a>.',
      required: true,
      defaultChecked: false,
    },
  ]}
  themeOptions={{ mode: "light" }}
/>

TopX + Betslip (predictions trigger)

<TopX
  entityId="top-x-template-123"
  sdk={sdk}
  language="en"
  userIsLoggedIn
  tabs={["play", "leaderboard"]}
  betslip={{
    trigger: "predictions-only",
    position: "side-right",
    currency: "£",
    stakePresets: [5, 10, 25, 50],
    ctaUrlTemplate:
      "https://your-bookmaker.com/bet?ids={selectionIds}&stake={stake}&ref={currentUrl}",
    labels: { disclaimer: "18+ | Please gamble responsibly" },
  }}
  themeOptions={{ mode: "dark" }}
/>

TopX + Betslip (odds trigger)

<TopX
  entityId="top-x-template-123"
  sdk={sdk}
  language="en"
  userIsLoggedIn
  betslip={{
    trigger: "odds-only",
    position: "bottom-right",
    currency: "€",
    ctaUrlTemplate:
      "https://your-bookmaker.com/bet?ids={selectionIds}&stake={stake}",
  }}
/>