feat: add 'Customise' option to variants dropdown (#2116)

Add a 'Customise' menu item to the variants dropdown in the chat box
that navigates users to the Agent Settings page (/settings/agents)
where they can configure executor variants.

- Add onCustomise callback to VariantProps interface in ChatBoxBase
- Render separator and Customise option with gear icon in dropdown
- Add navigation handler in SessionChatBoxContainer and CreateChatBoxContainer
- Add i18n translations for all supported locales

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Louis Knight-Webb
2026-01-17 13:30:25 +00:00
committed by GitHub
parent 14c9df626a
commit 6f7b0b6ebc
9 changed files with 46 additions and 8 deletions

View File

@@ -1,4 +1,5 @@
import { useMemo, useCallback, useState, useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import { useCreateMode } from '@/contexts/CreateModeContext';
import { useUserSystem } from '@/components/ConfigProvider';
@@ -11,6 +12,7 @@ import { CreateChatBox } from '../primitives/CreateChatBox';
export function CreateChatBoxContainer() {
const { t } = useTranslation('common');
const navigate = useNavigate();
const { profiles, config, updateAndSaveConfig } = useUserSystem();
const {
repos,
@@ -100,6 +102,11 @@ export function CreateChatBoxContainer() {
[effectiveProfile, setSelectedProfile]
);
// Navigate to agent settings to customise variants
const handleCustomise = useCallback(() => {
navigate('/settings/agents');
}, [navigate]);
// Handle executor change - use saved variant if switching to default executor
const handleExecutorChange = useCallback(
(executor: BaseCodingAgent) => {
@@ -235,6 +242,7 @@ export function CreateChatBoxContainer() {
selected: effectiveProfile.variant ?? 'DEFAULT',
options: variantOptions,
onChange: handleVariantChange,
onCustomise: handleCustomise,
}
: undefined
}

View File

@@ -1,4 +1,5 @@
import { useCallback, useEffect, useMemo, useRef } from 'react';
import { useNavigate } from 'react-router-dom';
import { useQueryClient } from '@tanstack/react-query';
import {
type Session,
@@ -122,6 +123,7 @@ export function SessionChatBoxContainer(props: SessionChatBoxContainerProps) {
const sessionId = session?.id;
const queryClient = useQueryClient();
const navigate = useNavigate();
const { executeAction } = useActions();
const actionCtx = useActionVisibilityContext();
@@ -307,6 +309,11 @@ export function SessionChatBoxContainer(props: SessionChatBoxContainerProps) {
[setVariantFromHook, saveToScratch, localMessage]
);
// Navigate to agent settings to customise variants
const handleCustomise = useCallback(() => {
navigate('/settings/agents');
}, [navigate]);
// Queue interaction
const {
isQueued,
@@ -638,6 +645,7 @@ export function SessionChatBoxContainer(props: SessionChatBoxContainerProps) {
selected: selectedVariant,
options: variantOptions,
onChange: setSelectedVariant,
onCustomise: handleCustomise,
}}
session={{
sessions,

View File

@@ -1,12 +1,16 @@
import { type ReactNode } from 'react';
import { CheckIcon } from '@phosphor-icons/react';
import { CheckIcon, GearIcon } from '@phosphor-icons/react';
import { useTranslation } from 'react-i18next';
import { cn } from '@/lib/utils';
import { toPrettyCase } from '@/utils/string';
import WYSIWYGEditor from '@/components/ui/wysiwyg';
import type { LocalImageMetadata } from '@/components/ui/wysiwyg/context/task-attempt-context';
import { Toolbar, ToolbarDropdown } from './Toolbar';
import { DropdownMenuItem, DropdownMenuLabel } from './Dropdown';
import {
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
} from './Dropdown';
export interface EditorProps {
value: string;
@@ -17,6 +21,7 @@ export interface VariantProps {
selected: string | null;
options: string[];
onChange: (variant: string | null) => void;
onCustomise?: () => void;
}
export enum VisualVariant {
@@ -173,6 +178,17 @@ export function ChatBoxBase({
{toPrettyCase(variantName)}
</DropdownMenuItem>
))}
{variant?.onCustomise && (
<>
<DropdownMenuSeparator />
<DropdownMenuItem
icon={GearIcon}
onClick={variant.onCustomise}
>
{t('chatBox.customise')}
</DropdownMenuItem>
</>
)}
</ToolbarDropdown>
)}
{footerLeft}

View File

@@ -204,7 +204,8 @@
"defaultPlaceholder": "Type a command or search..."
},
"chatBox": {
"variants": "Variants"
"variants": "Variants",
"customise": "Customise"
},
"projects": {
"noProjectFound": "No project found",

View File

@@ -204,7 +204,8 @@
"defaultPlaceholder": "Escribe un comando o busca..."
},
"chatBox": {
"variants": "Variantes"
"variants": "Variantes",
"customise": "Personalizar"
},
"projects": {
"noProjectFound": "No se encontró ningún proyecto",

View File

@@ -204,7 +204,8 @@
"defaultPlaceholder": "コマンドを入力または検索..."
},
"chatBox": {
"variants": "バリアント"
"variants": "バリアント",
"customise": "カスタマイズ"
},
"projects": {
"noProjectFound": "プロジェクトが見つかりません",

View File

@@ -204,7 +204,8 @@
"defaultPlaceholder": "명령어를 입력하거나 검색..."
},
"chatBox": {
"variants": "변형"
"variants": "변형",
"customise": "사용자 지정"
},
"projects": {
"noProjectFound": "프로젝트를 찾을 수 없습니다",

View File

@@ -204,7 +204,8 @@
"defaultPlaceholder": "输入命令或搜索..."
},
"chatBox": {
"variants": "变体"
"variants": "变体",
"customise": "自定义"
},
"projects": {
"noProjectFound": "未找到项目",

View File

@@ -204,7 +204,8 @@
"defaultPlaceholder": "輸入命令或搜尋..."
},
"chatBox": {
"variants": "變體"
"variants": "變體",
"customise": "自訂"
},
"projects": {
"noProjectFound": "找不到專案",