From 07b750eea8902de6dab2326bf4bae946f7cd5851 Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Wed, 23 Sep 2026 18:21:24 -0700 Subject: [PATCH] fix(chat): keep organization composer controls within narrow panels --- .../components/composer/composer.test.tsx | 2 + .../components/growing-textarea.tsx | 6 ++- .../user-input/components/input-toolbar.tsx | 10 ++-- .../user-input/components/model-selector.tsx | 51 +++++++++++-------- .../components/model-setting-trigger.tsx | 49 ++++++++++++++++++ 5 files changed, 90 insertions(+), 28 deletions(-) create mode 100644 apps/sim/app/workspace/[workspaceId]/home/components/user-input/components/model-setting-trigger.tsx diff --git a/apps/sim/app/o/[organizationId]/home/components/composer/composer.test.tsx b/apps/sim/app/o/[organizationId]/home/components/composer/composer.test.tsx index b0c2be8cc9b..e06572cab86 100644 --- a/apps/sim/app/o/[organizationId]/home/components/composer/composer.test.tsx +++ b/apps/sim/app/o/[organizationId]/home/components/composer/composer.test.tsx @@ -883,6 +883,8 @@ it('offers the advanced models and each model’s supported efforts', async () = await act(async () => model.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter', bubbles: true })) ) + expect(document.body.style.pointerEvents).not.toBe('none') + expect(model.getAttribute('aria-description')).toBe('GPT-6 Astra') const models = [...document.querySelectorAll('[role="menuitem"]')] expect(models.map((item) => item.textContent)).toEqual(['GPT-6 Astra', 'GPT-6 Sol', 'Opus 5.5']) await act(async () => models[1].click()) diff --git a/apps/sim/app/workspace/[workspaceId]/home/components/user-input/components/growing-textarea.tsx b/apps/sim/app/workspace/[workspaceId]/home/components/user-input/components/growing-textarea.tsx index 2bdcae19508..fe107decf8a 100644 --- a/apps/sim/app/workspace/[workspaceId]/home/components/user-input/components/growing-textarea.tsx +++ b/apps/sim/app/workspace/[workspaceId]/home/components/user-input/components/growing-textarea.tsx @@ -28,7 +28,11 @@ export function GrowingTextarea({ ref={inputRef} value={value} rows={1} - className={cn(TEXTAREA_BASE_CLASSES, compact && 'px-0 py-[3px]', className)} + className={cn( + TEXTAREA_BASE_CLASSES, + compact && 'whitespace-pre px-0 py-[3px] [overflow-wrap:normal]', + className + )} /> ) } diff --git a/apps/sim/app/workspace/[workspaceId]/home/components/user-input/components/input-toolbar.tsx b/apps/sim/app/workspace/[workspaceId]/home/components/user-input/components/input-toolbar.tsx index 57a664e9b09..f637b3286e3 100644 --- a/apps/sim/app/workspace/[workspaceId]/home/components/user-input/components/input-toolbar.tsx +++ b/apps/sim/app/workspace/[workspaceId]/home/components/user-input/components/input-toolbar.tsx @@ -36,14 +36,14 @@ export function InputToolbar({
{(selectionControl || showModelSelector || voiceControl) && ( -
+
{selectionControl ?? (showModelSelector && )} {voiceControl}
diff --git a/apps/sim/app/workspace/[workspaceId]/home/components/user-input/components/model-selector.tsx b/apps/sim/app/workspace/[workspaceId]/home/components/user-input/components/model-selector.tsx index 36c92af7c10..9ba8dfaf2e9 100644 --- a/apps/sim/app/workspace/[workspaceId]/home/components/user-input/components/model-selector.tsx +++ b/apps/sim/app/workspace/[workspaceId]/home/components/user-input/components/model-selector.tsx @@ -1,14 +1,13 @@ 'use client' import { - Chip, - ChipDropdown, DropdownMenu, DropdownMenuContent, DropdownMenuItem, + DropdownMenuItemLabel, DropdownMenuRadioGroup, - DropdownMenuTrigger, } from '@sim/emcn' +import { Brain, Check, Sparkles } from '@sim/emcn/icons' import { MOTHERSHIP_MODEL_OPTIONS, MOTHERSHIP_SIMPLE_EFFORT_OPTIONS, @@ -16,10 +15,11 @@ import { resolveMothershipModelSettings, } from '@/lib/mothership/model-options' import { FastModeToggle } from '@/app/workspace/[workspaceId]/home/components/user-input/components/fast-mode-toggle' +import { ModelSettingTrigger } from '@/app/workspace/[workspaceId]/home/components/user-input/components/model-setting-trigger' import { useFeatureFlag } from '@/app/workspace/[workspaceId]/providers/feature-flags-provider' import { useMothershipEffortStore } from '@/stores/mothership-effort/store' -/** Reasoning effort and Fast mode for Build chat composers. */ +/** Model, reasoning effort, and Fast mode for Build chat composers. */ export function ModelSelector() { const advanced = useFeatureFlag('mothership-model-selector') const selection = useMothershipEffortStore((state) => state.modelSelection) @@ -34,8 +34,13 @@ export function ModelSelector() { ? mothershipEffortOptions(modelSelection.model) : MOTHERSHIP_SIMPLE_EFFORT_OPTIONS const setEffort = useMothershipEffortStore((state) => state.setEffort) + const effortLabel = options.find((option) => option.value === effort)?.label ?? effort + const modelLabel = + MOTHERSHIP_MODEL_OPTIONS.find((option) => option.value === modelSelection.model)?.label ?? + modelSelection.model + return ( -
+
{advanced && ( <> {modelSelection.model !== 'claude-opus-5-5' && ( @@ -45,26 +50,28 @@ export function ModelSelector() { description='Faster responses at a higher price' /> )} - { - const model = MOTHERSHIP_MODEL_OPTIONS.find((option) => option.value === value) - if (model) setModel(model.value) - }} - /> + + + + {MOTHERSHIP_MODEL_OPTIONS.map((option) => ( + setModel(option.value)}> + + {modelSelection.model === option.value && ( + + )} + + ))} + + )} - - - {options.find((option) => option.value === effort)?.label} - - + {options.map((option) => ( diff --git a/apps/sim/app/workspace/[workspaceId]/home/components/user-input/components/model-setting-trigger.tsx b/apps/sim/app/workspace/[workspaceId]/home/components/user-input/components/model-setting-trigger.tsx new file mode 100644 index 00000000000..4123a811c89 --- /dev/null +++ b/apps/sim/app/workspace/[workspaceId]/home/components/user-input/components/model-setting-trigger.tsx @@ -0,0 +1,49 @@ +import type { ComponentType } from 'react' +import { Chip, chipContentLabelClass, DropdownMenuTrigger, OverflowText, Tooltip } from '@sim/emcn' +import { ChevronDown } from '@sim/emcn/icons' + +interface ModelSettingTriggerProps { + label: string + valueLabel: string + icon: ComponentType<{ className?: string }> + showChevron?: boolean +} + +/** Keeps one accessible trigger while replacing its label with an icon in narrow composers. */ +export function ModelSettingTrigger({ + label, + valueLabel, + icon: Icon, + showChevron = false, +}: ModelSettingTriggerProps) { + return ( + + + + + + + + {showChevron && ( + + )} + + + } + /> + + + + {label}: {valueLabel} + + + ) +}