fix(chat): tidy composer pickers

This commit is contained in:
Bohdan Triapitsyn
2026-08-21 13:10:48 +03:00
parent 59df2963ae
commit 2766e9fd8c
4 changed files with 37 additions and 18 deletions
@@ -57,6 +57,28 @@ type MobileVariantTarget = { providerId: string; modelId: string };
const buildModelRefKey = (providerID: string, modelID: string) => `${providerID}:${modelID}`; const buildModelRefKey = (providerID: string, modelID: string) => `${providerID}:${modelID}`;
const MAX_INLINE_MOBILE_VARIANT_OPTIONS = 6; const MAX_INLINE_MOBILE_VARIANT_OPTIONS = 6;
const AgentDescriptionTooltip: React.FC<{
description?: string;
children: React.ReactElement;
}> = ({ description, children }) => {
if (!description) {
return children;
}
return (
<Tooltip delayDuration={450}>
<TooltipTrigger asChild>{children}</TooltipTrigger>
<TooltipContent
side="right"
sideOffset={8}
className="max-w-xs text-left transition-none data-[starting-style]:opacity-100 data-[starting-style]:scale-100 data-[ending-style]:opacity-100 data-[ending-style]:scale-100"
>
<span className="typography-meta text-muted-foreground">{description}</span>
</TooltipContent>
</Tooltip>
);
};
const asPermissionRuleset = (value: unknown): PermissionRule[] | null => { const asPermissionRuleset = (value: unknown): PermissionRule[] | null => {
if (!Array.isArray(value)) { if (!Array.isArray(value)) {
return null; return null;
@@ -2316,6 +2338,7 @@ export const ModelControls: React.FC<ModelControlsProps> = ({
</DropdownMenuTrigger> </DropdownMenuTrigger>
</TooltipTrigger> </TooltipTrigger>
<DropdownMenuContent <DropdownMenuContent
side="top"
className="w-[min(380px,calc(100vw-2rem))] p-0 flex flex-col" className="w-[min(380px,calc(100vw-2rem))] p-0 flex flex-col"
align="end" align="end"
alignOffset={-40} alignOffset={-40}
@@ -2618,7 +2641,7 @@ export const ModelControls: React.FC<ModelControlsProps> = ({
</div> </div>
</DropdownMenuTrigger> </DropdownMenuTrigger>
</TooltipTrigger> </TooltipTrigger>
<DropdownMenuContent align="end" alignOffset={-40} className="w-[min(180px,calc(100vw-2rem))]"> <DropdownMenuContent side="top" align="end" alignOffset={-40} className="w-[min(180px,calc(100vw-2rem))]">
<DropdownMenuLabel className="typography-ui-header font-semibold text-foreground">{t('chat.modelControls.thinking')}</DropdownMenuLabel> <DropdownMenuLabel className="typography-ui-header font-semibold text-foreground">{t('chat.modelControls.thinking')}</DropdownMenuLabel>
<DropdownMenuItem className="typography-meta" onSelect={() => handleVariantSelect(undefined)}> <DropdownMenuItem className="typography-meta" onSelect={() => handleVariantSelect(undefined)}>
<div className="flex items-center justify-between gap-2 w-full min-w-0"> <div className="flex items-center justify-between gap-2 w-full min-w-0">
@@ -2708,7 +2731,7 @@ export const ModelControls: React.FC<ModelControlsProps> = ({
</div> </div>
</DropdownMenuTrigger> </DropdownMenuTrigger>
</TooltipTrigger> </TooltipTrigger>
<DropdownMenuContent align="end" alignOffset={-40} className="w-[min(280px,calc(100vw-2rem))] p-0 flex flex-col"> <DropdownMenuContent side="top" align="end" alignOffset={-40} className="w-[min(280px,calc(100vw-2rem))] p-0 flex flex-col">
<div className="p-2 border-b border-border/40"> <div className="p-2 border-b border-border/40">
<div className="relative"> <div className="relative">
<Icon name="search" className="absolute left-2.5 top-1/2 -translate-y-1/2 size-3.5 text-muted-foreground" /> <Icon name="search" className="absolute left-2.5 top-1/2 -translate-y-1/2 size-3.5 text-muted-foreground" />
@@ -2746,12 +2769,11 @@ export const ModelControls: React.FC<ModelControlsProps> = ({
</div> </div>
) : ( ) : (
sortedAndFilteredAgents.map((agent) => ( sortedAndFilteredAgents.map((agent) => (
<DropdownMenuItem <AgentDescriptionTooltip key={agent.name} description={agent.description}>
key={agent.name} <DropdownMenuItem
className="typography-meta" className="typography-meta"
onSelect={() => handleAgentChange(agent.name)} onSelect={() => handleAgentChange(agent.name)}
> >
<div className="flex flex-col gap-0.5">
<div className="flex items-center gap-1.5"> <div className="flex items-center gap-1.5">
<div className={cn( <div className={cn(
'h-1 w-1 rounded-full agent-dot', 'h-1 w-1 rounded-full agent-dot',
@@ -2759,13 +2781,8 @@ export const ModelControls: React.FC<ModelControlsProps> = ({
)} /> )} />
<span className="font-medium">{capitalizeAgentName(agent.name)}</span> <span className="font-medium">{capitalizeAgentName(agent.name)}</span>
</div> </div>
{agent.description && ( </DropdownMenuItem>
<span className="typography-meta text-muted-foreground max-w-[200px] ml-2.5 break-words"> </AgentDescriptionTooltip>
{agent.description}
</span>
)}
</div>
</DropdownMenuItem>
)) ))
)} )}
</div> </div>
@@ -89,7 +89,7 @@ export const ComposerAttachmentControls = React.memo(function ComposerAttachment
<Icon name="add-circle" className={cn(iconSizeClass, 'text-current')} /> <Icon name="add-circle" className={cn(iconSizeClass, 'text-current')} />
</button> </button>
</DropdownMenuTrigger> </DropdownMenuTrigger>
<DropdownMenuContent align="start"> <DropdownMenuContent side="top" align="start">
<DropdownMenuItem <DropdownMenuItem
onSelect={() => { onSelect={() => {
requestAnimationFrame(handlePickLocalFiles); requestAnimationFrame(handlePickLocalFiles);
@@ -122,7 +122,7 @@ export function DraftTargetSelectors(props: DraftTargetProps) {
: <ProjectLabel project={selectedProject} theme={theme} />} : <ProjectLabel project={selectedProject} theme={theme} />}
</SelectValue> </SelectValue>
</SelectTrigger> </SelectTrigger>
<SelectContent fitContent> <SelectContent side="top" fitContent>
{projects.map((project) => ( {projects.map((project) => (
<SelectItem key={project.id} value={project.id} className="max-w-[24rem] truncate"> <SelectItem key={project.id} value={project.id} className="max-w-[24rem] truncate">
<ProjectLabel project={project} theme={theme} /> <ProjectLabel project={project} theme={theme} />
@@ -144,7 +144,7 @@ export function DraftTargetSelectors(props: DraftTargetProps) {
{selectedBranchLabel ?? t('chat.chatInput.branch')} {selectedBranchLabel ?? t('chat.chatInput.branch')}
</SelectValue> </SelectValue>
</SelectTrigger> </SelectTrigger>
<SelectContent className="w-max min-w-48"> <SelectContent side="top" className="w-max min-w-48">
{projectRootBranchOption ? ( {projectRootBranchOption ? (
<SelectGroup> <SelectGroup>
<SelectLabel>{t('chat.chatInput.projectRoot')}</SelectLabel> <SelectLabel>{t('chat.chatInput.projectRoot')}</SelectLabel>
@@ -21,6 +21,7 @@ import { getRegisteredRuntimeAPIs } from '@/contexts/runtimeAPIRegistry';
import { useI18n } from '@/lib/i18n'; import { useI18n } from '@/lib/i18n';
import { parseModelIdentifier } from '@/lib/modelIdentifier'; import { parseModelIdentifier } from '@/lib/modelIdentifier';
import { runtimeFetch } from '@/lib/runtime-fetch'; import { runtimeFetch } from '@/lib/runtime-fetch';
import { isPrimaryMode } from '@/components/chat/mobileControlsUtils';
const getDisplayModel = ( const getDisplayModel = (
storedModel: string | undefined storedModel: string | undefined
@@ -390,6 +391,7 @@ export const DefaultsSettings: React.FC = () => {
<AgentSelector <AgentSelector
agentName={defaultAgent || ''} agentName={defaultAgent || ''}
onChange={handleAgentChange} onChange={handleAgentChange}
filter={(agent) => isPrimaryMode(agent.mode)}
className={SETTINGS_CUSTOM_TRIGGER_CLASS} className={SETTINGS_CUSTOM_TRIGGER_CLASS}
/> />
</SettingsFieldRow> </SettingsFieldRow>