Adds Ctrl+Shift+A (Cmd+Shift+A on Mac) keyboard shortcut to toggle between Ask and Build chat modes. **Changes:** - Created `useChatModeToggle` hook for shared logic - Added shortcut to ChatInput and HomeChatInput components **Usage:** Press Ctrl+Shift+A (or Cmd+Shift+A on Mac) to quickly switch between chat modes without using the UI. <img width="434" height="123" alt="image" src="https://github.com/user-attachments/assets/a8c167b6-2b54-46f5-8191-5019991fc8e5" /> Closes (#995) <!-- This is an auto-generated description by cubic. --> --- ## Summary by cubic Add a global hotkey to toggle between Ask and Build modes: Ctrl+Shift+A (Cmd+Shift+A on Mac). Makes switching faster without touching the UI and fulfills Linear #995. - **New Features** - Added useChatModeToggle hook to flip selectedChatMode, detect platform, and track PostHog event chat:mode_toggle. - Wired the hotkey into ChatInput and HomeChatInput via useChatModeToggle. - Updated ChatModeSelector tooltip to show the shortcut. <!-- End of auto-generated description by cubic. --> <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Adds Cmd/Ctrl + . shortcut to cycle chat modes via a new hook, and updates the mode selector tooltip to show the shortcut. > > - **UX/Hotkey**: > - Introduces `useChatModeToggle` to cycle `settings.selectedChatMode` (captures `chat:mode_toggle`), with platform detection (`detectIsMac`/`useIsMac`) and `useShortcut` binding for `Cmd/Ctrl + .`. > - **Integrations**: > - Wires `useChatModeToggle()` into `components/chat/ChatInput.tsx` and `components/chat/HomeChatInput.tsx` to enable the shortcut in chat inputs. > - **UI**: > - Enhances `components/ChatModeSelector.tsx` tooltip to display the platform-specific shortcut hint (`⌘ + .` or `Ctrl + .`). > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit d8cc3fff43b6eb3227623f1c084410f42392c0b3. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Will Chen <willchen90@gmail.com>
96 lines
3.0 KiB
TypeScript
96 lines
3.0 KiB
TypeScript
import {
|
|
MiniSelectTrigger,
|
|
Select,
|
|
SelectContent,
|
|
SelectItem,
|
|
SelectValue,
|
|
} from "@/components/ui/select";
|
|
import {
|
|
Tooltip,
|
|
TooltipContent,
|
|
TooltipTrigger,
|
|
} from "@/components/ui/tooltip";
|
|
import { useSettings } from "@/hooks/useSettings";
|
|
import type { ChatMode } from "@/lib/schemas";
|
|
import { cn } from "@/lib/utils";
|
|
import { detectIsMac } from "@/hooks/useChatModeToggle";
|
|
|
|
export function ChatModeSelector() {
|
|
const { settings, updateSettings } = useSettings();
|
|
|
|
const selectedMode = settings?.selectedChatMode || "build";
|
|
|
|
const handleModeChange = (value: string) => {
|
|
updateSettings({ selectedChatMode: value as ChatMode });
|
|
};
|
|
|
|
const getModeDisplayName = (mode: ChatMode) => {
|
|
switch (mode) {
|
|
case "build":
|
|
return "Build";
|
|
case "ask":
|
|
return "Ask";
|
|
case "agent":
|
|
return "Agent";
|
|
default:
|
|
return "Build";
|
|
}
|
|
};
|
|
const isMac = detectIsMac();
|
|
|
|
return (
|
|
<Select value={selectedMode} onValueChange={handleModeChange}>
|
|
<Tooltip>
|
|
<TooltipTrigger asChild>
|
|
<MiniSelectTrigger
|
|
data-testid="chat-mode-selector"
|
|
className={cn(
|
|
"h-6 w-fit px-1.5 py-0 text-xs-sm font-medium shadow-none gap-0.5",
|
|
selectedMode === "build"
|
|
? "bg-background hover:bg-muted/50 focus:bg-muted/50"
|
|
: "bg-primary/10 hover:bg-primary/20 focus:bg-primary/20 text-primary border-primary/20 dark:bg-primary/20 dark:hover:bg-primary/30 dark:focus:bg-primary/30",
|
|
)}
|
|
size="sm"
|
|
>
|
|
<SelectValue>{getModeDisplayName(selectedMode)}</SelectValue>
|
|
</MiniSelectTrigger>
|
|
</TooltipTrigger>
|
|
<TooltipContent>
|
|
<div className="flex flex-col">
|
|
<span>Open mode menu</span>
|
|
<span className="text-xs text-gray-200 dark:text-gray-500">
|
|
{isMac ? "⌘ + ." : "Ctrl + ."} to toggle
|
|
</span>
|
|
</div>
|
|
</TooltipContent>
|
|
</Tooltip>
|
|
<SelectContent align="start" onCloseAutoFocus={(e) => e.preventDefault()}>
|
|
<SelectItem value="build">
|
|
<div className="flex flex-col items-start">
|
|
<span className="font-medium">Build</span>
|
|
<span className="text-xs text-muted-foreground">
|
|
Generate and edit code
|
|
</span>
|
|
</div>
|
|
</SelectItem>
|
|
<SelectItem value="ask">
|
|
<div className="flex flex-col items-start">
|
|
<span className="font-medium">Ask</span>
|
|
<span className="text-xs text-muted-foreground">
|
|
Ask questions about the app
|
|
</span>
|
|
</div>
|
|
</SelectItem>
|
|
<SelectItem value="agent">
|
|
<div className="flex flex-col items-start">
|
|
<span className="font-medium">Agent (experimental)</span>
|
|
<span className="text-xs text-muted-foreground">
|
|
Agent can use tools (MCP) and generate code
|
|
</span>
|
|
</div>
|
|
</SelectItem>
|
|
</SelectContent>
|
|
</Select>
|
|
);
|
|
}
|