Player & Agent Menu Page — Design Spec
Date: 2026-06-16
Status: Approved approach + gradient token confirmed
Figma: node 3542-2674 (forsyt.io master file)
Goal
Replace the popover "More" menus (player and agent views) with a dedicated full menu page matching the Figma design: a gradient banner header (avatar + display name) over a flat list of icon+label rows, with the bottom nav showing "More" active. Each view keeps its current menu options. Email is intentionally omitted for now. Must work in dark and light mode via the existing design system.
Routes
| View | Route | File |
|---|---|---|
| Player | /menu | src/app/menu/page.tsx |
| Agent | /agent-v2/menu | src/app/agent-v2/menu/page.tsx |
Player /menu renders under the root layout (global BottomNav). Agent
/agent-v2/menu renders under the agent-v2 layout (its own bottom nav).
Components
src/components/menu/MenuScreen.tsx (new, shared, presentational)
Dumb component — no business logic, no data fetching.
Props:
interface MenuItem {
icon: React.ComponentType<{ className?: string }>;
label: string;
href?: string; // navigation target
onClick?: () => void; // action (e.g. logout) — mutually exclusive with href
external?: boolean; // shows the ↗ "leaves this section" arrow (e.g. Agent Panel)
danger?: boolean; // red label (logout) — uses text-loss
}
interface MenuScreenProps {
displayName: string;
avatarUrl?: string | null; // falls back to initial when absent
role?: string; // optional small badge under name (no email)
items: MenuItem[];
}
Renders:
- Gradient banner header — full-width, ~180px. Centered circular avatar (dashed
ring), then
displayName(white, centered). No email row. - List — each
MenuItemis a full-width row: left icon (currentColor/text-fg), label (text-fg), optional right ↗ forexternal,text-losswhendanger.h-px bg-fg/[0.06]divider between rows.hrefrows use the router;onClickrows fire the handler.
src/app/menu/page.tsx (player)
Reads useAuthStore, builds the player item list, renders <MenuScreen>:
- Home (
/) - Settings (
/settings) - PnL Report (
/reports/pnl) — flattened from the old expandable Reports section - Bet History (
/reports/bet-history) — flattened - Agent Panel (
/agent) —external, only if user has agent access - Admin Panel (
/admin) —external, only if user has admin access - Install App — only when installable (keeps current PWA-install behavior)
- Logout / Exit Demo —
danger,onClick
src/app/agent-v2/menu/page.tsx (agent)
Reads useAuthStore, builds the agent item list, renders <MenuScreen>:
- Player View (
/sports) —external - Ledger (
/agent-v2/ledger) - Admin Panel (
/admin) —external, only if platform_admin / adminUser - Logout —
danger,onClick
Bottom-nav changes
- Player
BottomNav.tsx: "More" navigates to/menu(was: toggle popover). "More" shows active whenpathname === '/menu'. The popover JSX/state becomes dead code. - Agent
agent-v2/layout.tsx: "More" navigates to/agent-v2/menu(was: toggle popover). Active on that route. Popover JSX/state becomes dead code. - The menu page suppresses the existing top header (player global Header; agent-v2 layout header) so the gradient banner sits at the very top.
Design tokens
One new token — the banner gradient. Everything else reuses existing tokens
(bg-bg, text-fg, dividers bg-fg/[0.06], text-loss, icon currentColor).
Confirmed: --menu-header-gradient: linear-gradient(135deg, #e171d3 0%, #d9614f 45%, #5f8fc4 100%) (magenta → coral → blue, sampled from Figma). Defined identically in
both :root,.dark and .light — the banner is decorative with white text and reads fine
on the vibrant gradient in either theme.
Dark / light mode
- List, dividers, icons, labels all flip via existing tokens (same pattern as the
recent contrast fixes —
currentColoricons,text-fg, faint dividers). - Banner gradient + white header text are constant (readable on the vibrant gradient in both modes).
Dead code (list, do not delete without confirmation)
- Player popover block +
isMoreMenuOpenstate inBottomNav.tsx. - Agent popover block +
moreOpenstate inagent-v2/layout.tsx.
These will be itemized after wiring; removal confirmed with the user (Dead Code Hygiene).
Out of scope
- Email display.
- Bet-slip green-tint / keypad contrast (separate task).
- Any backend/API change — frontend only.
Cross-system impact
- frontend: new shared component, 2 routes, 2 bottom-nav edits, 1 new token.
- backend / services / infra: none.
Testing / verification
- Render
/menuand/agent-v2/menuin both dark and light mode; verify every current menu option is present and routes correctly, conditionals (Agent/Admin/Install) behave, logout works, "More" shows active, and the banner + rows are legible in both themes.