"use client" import { useState, useEffect, useRef, useCallback } from "react" import { useRouter } from "next/navigation" import { Command } from "cmdk" import { ArrowRight, Bot, Database, FileText, Globe, KeyRound, Layers, Search, Wallet, Webhook, Zap, Server, Activity, Eye, Boxes, BarChart3, RotateCw, Play, Square, MessageSquare, Sparkles, ArrowUpRight, Terminal, } from "@luxfi/ui/icons" import { useBrand } from "@/components/brand-logo" import { AiChat } from "@/components/ai-chat" // Navigation pages const pages = [ { name: "Dashboard", href: "/dashboard", icon: Zap, group: "Navigation" }, { name: "Documentation", href: "/docs", icon: FileText, group: "Navigation" }, { name: "Pricing", href: "/pricing", icon: ArrowRight, group: "Navigation" }, { name: "Node (RPC)", href: "/products/node", icon: Globe, group: "Products" }, { name: "Token API", href: "/products/data", icon: Database, group: "Products" }, { name: "NFT API", href: "/products/data", icon: Database, group: "Products" }, { name: "Smart Wallets", href: "/products/wallets", icon: Wallet, group: "Products" }, { name: "Explorer", href: "/products/explorer", icon: Search, group: "Products" }, { name: "MPC", href: "/products/mpc", icon: KeyRound, group: "Products" }, { name: "Webhooks", href: "/products/webhooks", icon: Webhook, group: "Products" }, { name: "Rollups", href: "/products/rollups", icon: Layers, group: "Products" }, { name: "Ethereum", href: "/chains/ethereum", icon: Globe, group: "Chains" }, { name: "Solana", href: "/chains/solana", icon: Globe, group: "Chains" }, { name: "Base", href: "/chains/base", icon: Globe, group: "Chains" }, { name: "Arbitrum", href: "/chains/arbitrum", icon: Globe, group: "Chains" }, { name: "Polygon", href: "/chains/polygon", icon: Globe, group: "Chains" }, { name: "All Chains", href: "/chains", icon: Globe, group: "Chains" }, { name: "Quickstart", href: "/docs/quickstart", icon: FileText, group: "Docs" }, { name: "API Reference", href: "/docs/api", icon: FileText, group: "Docs" }, { name: "SDKs", href: "/docs/sdks", icon: FileText, group: "Docs" }, ] // Infrastructure quick actions const infraActions = [ { name: "Services", href: "/dashboard/infrastructure/services", icon: Boxes, group: "Infrastructure" }, { name: "Observability", href: "/dashboard/infrastructure/observability", icon: Eye, group: "Infrastructure" }, { name: "Nodes", href: "/dashboard/infrastructure/nodes", icon: Server, group: "Infrastructure" }, { name: "Monitoring", href: "/dashboard/infrastructure/monitoring", icon: Activity, group: "Infrastructure" }, { name: "Fleet Status", href: "/dashboard/infrastructure/nodes", icon: BarChart3, group: "Infrastructure" }, ] // AI-powered actions (trigger chat with pre-filled prompts) const aiActions = [ { name: "Check fleet health", prompt: "Check the health of all fleets and services", icon: Activity, group: "AI Actions" }, { name: "Show active alerts", prompt: "Are there any active alerts or incidents?", icon: Eye, group: "AI Actions" }, { name: "Search logs", prompt: "Search recent logs for errors across all services", icon: Terminal, group: "AI Actions" }, { name: "Scale validators", prompt: "How do I scale my validator fleet?", icon: ArrowUpRight, group: "AI Actions" }, { name: "Deploy service", prompt: "Help me deploy a new infrastructure service", icon: Play, group: "AI Actions" }, { name: "RPC status", prompt: "What's the current RPC endpoint status and latency?", icon: Zap, group: "AI Actions" }, ] export function CommandMenu() { const [open, setOpen] = useState(false) const [chatOpen, setChatOpen] = useState(false) const [chatPrompt, setChatPrompt] = useState() const [mode, setMode] = useState<"search" | "ai">("search") const router = useRouter() const brand = useBrand() const inputRef = useRef(null) useEffect(() => { const down = (e: KeyboardEvent) => { // cmd+K = command palette if (e.key === "k" && (e.metaKey || e.ctrlKey)) { if ( e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement ) { return } e.preventDefault() setOpen((o) => !o) setMode("search") } // cmd+J = AI chat directly if (e.key === "j" && (e.metaKey || e.ctrlKey)) { if ( e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement ) { return } e.preventDefault() setChatPrompt(undefined) setChatOpen((o) => !o) } // "/" = search (not in input) if (e.key === "/" && !( e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement )) { e.preventDefault() setOpen(true) setMode("search") } } document.addEventListener("keydown", down) return () => document.removeEventListener("keydown", down) }, []) const runCommand = useCallback((href: string) => { setOpen(false) router.push(href) }, [router]) const runAiAction = useCallback((prompt: string) => { setOpen(false) setChatPrompt(prompt) setChatOpen(true) }, []) const switchToAi = useCallback(() => { setOpen(false) setChatPrompt(undefined) setChatOpen(true) }, []) const groups = pages.reduce( (acc, page) => { if (!acc[page.group]) acc[page.group] = [] acc[page.group].push(page) return acc }, {} as Record ) // Ecosystem links from brand const ecosystemLinks = brand.footerLinks.map((link) => ({ name: link.name, href: link.href, icon: Globe, external: link.external, })) return ( <> {/* Trigger button */} {/* Command palette dialog */} {open && (
setOpen(false)} />
No results found. Press the AI button to ask a question. {/* AI Actions */} {aiActions.map((action) => ( runAiAction(action.prompt)} className="flex cursor-pointer items-center gap-3 rounded-md px-2 py-2 text-sm aria-selected:bg-accent aria-selected:text-accent-foreground" > {action.name} ))} {/* Infrastructure */} {infraActions.map((item) => ( runCommand(item.href)} className="flex cursor-pointer items-center gap-3 rounded-md px-2 py-2 text-sm aria-selected:bg-accent aria-selected:text-accent-foreground" > {item.name} ))} {/* Navigation groups */} {Object.entries(groups).map(([group, items]) => ( {items.map((item) => ( runCommand(item.href)} className="flex cursor-pointer items-center gap-3 rounded-md px-2 py-2 text-sm aria-selected:bg-accent aria-selected:text-accent-foreground" > {item.name} ))} ))} {/* Ecosystem */} {ecosystemLinks.length > 0 && ( {ecosystemLinks.map((item) => ( { setOpen(false) if (item.external) { window.open(item.href, "_blank") } else { router.push(item.href) } }} className="flex cursor-pointer items-center gap-3 rounded-md px-2 py-2 text-sm aria-selected:bg-accent aria-selected:text-accent-foreground" > {item.name} ))} )} {/* Footer */}
↑↓ Navigate ↵ Select esc Close
⌘J AI Chat
)} {/* AI Chat Panel */} setChatOpen(false)} initialPrompt={chatPrompt} /> ) }