11import { Spinner } from "~/components/ui/spinner" ;
22import { NotificationSettings } from "./NotificationSettings" ;
3- import { ArchiveIcon , ArchiveX , ChevronRightIcon , SettingsIcon } from "lucide-react" ;
3+ import { ArchiveIcon , ArchiveX , CheckIcon , ChevronRightIcon , SettingsIcon } from "lucide-react" ;
44import { Link , useNavigate } from "@tanstack/react-router" ;
55import type { CSSProperties , ReactNode } from "react" ;
66import { useCallback , useEffect , useMemo , useRef , useState } from "react" ;
@@ -105,6 +105,7 @@ import {
105105 AlertDialogTitle ,
106106} from "../ui/alert-dialog" ;
107107import { Button } from "../ui/button" ;
108+ import { Toggle , ToggleGroup } from "../ui/toggle-group" ;
108109import { Collapsible , CollapsiblePanel , CollapsibleTrigger } from "../ui/collapsible" ;
109110import {
110111 Dialog ,
@@ -578,6 +579,7 @@ export function useSettingsRestore(onRestored?: () => void) {
578579 ...( settings . composerCollapseOnScroll !== DEFAULT_UNIFIED_SETTINGS . composerCollapseOnScroll
579580 ? [ "Collapse composer on scroll" ]
580581 : [ ] ) ,
582+ ...( settings . sendShortcut !== DEFAULT_UNIFIED_SETTINGS . sendShortcut ? [ "Send shortcut" ] : [ ] ) ,
581583 ...( settings . followUpBehavior !== DEFAULT_UNIFIED_SETTINGS . followUpBehavior
582584 ? [ "Follow-up behavior" ]
583585 : [ ] ) ,
@@ -639,6 +641,7 @@ export function useSettingsRestore(onRestored?: () => void) {
639641 settings . confirmThreadDelete ,
640642 settings . confirmThreadUnpin ,
641643 settings . composerCollapseOnScroll ,
644+ settings . sendShortcut ,
642645 settings . followUpBehavior ,
643646 settings . addProjectBaseDirectory ,
644647 settings . defaultThreadEnvMode ,
@@ -752,6 +755,7 @@ export function useSettingsRestore(onRestored?: () => void) {
752755 proactivePanelsEnabled : DEFAULT_UNIFIED_SETTINGS . proactivePanelsEnabled ,
753756 showSkillsInSlashMenu : DEFAULT_UNIFIED_SETTINGS . showSkillsInSlashMenu ,
754757 composerCollapseOnScroll : DEFAULT_UNIFIED_SETTINGS . composerCollapseOnScroll ,
758+ sendShortcut : DEFAULT_UNIFIED_SETTINGS . sendShortcut ,
755759 followUpBehavior : DEFAULT_UNIFIED_SETTINGS . followUpBehavior ,
756760 contextWindowMeterEnabled : DEFAULT_UNIFIED_SETTINGS . contextWindowMeterEnabled ,
757761 environmentIdentificationMode : DEFAULT_UNIFIED_SETTINGS . environmentIdentificationMode ,
@@ -2086,6 +2090,12 @@ function LegacyFeaturesSection() {
20862090}
20872091
20882092export function GeneralSettingsPanel ( ) {
2093+ const modifierLabel = isMacPlatform ( navigator . platform ) ? "⌘" : "Ctrl" ;
2094+ const sendShortcutOptions = [
2095+ { value : "enter" , label : "Enter" } ,
2096+ { value : "mod-enter-multiline" , label : `${ modifierLabel } + Enter for multiline prompts` } ,
2097+ { value : "mod-enter" , label : `${ modifierLabel } + Enter always` } ,
2098+ ] as const ;
20892099 const settings = useScopedSettings ( ) ;
20902100 const updateSettings = useUpdateScopedSettings ( ) ;
20912101 const navigate = useNavigate ( ) ;
@@ -2594,9 +2604,61 @@ export function GeneralSettingsPanel() {
25942604 }
25952605 />
25962606
2607+ < SettingsRow
2608+ { ...searchableSetting ( "send-shortcut" ) }
2609+ description = "Choose when Enter sends a prompt or inserts a new line"
2610+ resetAction = {
2611+ settings . sendShortcut !== DEFAULT_UNIFIED_SETTINGS . sendShortcut ? (
2612+ < SettingResetButton
2613+ label = "send shortcut"
2614+ onClick = { ( ) =>
2615+ updateSettings ( { sendShortcut : DEFAULT_UNIFIED_SETTINGS . sendShortcut } )
2616+ }
2617+ />
2618+ ) : null
2619+ }
2620+ control = {
2621+ < Select
2622+ value = { settings . sendShortcut }
2623+ onValueChange = { ( value ) => {
2624+ const option = sendShortcutOptions . find ( ( option ) => option . value === value ) ;
2625+ if ( option ) updateSettings ( { sendShortcut : option . value } ) ;
2626+ } }
2627+ >
2628+ < SelectTrigger
2629+ size = "sm"
2630+ className = "w-auto min-w-0 max-w-full"
2631+ aria-label = "Send shortcut"
2632+ >
2633+ < SelectValue >
2634+ {
2635+ sendShortcutOptions . find ( ( option ) => option . value === settings . sendShortcut )
2636+ ?. label
2637+ }
2638+ </ SelectValue >
2639+ </ SelectTrigger >
2640+ < SelectPopup align = "end" alignItemWithTrigger = { false } >
2641+ { sendShortcutOptions . map ( ( option ) => (
2642+ < SelectItem key = { option . value } value = { option . value } >
2643+ < span className = "flex items-center justify-between gap-4" >
2644+ { option . label }
2645+ { settings . sendShortcut === option . value && < CheckIcon aria-hidden = "true" /> }
2646+ </ span >
2647+ </ SelectItem >
2648+ ) ) }
2649+ </ SelectPopup >
2650+ </ Select >
2651+ }
2652+ />
2653+
25972654 < SettingsRow
25982655 { ...searchableSetting ( "follow-up-behavior" ) }
2599- description = "Queue follow-ups while the agent runs or steer the current turn."
2656+ description = {
2657+ "Queue follow-ups while the agent runs or steer the current run. " +
2658+ ( settings . sendShortcut === "mod-enter-multiline"
2659+ ? `Press ${ modifierLabel } + Enter for single-line prompts or ${ modifierLabel } + Shift + Enter for multiline prompts to do the opposite for one message.`
2660+ : `Press ${ modifierLabel } ${ settings . sendShortcut === "mod-enter" ? " + Shift" : "" } + Enter to do the opposite for one message.` )
2661+ }
26002662 resetAction = {
26012663 settings . followUpBehavior !== DEFAULT_UNIFIED_SETTINGS . followUpBehavior ? (
26022664 < SettingResetButton
@@ -2610,28 +2672,23 @@ export function GeneralSettingsPanel() {
26102672 ) : null
26112673 }
26122674 control = {
2613- < Select
2614- value = { settings . followUpBehavior }
2615- onValueChange = { ( value ) => {
2675+ < ToggleGroup
2676+ aria-label = "Follow-up behavior"
2677+ variant = "default"
2678+ value = { [ settings . followUpBehavior ] }
2679+ onValueChange = { ( values ) => {
2680+ const value = values [ 0 ] ;
26162681 if ( value === "queue" || value === "steer" ) {
26172682 updateSettings ( { followUpBehavior : value } ) ;
26182683 }
26192684 } }
26202685 >
2621- < SelectTrigger size = "sm" className = "w-full sm:w-40" aria-label = "Follow-up behavior" >
2622- < SelectValue >
2623- { settings . followUpBehavior === "queue" ? "Queue" : "Steer" }
2624- </ SelectValue >
2625- </ SelectTrigger >
2626- < SelectPopup align = "end" alignItemWithTrigger = { false } >
2627- < SelectItem hideIndicator value = "queue" >
2628- Queue
2629- </ SelectItem >
2630- < SelectItem hideIndicator value = "steer" >
2631- Steer
2632- </ SelectItem >
2633- </ SelectPopup >
2634- </ Select >
2686+ { ( [ "queue" , "steer" ] as const ) . map ( ( value ) => (
2687+ < Toggle key = { value } value = { value } variant = "pill" >
2688+ { value === "queue" ? "Queue" : "Steer" }
2689+ </ Toggle >
2690+ ) ) }
2691+ </ ToggleGroup >
26352692 }
26362693 />
26372694
0 commit comments