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
| Prop | Type | Description |
|---|---|---|
entityId | string | TopX template identifier. |
sdk | FansUnitedSDKModel | SDK instance. |
language | LanguageType | Display language. |
TopX does not take a
templateprop — its layout is a fixed multi-tab interface.
Optional props
| Prop | Type | Default | Description |
|---|---|---|---|
themeOptions | CustomThemeOptions | — | See Theming. |
userIsLoggedIn | boolean | false | Host auth state. |
signInCTA | SignInCTADetails | — | See Sign-in CTA. |
tabs | TopXTab[] | all tabs | Which tabs to enable. |
defaultImagePlaceholderUrl | string | — | Fallback image URL for the hero header. |
playTabBanners | PlayTabBanner[] | — | Custom banners injected into the Play tab. |
consents | ConsentDef[] | — | Consent definitions required before predicting. |
matchCardBgImageUrl | string | — | Background image URL for match prediction cards. |
showCountdown | boolean | true | Show the kickoff countdown timer on match cards for open games. |
betslip | TopXBetslipConfig | — | Betslip integration. See below. |
Tabs
type TopXTab = "play" | "leaderboard" | "private-leagues" | "rules" | "prizes";| Tab | Description |
|---|---|
play | Main prediction interface — browse games by day and submit score forecasts. |
leaderboard | Global rankings with pagination and user highlight. |
private-leagues | Create and join private leagues. |
rules | Searchable game rules and scoring system. |
prizes | Prize 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;
}| Position | Location |
|---|---|
above-group-nav | Above the game-day navigation. |
below-group-nav | Below the game-day navigation. |
below-matches | Below the list of match cards. |
bottom | Very bottom of the Play tab. |
left | Left sidebar (desktop only). |
right | Right 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
| Mode | When 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}",
}}
/>