Frontend
Command Palette

Command Palette & Context Cycling System

A comprehensive keyboard-driven navigation system with Cmd+K/Ctrl+K command palette and Shift+Tab context cycling that adapts to your current page.

Features Overview

1. Command Palette (Cmd+K / Ctrl+K)

Context-aware command menu that adapts to your current page:

PageAvailable Commands
League NotebookLMUpload, validate, view analysis, edit
Chat ModeSports/league search, filtering
MarketsBetting platform, market type search
GlobalNavigation, quick actions

2. Context Cycler (Shift+Tab)

Page-aware context switching:

PageCycles Through
League WorkspaceYour leagues
Chat ModeSport archetypes (Combat, Racing, Team)
Markets PageMarket types (Player Props, Totals, Parlays)
GlobalRecent workspaces

Installation

Wrap Your App

In your root layout (app/layout.tsx or app/(dashboard)/layout.tsx):

import { CommandPaletteProvider } from '@/components/command-palette'
 
export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        <AuthProvider>
          <CommandPaletteProvider>
            {children}
          </CommandPaletteProvider>
        </AuthProvider>
      </body>
    </html>
  )
}

Install Dependencies (if needed)

npm install framer-motion cmdk

Keyboard Shortcuts

Global Shortcuts

ShortcutAction
Cmd+K / Ctrl+KOpen command palette
Shift+TabOpen context cycler
EscClose any modal
↑↓Navigate items
EnterSelect item

Navigation Shortcuts (when palette is open)

ShortcutAction
G HGo to Home
G LGo to My Leagues
G EGo to Explore
G CGo to Chat

Action Shortcuts

ShortcutAction
Cmd+NCreate new league
Cmd+FFocus search
Cmd+EEdit current league
Cmd+VValidate data
Cmd+Shift+EExport fingerprint JSON

Context-Aware Behavior

Path: /dashboard/leagues/[id]

Command Palette shows:

  • βœ… Upload Document
  • βœ… Validate Data
  • βœ… View Fingerprint
  • βœ… Edit League Info
  • βœ… Sport Archetype Compliance
  • βœ… Platform Compatibility
  • βœ… Export JSON
  • βœ… View Analytics
  • βœ… Settings

Context Cycler shows:

  • Your leagues (cycle through them quickly)

Programmatic Control

Open Command Palette

import { useCommandPalette } from '@/components/command-palette'
 
function MyComponent() {
  const { openCommandPalette, setLeagueContext } = useCommandPalette()
 
  return (
    <Button onClick={openCommandPalette}>
      Open Command Palette
    </Button>
  )
}

Setting Specific Contexts

// Set league context
useCommandPalette().setLeagueContext('league-123', 'Pro Curling League')
 
// Set chat context (sport archetypes)
useCommandPalette().setChatContext()
 
// Set market context
useCommandPalette().setMarketContext()

Listening to Custom Events

useEffect(() => {
  const handleContextSwitch = (event: CustomEvent) => {
    console.log('Context switched:', event.detail)
  }
 
  window.addEventListener('switch-context', handleContextSwitch)
  return () => window.removeEventListener('switch-context', handleContextSwitch)
}, [])
 
// Listen for sport archetype search
window.addEventListener('search-sport-archetype', (event: CustomEvent) => {
  const archetype = event.detail.archetype
  // Filter leagues by archetype
})
 
// Listen for platform search
window.addEventListener('search-platform', (event: CustomEvent) => {
  const platform = event.detail.platform
  // Filter leagues by platform compatibility
})

Adding Custom Commands

// In CommandPalette.tsx, add to the appropriate command group
 
const customCommands: CommandGroup = {
  heading: 'Custom Actions',
  actions: [
    {
      id: 'custom-action',
      label: 'My Custom Action',
      description: 'Does something awesome',
      icon: Sparkles,
      shortcut: ['Cmd', 'Shift', 'X'],
      onSelect: () => {
        // Your custom logic
      },
    },
  ],
}

Adding Custom Context Items

