Skip to content

Commit c510377

Browse files
authored
fix(chat): keep organization composer controls within narrow panels (#8217)
1 parent 3c3770a commit c510377

5 files changed

Lines changed: 90 additions & 28 deletions

File tree

apps/sim/app/o/[organizationId]/home/components/composer/composer.test.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -883,6 +883,8 @@ it('offers the advanced models and each model’s supported efforts', async () =
883883
await act(async () =>
884884
model.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter', bubbles: true }))
885885
)
886+
expect(document.body.style.pointerEvents).not.toBe('none')
887+
expect(model.getAttribute('aria-description')).toBe('GPT-6 Astra')
886888
const models = [...document.querySelectorAll<HTMLElement>('[role="menuitem"]')]
887889
expect(models.map((item) => item.textContent)).toEqual(['GPT-6 Astra', 'GPT-6 Sol', 'Opus 5.5'])
888890
await act(async () => models[1].click())

apps/sim/app/workspace/[workspaceId]/home/components/user-input/components/growing-textarea.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,11 @@ export function GrowingTextarea({
2828
ref={inputRef}
2929
value={value}
3030
rows={1}
31-
className={cn(TEXTAREA_BASE_CLASSES, compact && 'px-0 py-[3px]', className)}
31+
className={cn(
32+
TEXTAREA_BASE_CLASSES,
33+
compact && 'whitespace-pre px-0 py-[3px] [overflow-wrap:normal]',
34+
className
35+
)}
3236
/>
3337
)
3438
}

apps/sim/app/workspace/[workspaceId]/home/components/user-input/components/input-toolbar.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,14 @@ export function InputToolbar({
3636
<div
3737
className={
3838
editor
39-
? 'grid grid-cols-[auto_minmax(0,1fr)_auto] items-end gap-x-3'
40-
: 'flex items-center justify-between'
39+
? '@container/input-toolbar grid grid-cols-[auto_minmax(0,1fr)_auto] items-end gap-x-3'
40+
: '@container/input-toolbar flex flex-wrap items-center justify-between gap-y-1'
4141
}
4242
>
4343
<div
4444
ref={leadingRef}
4545
className={cn(
46-
'flex h-[30px] items-center gap-1',
46+
'flex h-[30px] shrink-0 items-center @max-[280px]/input-toolbar:gap-0 gap-1',
4747
editor && 'col-start-1',
4848
editor && (expanded ? 'row-start-2' : 'row-start-1')
4949
)}
@@ -60,15 +60,15 @@ export function InputToolbar({
6060
<div
6161
ref={trailingRef}
6262
className={cn(
63-
'flex h-[30px] items-center gap-1.5',
63+
'ml-auto flex h-[30px] shrink-0 items-center @max-[280px]/input-toolbar:gap-0 gap-1',
6464
editor && 'col-start-3',
6565
editor && (expanded ? 'row-start-2' : 'row-start-1')
6666
)}
6767
>
6868
{trailingControls ?? (
6969
<>
7070
{(selectionControl || showModelSelector || voiceControl) && (
71-
<div className='flex items-center'>
71+
<div className='flex items-center gap-[inherit]'>
7272
{selectionControl ?? (showModelSelector && <ModelSelector />)}
7373
{voiceControl}
7474
</div>

apps/sim/app/workspace/[workspaceId]/home/components/user-input/components/model-selector.tsx

Lines changed: 29 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,25 @@
11
'use client'
22

33
import {
4-
Chip,
5-
ChipDropdown,
64
DropdownMenu,
75
DropdownMenuContent,
86
DropdownMenuItem,
7+
DropdownMenuItemLabel,
98
DropdownMenuRadioGroup,
10-
DropdownMenuTrigger,
119
} from '@sim/emcn'
10+
import { Brain, Check, Sparkles } from '@sim/emcn/icons'
1211
import {
1312
MOTHERSHIP_MODEL_OPTIONS,
1413
MOTHERSHIP_SIMPLE_EFFORT_OPTIONS,
1514
mothershipEffortOptions,
1615
resolveMothershipModelSettings,
1716
} from '@/lib/mothership/model-options'
1817
import { FastModeToggle } from '@/app/workspace/[workspaceId]/home/components/user-input/components/fast-mode-toggle'
18+
import { ModelSettingTrigger } from '@/app/workspace/[workspaceId]/home/components/user-input/components/model-setting-trigger'
1919
import { useFeatureFlag } from '@/app/workspace/[workspaceId]/providers/feature-flags-provider'
2020
import { useMothershipEffortStore } from '@/stores/mothership-effort/store'
2121

22-
/** Reasoning effort and Fast mode for Build chat composers. */
22+
/** Model, reasoning effort, and Fast mode for Build chat composers. */
2323
export function ModelSelector() {
2424
const advanced = useFeatureFlag('mothership-model-selector')
2525
const selection = useMothershipEffortStore((state) => state.modelSelection)
@@ -34,8 +34,13 @@ export function ModelSelector() {
3434
? mothershipEffortOptions(modelSelection.model)
3535
: MOTHERSHIP_SIMPLE_EFFORT_OPTIONS
3636
const setEffort = useMothershipEffortStore((state) => state.setEffort)
37+
const effortLabel = options.find((option) => option.value === effort)?.label ?? effort
38+
const modelLabel =
39+
MOTHERSHIP_MODEL_OPTIONS.find((option) => option.value === modelSelection.model)?.label ??
40+
modelSelection.model
41+
3742
return (
38-
<div className='flex items-center'>
43+
<div className='flex items-center gap-[inherit]'>
3944
{advanced && (
4045
<>
4146
{modelSelection.model !== 'claude-opus-5-5' && (
@@ -45,26 +50,28 @@ export function ModelSelector() {
4550
description='Faster responses at a higher price'
4651
/>
4752
)}
48-
<ChipDropdown
49-
variant='default'
50-
className='border-0'
51-
aria-label='Model'
52-
value={modelSelection.model}
53-
options={MOTHERSHIP_MODEL_OPTIONS}
54-
matchTriggerWidth={false}
55-
onChange={(value) => {
56-
const model = MOTHERSHIP_MODEL_OPTIONS.find((option) => option.value === value)
57-
if (model) setModel(model.value)
58-
}}
59-
/>
53+
<DropdownMenu modal={false}>
54+
<ModelSettingTrigger
55+
label='Model'
56+
valueLabel={modelLabel}
57+
icon={Sparkles}
58+
showChevron
59+
/>
60+
<DropdownMenuContent side='top' align='end'>
61+
{MOTHERSHIP_MODEL_OPTIONS.map((option) => (
62+
<DropdownMenuItem key={option.value} onSelect={() => setModel(option.value)}>
63+
<DropdownMenuItemLabel label={option.label} />
64+
{modelSelection.model === option.value && (
65+
<Check className='ml-auto! size-[16px]!' />
66+
)}
67+
</DropdownMenuItem>
68+
))}
69+
</DropdownMenuContent>
70+
</DropdownMenu>
6071
</>
6172
)}
6273
<DropdownMenu>
63-
<DropdownMenuTrigger asChild>
64-
<Chip aria-label='Reasoning effort' className={advanced ? undefined : '-ml-2'}>
65-
{options.find((option) => option.value === effort)?.label}
66-
</Chip>
67-
</DropdownMenuTrigger>
74+
<ModelSettingTrigger label='Reasoning effort' valueLabel={effortLabel} icon={Brain} />
6875
<DropdownMenuContent side='top' align='start'>
6976
<DropdownMenuRadioGroup aria-label='Reasoning effort'>
7077
{options.map((option) => (
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import type { ComponentType } from 'react'
2+
import { Chip, chipContentLabelClass, DropdownMenuTrigger, OverflowText, Tooltip } from '@sim/emcn'
3+
import { ChevronDown } from '@sim/emcn/icons'
4+
5+
interface ModelSettingTriggerProps {
6+
label: string
7+
valueLabel: string
8+
icon: ComponentType<{ className?: string }>
9+
showChevron?: boolean
10+
}
11+
12+
/** Keeps one accessible trigger while replacing its label with an icon in narrow composers. */
13+
export function ModelSettingTrigger({
14+
label,
15+
valueLabel,
16+
icon: Icon,
17+
showChevron = false,
18+
}: ModelSettingTriggerProps) {
19+
return (
20+
<Tooltip.Root preferAbove>
21+
<Tooltip.Trigger asChild>
22+
<DropdownMenuTrigger asChild>
23+
<Chip
24+
aria-label={label}
25+
aria-description={valueLabel}
26+
leftAdornment={
27+
<>
28+
<Icon className='@max-[320px]/input-toolbar:block hidden size-[14px] text-[var(--text-icon)]' />
29+
<span className='flex @max-[320px]/input-toolbar:hidden min-w-0 items-center gap-2'>
30+
<OverflowText
31+
label={valueLabel}
32+
className={chipContentLabelClass}
33+
focusTarget='nearest-interactive'
34+
/>
35+
{showChevron && (
36+
<ChevronDown className='size-[14px] shrink-0 text-[var(--text-icon)]' />
37+
)}
38+
</span>
39+
</>
40+
}
41+
/>
42+
</DropdownMenuTrigger>
43+
</Tooltip.Trigger>
44+
<Tooltip.Content>
45+
{label}: {valueLabel}
46+
</Tooltip.Content>
47+
</Tooltip.Root>
48+
)
49+
}

0 commit comments

Comments
 (0)