feat: group chat visual settings into labeled sections

Adds section headers and tooltip help for the goal settings area
Reorganizes chat settings into Session Assistance, Reasoning, Message Appearance, Tools & Files, and Composer groups
Adds localized labels and search entries for the new section headings
This commit is contained in:
Bohdan Triapitsyn
2026-07-13 01:33:19 +03:00
parent 9b645f0e53
commit 9dd389fe8e
12 changed files with 143 additions and 34 deletions
@@ -1824,11 +1824,18 @@ export const OpenChamberVisualSettings: React.FC<OpenChamberVisualSettingsProps>
{/* The goal loop runs in the web server — VS Code only renders
goal state, so the settings section is hidden there too. */}
{shouldShow('sessionGoal') && !isVSCode && (
<div className="mb-8">
<div className="mb-1 px-1">
<section className="p-2 mb-6 space-y-0.5">
<div className="flex items-center gap-1.5 py-1.5">
<h3 className="typography-ui-header font-medium text-foreground">{t('settings.openchamber.visual.goal.sectionTitle')}</h3>
<Tooltip>
<TooltipTrigger asChild>
<Icon name="information" className="h-3.5 w-3.5 cursor-help text-muted-foreground/60" />
</TooltipTrigger>
<TooltipContent sideOffset={8} className="max-w-sm">
{t('settings.openchamber.visual.goal.description')}
</TooltipContent>
</Tooltip>
</div>
<section className="p-2 space-y-0.5">
<div
data-settings-item="chat.session-goal"
className="group flex cursor-pointer items-center gap-2 py-0.5"
@@ -1891,14 +1898,15 @@ export const OpenChamberVisualSettings: React.FC<OpenChamberVisualSettingsProps>
/>
) : null}
</div>
<p className="typography-meta text-muted-foreground/70 px-0.5 pt-0.5">{t('settings.openchamber.visual.goal.description')}</p>
</section>
</div>
</section>
)}
{(shouldShow('sessionAssist') || shouldShow('collapsibleUserMessages') || shouldShow('stickyUserHeader') || shouldShow('wideChatLayout') || shouldShow('codeBlockLineWrap') || shouldShow('splitAssistantMessageActions') || shouldShow('subagentReadOnlyBanner') || shouldShow('dotfiles') || shouldShow('fileViewerPreview') || shouldShow('persistDraft') || shouldShow('showToolFileIcons') || shouldShow('showTurnChangedFiles') || (!isMobile && shouldShow('inputSpellcheck')) || shouldShow('reasoning')) && (
<section className="p-2 space-y-0.5">
{shouldShow('sessionAssist') && (
<div className="space-y-6">
{(shouldShow('sessionAssist') || shouldShow('subagentReadOnlyBanner')) && (
<section className="p-2 space-y-0.5">
<h3 data-settings-item="chat.session-assistance" className="typography-ui-header font-medium text-foreground py-1.5">{t('settings.openchamber.visual.section.sessionAssistance')}</h3>
{shouldShow('sessionAssist') && (
<>
<div
data-settings-item="chat.session-recap"
@@ -1943,7 +1951,35 @@ export const OpenChamberVisualSettings: React.FC<OpenChamberVisualSettingsProps>
<span className="typography-ui-label text-foreground">{t('settings.openchamber.visual.field.sessionSuggestion')}</span>
</div>
</>
)}
{shouldShow('subagentReadOnlyBanner') && (
<div
data-settings-item="chat.subagent-read-only-banner"
className="group flex cursor-pointer items-center gap-2 py-0.5"
role="button"
tabIndex={0}
aria-pressed={allowPromptingSubagentSessions}
onClick={() => setAllowPromptingSubagentSessions(!allowPromptingSubagentSessions)}
onKeyDown={(event) => {
if (event.key === ' ' || event.key === 'Enter') {
event.preventDefault();
setAllowPromptingSubagentSessions(!allowPromptingSubagentSessions);
}
}}
>
<Checkbox
checked={allowPromptingSubagentSessions}
onChange={setAllowPromptingSubagentSessions}
ariaLabel={t('settings.openchamber.visual.field.allowPromptingSubagentSessionsAria')}
/>
<span className="typography-ui-label text-foreground">{t('settings.openchamber.visual.field.allowPromptingSubagentSessions')}</span>
</div>
)}
</section>
)}
{shouldShow('reasoning') && (
<section className="p-2 space-y-0.5">
<h3 data-settings-item="chat.reasoning" className="typography-ui-header font-medium text-foreground py-1.5">{t('settings.openchamber.visual.section.reasoning')}</h3>
{shouldShow('reasoning') && (
<div
data-settings-item="chat.reasoning-traces"
@@ -1990,7 +2026,12 @@ export const OpenChamberVisualSettings: React.FC<OpenChamberVisualSettingsProps>
<span className="typography-ui-label text-foreground">{t('settings.openchamber.visual.field.collapsibleThinkingBlocks')}</span>
</div>
)}
</section>
)}
{(shouldShow('collapsibleUserMessages') || shouldShow('stickyUserHeader') || shouldShow('wideChatLayout') || shouldShow('splitAssistantMessageActions') || shouldShow('codeBlockLineWrap')) && (
<section className="p-2 space-y-0.5">
<h3 data-settings-item="chat.message-appearance" className="typography-ui-header font-medium text-foreground py-1.5">{t('settings.openchamber.visual.section.messageAppearance')}</h3>
{shouldShow('collapsibleUserMessages') && (
<div
data-settings-item="chat.collapsible-user-messages"
@@ -2097,30 +2138,6 @@ export const OpenChamberVisualSettings: React.FC<OpenChamberVisualSettingsProps>
</div>
)}
{shouldShow('subagentReadOnlyBanner') && (
<div
data-settings-item="chat.subagent-read-only-banner"
className="group flex cursor-pointer items-center gap-2 py-0.5"
role="button"
tabIndex={0}
aria-pressed={allowPromptingSubagentSessions}
onClick={() => setAllowPromptingSubagentSessions(!allowPromptingSubagentSessions)}
onKeyDown={(event) => {
if (event.key === ' ' || event.key === 'Enter') {
event.preventDefault();
setAllowPromptingSubagentSessions(!allowPromptingSubagentSessions);
}
}}
>
<Checkbox
checked={allowPromptingSubagentSessions}
onChange={setAllowPromptingSubagentSessions}
ariaLabel={t('settings.openchamber.visual.field.allowPromptingSubagentSessionsAria')}
/>
<span className="typography-ui-label text-foreground">{t('settings.openchamber.visual.field.allowPromptingSubagentSessions')}</span>
</div>
)}
{shouldShow('codeBlockLineWrap') && (
<div
data-settings-item="chat.code-block-line-wrap"
@@ -2144,7 +2161,12 @@ export const OpenChamberVisualSettings: React.FC<OpenChamberVisualSettingsProps>
<span className="typography-ui-label text-foreground">{t('settings.openchamber.visual.field.codeBlockLineWrap')}</span>
</div>
)}
</section>
)}
{(shouldShow('showToolFileIcons') || shouldShow('showTurnChangedFiles') || shouldShow('dotfiles') || shouldShow('fileViewerPreview')) && (
<section className="p-2 space-y-0.5">
<h3 data-settings-item="chat.tools-and-files" className="typography-ui-header font-medium text-foreground py-1.5">{t('settings.openchamber.visual.section.toolsAndFiles')}</h3>
{shouldShow('showToolFileIcons') && (
<div
data-settings-item="chat.tool-file-icons"
@@ -2241,7 +2263,12 @@ export const OpenChamberVisualSettings: React.FC<OpenChamberVisualSettingsProps>
<span className="typography-ui-label text-foreground">{t('settings.openchamber.defaults.field.openFilesPreview')}</span>
</div>
)}
</section>
)}
{(shouldShow('persistDraft') || (!isMobile && shouldShow('inputSpellcheck'))) && (
<section className="p-2 space-y-0.5">
<h3 data-settings-item="chat.composer" className="typography-ui-header font-medium text-foreground py-1.5">{t('settings.openchamber.visual.section.composer')}</h3>
{shouldShow('persistDraft') && (
<div
data-settings-item="chat.persist-drafts"
@@ -2269,7 +2296,7 @@ export const OpenChamberVisualSettings: React.FC<OpenChamberVisualSettingsProps>
{!isMobile && shouldShow('inputSpellcheck') && (
<div
data-settings-item="chat.spellcheck"
className="group flex cursor-pointer items-center gap-2 py-1.5"
className="group flex cursor-pointer items-center gap-2 py-0.5"
role="button"
tabIndex={0}
aria-pressed={inputSpellcheckEnabled}
@@ -2289,8 +2316,10 @@ export const OpenChamberVisualSettings: React.FC<OpenChamberVisualSettingsProps>
<span className="typography-ui-label text-foreground">{t('settings.openchamber.visual.field.enableSpellcheckInTextInputs')}</span>
</div>
)}
</section>
)}
</section>
</div>
)}
</div>