Phase 3: AI Panel Polish, Mobile-First UX, Spacing Overhaul, Fixture Redesign
What Was Implemented
New Dependency
react-resizable-panelsv4.6.2 — API:Group,Panel,Separator(v4 names, not v2PanelGroup/PanelResizeHandle)
New File
src/components/layout/AIMobileSheet.tsx— Mobile bottom sheet for AI (chat default, analysis tab when activeAnalysis exists)
1. AI Panel: Scrollable, Resizable, Collapsible
Chat scrolling fix
AIChatPanel.tsx: Root divflex-1→h-fullfixes nested flex overflow. Messages scroll, tabs stay fixed.
AI button always visible
AIFloatingButton.tsx: RemovedisOpenhide condition. ShowsXwhen open, gradientSparkleswhen closed. z-indexz-[60]. Positionbottom-[4.5rem] md:bottom-6.
Resizable panes
AIPanel.tsx: Full rewrite usingreact-resizable-panelsv4 (Group/Panel/Separator). Vertical split,minSize={15}, 6px drag handle with pill grip.
Collapsible panes
aiPanelStore.ts: AddedanalysisVisible,chatVisible,toggleAnalysis(),toggleChat(). Persisted viapartialize.AIPanel.tsx: Three render states — both collapsed (restore buttons), one visible (fills full), both visible (resizable).PaneHeadercomponent with collapseChevronDownbutton per pane.AnalysisContentnow exported for use byAIMobileSheet.
2. Layout Spacing: 5px Gaps, Edge-to-Edge
5px gap system
MainLayout.tsx: Gridmt-[5px] gap-[5px] pl-[5px] pr-[5px] pb-[5px]. Heighth-[calc(100vh-71px)]. Aside/main useh-full.
Sports page push-not-overlay
MainLayout.tsx: RemovedisSportsPageexclusion fromshowAIColumn. AI panel is now a grid column on all pages. Removed overlay div.
Edge-to-edge padding
fixture/[id]/page.tsx:px-4 sm:px-6 py-4→px-2 py-2live/page.tsx:px-4 sm:px-6 lg:px-8 py-6→px-2 py-2my-bets/page.tsx:px-4 sm:px-6 lg:px-8 py-6→px-2 py-2watchlists/page.tsx:px-4 py-6→px-2 py-2sports/page.tsx: Already tight (px-3 py-4), left as-is
3. Mobile: Bet Slip Bottom Sheet + AI Bottom Sheet
Bet slip collapsed bar
BetPanel.tsx: Replaced floating FAB with persistent collapsed bar atfixed bottom-16. Shows "Betslip (N)" withChevronUp. Full-width, above BottomNav.
Improved sheet physics
- Both
BetPanel.tsxandAIMobileSheet.tsx: Velocity tracking (dismiss if > 500px/s), 40% height threshold, rubber-band at top (Math.pow(overDrag, 0.7)),sheet-transitionCSS class for spring snap-back.
AI mobile sheet
AIMobileSheet.tsx:lg:hidden, reads fromaiPanelStore, tab bar (Chat/Analysis) only whenactiveAnalysisexists. Same drag-to-dismiss mechanics. Glassmorphic:bg-slate-900/95 backdrop-blur-2xl.layout.tsx: Added<AIMobileSheet />after<AIFloatingButton />.
CSS utilities
globals.css: Added.sheet-transition(300mscubic-bezier(0.32, 0.72, 0, 1)),.glass-panel,.glass-panel-elevated.
4. Fixture Page: Header Removal, Breadcrumbs
Removed duplicate header card
fixture/[id]/page.tsx: Removedbg-slate-800/50 rounded-xlheader block (tournament, LIVE badge, volume, full SportScoreDisplay).
Compact match header in market tab
- Inline teams row,
SportScoreDisplay compact, LIVE badge, volume,AIFixtureButton size="sm".
1EXCH-style breadcrumbs
FixtureBreadcrumb.tsx: Slash separators (/),ArrowLeftback button,useRouter().back(). Style:text-blue-400links,text-slate-400current,text-slate-600separators.
Files Changed
| File | Change |
|---|---|
package.json / package-lock.json | Added react-resizable-panels |
AIPanel.tsx | Rewrite: resizable + collapsible panes via Group/Panel/Separator |
AIChatPanel.tsx | Root div flex-1 → h-full |
AIFloatingButton.tsx | Always visible, X icon when open, z-[60] |
aiPanelStore.ts | Added analysisVisible/chatVisible + toggles, persisted |
MainLayout.tsx | 5px gaps, push-not-overlay, height fix |
BetPanel.tsx | Collapsed bar, velocity drag-to-dismiss, glassmorphic sheet |
AIMobileSheet.tsx | NEW — Mobile AI bottom sheet |
layout.tsx | Added AIMobileSheet |
fixture/[id]/page.tsx | Removed header card, compact market tab header, reduced padding |
FixtureBreadcrumb.tsx | Slash separators, back button |
live/page.tsx | Reduced padding |
my-bets/page.tsx | Reduced padding |
watchlists/page.tsx | Reduced padding |
globals.css | sheet-transition, glass-panel, glass-panel-elevated utilities |
Verification
npx tsc --noEmit— 0 errorsnpm run lint— 0 new errors (162 pre-existing in unrelated files)