// Add your custom context type
export type ContextType = 'league' | 'sport-archetype' | 'betting-market' | 'your-custom-type' | 'recent'
 
// Define your custom items
const yourCustomItems: ContextItem[] = [
  {
    id: 'item-1',
    label: 'Custom Item 1',
    sublabel: 'Description',
    icon: YourIcon,
    color: 'from-blue-500 to-purple-500',
    onSelect: () => {
      // Your logic
    },
  },
]

Integration Examples

Chat with Context Switching

'use client'
 
import { useEffect, useState } from 'react'
 
export function ChatPage() {
  const [sportArchetype, setSportArchetype] = useState('team_sports')
 
  useEffect(() => {
    const handleSwitch = (event: CustomEvent) => {
      if (event.detail.type === 'sport-archetype') {
        setSportArchetype(event.detail.value)
      }
    }
 
    window.addEventListener('switch-context', handleSwitch)
    return () => window.removeEventListener('switch-context', handleSwitch)
  }, [])
 
  return (
    <div>
      <h1>Chat - {sportArchetype}</h1>
      {/* Chat interface filtered by current archetype */}
    </div>
  )
}

Markets with Dynamic Filtering

'use client'
 
import { useEffect, useState } from 'react'
 
export function MarketsPage() {
  const [marketType, setMarketType] = useState('player-props')
 
  useEffect(() => {
    const handleSwitch = (event: CustomEvent) => {
      if (event.detail.type === 'betting-market') {
        setMarketType(event.detail.value)
      }
    }
 
    window.addEventListener('switch-context', handleSwitch)
    return () => window.removeEventListener('switch-context', handleSwitch)
  }, [])
 
  return (
    <div>
      <h1>Markets - {marketType}</h1>
      {/* Markets filtered by current type */}
    </div>
  )
}

Configuration

Auto-Close Behavior

The context cycler automatically closes after 3 seconds of inactivity:

// Change timeout duration in ContextCycler.tsx
const timer = setTimeout(() => {
  setOpen(false)
}, 3000) // Change this value

Badge Indicators

{
  id: 'action',
  label: 'My Action',
  badge: 'New', // Shows badge
  shortcut: ['Cmd', 'X'], // Shows keyboard shortcut
  onSelect: () => {},
}

Search with Keywords

{
  id: 'combat',
  label: 'Combat Sports',
  keywords: ['mma', 'boxing', 'martial', 'fighting', 'ufc'],
  onSelect: () => {},
}

Architecture

CommandPaletteProvider (Root)
β”œβ”€β”€ CommandPalette (Cmd+K)
β”‚   β”œβ”€β”€ Context Detection
β”‚   β”œβ”€β”€ Command Groups
β”‚   └── Search & Filter
└── ContextCycler (Shift+Tab)
    β”œβ”€β”€ Context Detection
    β”œβ”€β”€ Item Lists
    └── Auto-Close Timer

Files

FilePurpose
CommandPalette.tsxMain command palette component
ContextCycler.tsxContext switching component
CommandPaletteProvider.tsxGlobal provider and orchestrator
index.tsBarrel exports

Dependencies

  • cmdk - Command menu component
  • framer-motion - Animations
  • lucide-react - Icons
  • tailwindcss - Styling
  • shadcn/ui - UI components

Accessibility

  • βœ… Full keyboard navigation
  • βœ… ARIA labels and roles
  • βœ… Focus management
  • βœ… Screen reader compatible
  • βœ… High contrast support

Troubleshooting

IssueSolution
Command Palette Not OpeningEnsure CommandPaletteProvider wraps your app
Context Cycler Not Showing ItemsCreate some items first (leagues, etc.)
Keyboard Shortcuts Not WorkingCheck for conflicts with browser/OS shortcuts

Related Documentation

Platform

Documentation

Community

Support

partnership@altsportsdata.comdev@altsportsleagues.ai

2025 Β© AltSportsLeagues.ai. Powered by AI-driven sports business intelligence.

πŸ€– AI-Enhancedβ€’πŸ“Š Data-Drivenβ€’βš‘ Real-Time