Files
moreminimore-vibe/src/components/ChatModeSelector.tsx
Adeniji Adekunle James 3b68fb4e48 feat: add hotkey to toggle chat modes (#1274) (#995) (#1284)
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>
2025-09-30 13:43:24 -07:00

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>
);
}