@@ -154,6 +159,10 @@ const CodeBlock = ({ node, inline, className, children, ...props }: CodeBlockPro
const markdownComponents = {
code: CodeBlock,
+ // CodeBlock renders its own syntax-highlighted ; this passthrough stops
+ // react-markdown (and Tailwind Typography) from wrapping it in a second,
+ // dark-themed shell that would frame the block.
+ pre: ({ children }: { children?: React.ReactNode }) => <>{children}>,
blockquote: ({ children }: { children?: React.ReactNode }) => (
{children}
diff --git a/src/components/chat/view/subcomponents/MessageComponent.tsx b/src/components/chat/view/subcomponents/MessageComponent.tsx
index e9615a852..b326a8769 100644
--- a/src/components/chat/view/subcomponents/MessageComponent.tsx
+++ b/src/components/chat/view/subcomponents/MessageComponent.tsx
@@ -377,15 +377,15 @@ const MessageComponent = memo(({ message, prevMessage, createDiff, onFileOpen, a
return (
-
+
-
+
-
+
{formatted}
diff --git a/src/components/code-editor/view/subcomponents/markdown/MarkdownCodeBlock.tsx b/src/components/code-editor/view/subcomponents/markdown/MarkdownCodeBlock.tsx
index 21101ae55..9f7d611e4 100644
--- a/src/components/code-editor/view/subcomponents/markdown/MarkdownCodeBlock.tsx
+++ b/src/components/code-editor/view/subcomponents/markdown/MarkdownCodeBlock.tsx
@@ -1,8 +1,9 @@
import { useState } from 'react';
import type { ComponentProps } from 'react';
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
-import { oneDark as prismOneDark } from 'react-syntax-highlighter/dist/esm/styles/prism';
+import { oneDark as prismOneDark, oneLight as prismOneLight } from 'react-syntax-highlighter/dist/esm/styles/prism';
import { copyTextToClipboard } from '../../../../../utils/clipboard';
+import { useTheme } from '../../../../../contexts/ThemeContext';
type MarkdownCodeBlockProps = {
inline?: boolean;
@@ -16,6 +17,7 @@ export default function MarkdownCodeBlock({
node: _node,
...props
}: MarkdownCodeBlockProps) {
+ const { isDarkMode } = useTheme();
const [copied, setCopied] = useState(false);
const rawContent = Array.isArray(children) ? children.join('') : String(children ?? '');
const looksMultiline = /[\r\n]/.test(rawContent);
@@ -50,20 +52,22 @@ export default function MarkdownCodeBlock({
setTimeout(() => setCopied(false), 2000);
}
})}
- className="absolute right-2 top-2 z-10 rounded-md border border-gray-600 bg-gray-700/80 px-2 py-1 text-xs text-white opacity-0 transition-opacity hover:bg-gray-700 group-hover:opacity-100"
+ className="absolute right-2 top-2 z-10 rounded-md border border-border bg-card/90 px-2 py-1 text-xs text-foreground/80 opacity-0 transition-opacity hover:bg-muted group-hover:opacity-100"
>
{copied ? 'Copied!' : 'Copy'}
{rawContent}
diff --git a/src/components/code-editor/view/subcomponents/markdown/MarkdownPreview.tsx b/src/components/code-editor/view/subcomponents/markdown/MarkdownPreview.tsx
index 976ebd3f8..99e0c1eef 100644
--- a/src/components/code-editor/view/subcomponents/markdown/MarkdownPreview.tsx
+++ b/src/components/code-editor/view/subcomponents/markdown/MarkdownPreview.tsx
@@ -12,6 +12,9 @@ type MarkdownPreviewProps = {
const markdownPreviewComponents: Components = {
code: MarkdownCodeBlock,
+ // MarkdownCodeBlock renders its own highlighted
; passthrough prevents a
+ // second Typography-styled shell from framing it.
+ pre: ({ children }) => <>{children}>,
blockquote: ({ children }) => (
{children}
diff --git a/src/components/git-panel/view/GitPanelHeader.tsx b/src/components/git-panel/view/GitPanelHeader.tsx
index 9913cefb5..31e64ba6b 100644
--- a/src/components/git-panel/view/GitPanelHeader.tsx
+++ b/src/components/git-panel/view/GitPanelHeader.tsx
@@ -189,7 +189,7 @@ export default function GitPanelHeader({
diff --git a/src/components/quick-settings-panel/constants.ts b/src/components/quick-settings-panel/constants.ts
index 9c5fd5c39..3810d9ba2 100644
--- a/src/components/quick-settings-panel/constants.ts
+++ b/src/components/quick-settings-panel/constants.ts
@@ -16,7 +16,7 @@ export const HANDLE_POSITION_MAX = 90;
export const DRAG_THRESHOLD_PX = 5;
export const SETTING_ROW_CLASS =
- 'flex items-center justify-between p-3 rounded-lg bg-gray-50 dark:bg-gray-800 hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors border border-transparent hover:border-gray-300 dark:hover:border-gray-600';
+ 'flex items-center justify-between p-3 rounded-lg bg-muted/60 hover:bg-accent transition-colors border border-transparent hover:border-border';
export const TOGGLE_ROW_CLASS = `${SETTING_ROW_CLASS} cursor-pointer`;
diff --git a/src/components/quick-settings-panel/view/QuickSettingsContent.tsx b/src/components/quick-settings-panel/view/QuickSettingsContent.tsx
index b8bd1032d..8388876af 100644
--- a/src/components/quick-settings-panel/view/QuickSettingsContent.tsx
+++ b/src/components/quick-settings-panel/view/QuickSettingsContent.tsx
@@ -49,11 +49,11 @@ export default function QuickSettingsContent({
-
+
{isDarkMode ? (
-
+
) : (
-
+
)}
{t('quickSettings.darkMode')}
@@ -68,7 +68,7 @@ export default function QuickSettingsContent({
{renderToggleRows(inputSettingToggles)}
-
+
{t('quickSettings.sendByCtrlEnterDescription')}
diff --git a/src/components/quick-settings-panel/view/QuickSettingsPanelHeader.tsx b/src/components/quick-settings-panel/view/QuickSettingsPanelHeader.tsx
index 025e3b217..949369ec9 100644
--- a/src/components/quick-settings-panel/view/QuickSettingsPanelHeader.tsx
+++ b/src/components/quick-settings-panel/view/QuickSettingsPanelHeader.tsx
@@ -5,9 +5,9 @@ export default function QuickSettingsPanelHeader() {
const { t } = useTranslation('settings');
return (
-
-
-
+
+
+
{t('quickSettings.title')}
diff --git a/src/components/quick-settings-panel/view/QuickSettingsSection.tsx b/src/components/quick-settings-panel/view/QuickSettingsSection.tsx
index 60786ab94..f400b3714 100644
--- a/src/components/quick-settings-panel/view/QuickSettingsSection.tsx
+++ b/src/components/quick-settings-panel/view/QuickSettingsSection.tsx
@@ -13,7 +13,7 @@ export default function QuickSettingsSection({
}: QuickSettingsSectionProps) {
return (
-
+
{title}
{children}
diff --git a/src/components/quick-settings-panel/view/QuickSettingsToggleRow.tsx b/src/components/quick-settings-panel/view/QuickSettingsToggleRow.tsx
index 61bdd52ce..a42a8fee1 100644
--- a/src/components/quick-settings-panel/view/QuickSettingsToggleRow.tsx
+++ b/src/components/quick-settings-panel/view/QuickSettingsToggleRow.tsx
@@ -17,8 +17,8 @@ function QuickSettingsToggleRow({
}: QuickSettingsToggleRowProps) {
return (
-
-
+
+
{label}
{
const themeColorMeta = document.querySelector('meta[name="theme-color"]');
if (themeColorMeta) {
- themeColorMeta.setAttribute('content', '#0c1117'); // Dark background color (hsl(222.2 84% 4.9%))
+ themeColorMeta.setAttribute('content', '#141414'); // Dark background color (hsl(0 0% 8%))
}
} else {
document.documentElement.classList.remove('dark');
@@ -55,7 +55,7 @@ export const ThemeProvider = ({ children }) => {
const themeColorMeta = document.querySelector('meta[name="theme-color"]');
if (themeColorMeta) {
- themeColorMeta.setAttribute('content', '#ffffff'); // Light background color
+ themeColorMeta.setAttribute('content', '#f6f4ef'); // Light background color (warm cream)
}
}
}, [isDarkMode]);
diff --git a/src/index.css b/src/index.css
index 20ea8a551..ed7f4f5ab 100644
--- a/src/index.css
+++ b/src/index.css
@@ -23,37 +23,37 @@
@layer base {
:root {
- --background: 0 0% 100%;
- --foreground: 222.2 84% 4.9%;
+ --background: 44 22% 96%;
+ --foreground: 36 25% 4%;
--card: 0 0% 100%;
- --card-foreground: 222.2 84% 4.9%;
+ --card-foreground: 36 25% 4%;
--popover: 0 0% 100%;
- --popover-foreground: 222.2 84% 4.9%;
+ --popover-foreground: 36 25% 4%;
--primary: 221.2 83.2% 53.3%;
--primary-foreground: 210 40% 98%;
- --secondary: 210 40% 96.1%;
- --secondary-foreground: 222.2 47.4% 11.2%;
- --muted: 210 40% 96.1%;
- --muted-foreground: 215.4 16.3% 46.9%;
- --accent: 210 40% 96.1%;
- --accent-foreground: 222.2 47.4% 11.2%;
+ --secondary: 44 15% 91%;
+ --secondary-foreground: 36 15% 18%;
+ --muted: 44 15% 91%;
+ --muted-foreground: 40 5% 44%;
+ --accent: 44 15% 91%;
+ --accent-foreground: 36 15% 18%;
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 210 40% 98%;
- --border: 214.3 31.8% 91.4%;
- --input: 214.3 31.8% 91.4%;
+ --border: 44 14% 87%;
+ --input: 44 14% 87%;
--ring: 221.2 83.2% 53.3%;
--radius: 0.5rem;
/* Nav design tokens */
- --nav-glass-bg: 0 0% 100% / 0.7;
+ --nav-glass-bg: 44 22% 96% / 0.7;
--nav-glass-blur: 20px;
--nav-glass-saturate: 1.8;
--nav-tab-glow: 221.2 83.2% 53.3% / 0.18;
--nav-tab-ring: 221.2 83.2% 53.3% / 0.10;
--nav-float-shadow: 0 0% 0% / 0.06;
- --nav-float-ring: 214.3 31.8% 91.4% / 0.5;
- --nav-divider-color: 214.3 31.8% 91.4% / 0.5;
- --nav-input-bg: 210 40% 96.1% / 0.5;
+ --nav-float-ring: 44 14% 87% / 0.5;
+ --nav-divider-color: 44 14% 87% / 0.5;
+ --nav-input-bg: 44 15% 91% / 0.5;
--nav-input-focus-ring: 221.2 83.2% 53.3% / 0.22;
/* Safe area CSS variables */
@@ -85,36 +85,36 @@
}
.dark {
- --background: 222.2 84% 4.9%;
- --foreground: 210 40% 98%;
- --card: 217.2 91.2% 8%;
- --card-foreground: 210 40% 98%;
- --popover: 217.2 91.2% 8%;
- --popover-foreground: 210 40% 98%;
+ --background: 0 0% 8%;
+ --foreground: 40 8% 93%;
+ --card: 0 0% 12%;
+ --card-foreground: 40 8% 93%;
+ --popover: 0 0% 12%;
+ --popover-foreground: 40 8% 93%;
--primary: 217.2 91.2% 59.8%;
- --primary-foreground: 222.2 47.4% 11.2%;
- --secondary: 217.2 32.6% 17.5%;
- --secondary-foreground: 210 40% 98%;
- --muted: 217.2 32.6% 17.5%;
- --muted-foreground: 215 20.2% 65.1%;
- --accent: 217.2 32.6% 17.5%;
- --accent-foreground: 210 40% 98%;
+ --primary-foreground: 0 0% 8%;
+ --secondary: 0 0% 17%;
+ --secondary-foreground: 40 8% 93%;
+ --muted: 0 0% 17%;
+ --muted-foreground: 0 0% 60%;
+ --accent: 0 0% 17%;
+ --accent-foreground: 40 8% 93%;
--destructive: 0 62.8% 30.6%;
- --destructive-foreground: 210 40% 98%;
- --border: 217.2 32.6% 17.5%;
- --input: 220 13% 46%;
+ --destructive-foreground: 40 8% 93%;
+ --border: 0 0% 17%;
+ --input: 0 0% 23%;
--ring: 217.2 91.2% 59.8%;
/* Nav design tokens — dark overrides */
- --nav-glass-bg: 217.2 91.2% 8% / 0.55;
+ --nav-glass-bg: 0 0% 12% / 0.55;
--nav-glass-blur: 24px;
--nav-glass-saturate: 1.6;
--nav-tab-glow: 217.2 91.2% 59.8% / 0.25;
--nav-tab-ring: 217.2 91.2% 59.8% / 0.15;
--nav-float-shadow: 0 0% 0% / 0.35;
- --nav-float-ring: 217.2 32.6% 17.5% / 0.3;
- --nav-divider-color: 217.2 32.6% 17.5% / 0.5;
- --nav-input-bg: 217.2 32.6% 17.5% / 0.5;
+ --nav-float-ring: 0 0% 17% / 0.3;
+ --nav-divider-color: 0 0% 17% / 0.5;
+ --nav-input-bg: 0 0% 17% / 0.5;
--nav-input-focus-ring: 217.2 91.2% 59.8% / 0.25;
}
}
@@ -350,7 +350,7 @@
}
.dark .scrollbar-thin::-webkit-scrollbar-track {
- background: rgba(31, 41, 55, 0.3);
+ background: rgba(38, 38, 38, 0.3);
}
.dark .scrollbar-thin::-webkit-scrollbar-thumb {
@@ -369,7 +369,7 @@
}
.dark::-webkit-scrollbar-track {
- background: rgba(31, 41, 55, 0.5);
+ background: rgba(38, 38, 38, 0.5);
}
.dark::-webkit-scrollbar-thumb {
@@ -384,7 +384,7 @@
/* Firefox scrollbar styles */
.dark {
scrollbar-width: thin;
- scrollbar-color: rgba(107, 114, 128, 0.5) rgba(31, 41, 55, 0.5);
+ scrollbar-color: rgba(115, 115, 115, 0.5) rgba(38, 38, 38, 0.5);
}
/* Ensure checkbox styling is preserved */
@@ -475,7 +475,7 @@
/* Fix focus-within container issues in dark mode */
.dark .focus-within\:ring-2:focus-within {
- background-color: rgb(31 41 55) !important; /* gray-800 */
+ background-color: rgb(20 20 20) !important;
}
/* Ensure textarea remains transparent with visible text */
@@ -873,12 +873,12 @@
/* Fix focus ring offset color in dark mode */
.dark [class*="ring-offset"] {
- --tw-ring-offset-color: rgb(31 41 55); /* gray-800 */
+ --tw-ring-offset-color: rgb(20 20 20);
}
-
+
/* Ensure buttons don't show white backgrounds in dark mode */
.dark button:focus {
- --tw-ring-offset-color: rgb(31 41 55); /* gray-800 */
+ --tw-ring-offset-color: rgb(20 20 20);
}
/* Fix mobile select dropdown styling */
@@ -921,8 +921,8 @@
}
.dark select option {
- background-color: rgb(31 41 55) !important;
- color: rgb(243 244 246) !important;
+ background-color: rgb(31 31 31) !important;
+ color: rgb(237 235 230) !important;
}
/* Tool details chevron animation */
From 9090e7347844878c1cf9999ec821676df63fdce7 Mon Sep 17 00:00:00 2001
From: Haileyesus <118998054+blackmammoth@users.noreply.github.com>
Date: Mon, 29 Jun 2026 23:52:06 +0300
Subject: [PATCH 10/22] fix: use app theme for code editor
---
.../code-editor/constants/settings.ts | 2 --
.../hooks/useCodeEditorSettings.ts | 19 +------------------
.../code-editor/view/CodeEditor.tsx | 5 ++++-
.../settings/constants/constants.ts | 1 -
.../settings/hooks/useSettingsController.ts | 2 --
src/components/settings/types/types.ts | 1 -
src/components/settings/view/Settings.tsx | 1 -
.../view/tabs/AppearanceSettingsTab.tsx | 13 -------------
8 files changed, 5 insertions(+), 39 deletions(-)
diff --git a/src/components/code-editor/constants/settings.ts b/src/components/code-editor/constants/settings.ts
index fe3d5d24d..4d8d1068d 100644
--- a/src/components/code-editor/constants/settings.ts
+++ b/src/components/code-editor/constants/settings.ts
@@ -1,5 +1,4 @@
export const CODE_EDITOR_STORAGE_KEYS = {
- theme: 'codeEditorTheme',
wordWrap: 'codeEditorWordWrap',
showMinimap: 'codeEditorShowMinimap',
lineNumbers: 'codeEditorLineNumbers',
@@ -7,7 +6,6 @@ export const CODE_EDITOR_STORAGE_KEYS = {
} as const;
export const CODE_EDITOR_DEFAULTS = {
- isDarkMode: true,
wordWrap: false,
minimapEnabled: true,
showLineNumbers: true,
diff --git a/src/components/code-editor/hooks/useCodeEditorSettings.ts b/src/components/code-editor/hooks/useCodeEditorSettings.ts
index 639054d74..06a8ffe4b 100644
--- a/src/components/code-editor/hooks/useCodeEditorSettings.ts
+++ b/src/components/code-editor/hooks/useCodeEditorSettings.ts
@@ -5,15 +5,6 @@ import {
CODE_EDITOR_STORAGE_KEYS,
} from '../constants/settings';
-const readTheme = () => {
- const savedTheme = localStorage.getItem(CODE_EDITOR_STORAGE_KEYS.theme);
- if (!savedTheme) {
- return CODE_EDITOR_DEFAULTS.isDarkMode;
- }
-
- return savedTheme === 'dark';
-};
-
const readBoolean = (storageKey: string, defaultValue: boolean, falseValue = 'false') => {
const value = localStorage.getItem(storageKey);
if (value === null) {
@@ -33,7 +24,6 @@ const readFontSize = () => {
};
export const useCodeEditorSettings = () => {
- const [isDarkMode, setIsDarkMode] = useState(readTheme);
const [wordWrap, setWordWrap] = useState(readWordWrap);
const [minimapEnabled, setMinimapEnabled] = useState(() => (
readBoolean(CODE_EDITOR_STORAGE_KEYS.showMinimap, CODE_EDITOR_DEFAULTS.minimapEnabled)
@@ -43,18 +33,13 @@ export const useCodeEditorSettings = () => {
));
const [fontSize, setFontSize] = useState(readFontSize);
- // Keep legacy behavior where the editor writes theme and wrap settings directly.
- useEffect(() => {
- localStorage.setItem(CODE_EDITOR_STORAGE_KEYS.theme, isDarkMode ? 'dark' : 'light');
- }, [isDarkMode]);
-
+ // Keep legacy behavior where the editor writes wrap settings directly.
useEffect(() => {
localStorage.setItem(CODE_EDITOR_STORAGE_KEYS.wordWrap, String(wordWrap));
}, [wordWrap]);
useEffect(() => {
const refreshFromStorage = () => {
- setIsDarkMode(readTheme());
setWordWrap(readWordWrap());
setMinimapEnabled(readBoolean(CODE_EDITOR_STORAGE_KEYS.showMinimap, CODE_EDITOR_DEFAULTS.minimapEnabled));
setShowLineNumbers(readBoolean(CODE_EDITOR_STORAGE_KEYS.lineNumbers, CODE_EDITOR_DEFAULTS.showLineNumbers));
@@ -71,8 +56,6 @@ export const useCodeEditorSettings = () => {
}, []);
return {
- isDarkMode,
- setIsDarkMode,
wordWrap,
setWordWrap,
minimapEnabled,
diff --git a/src/components/code-editor/view/CodeEditor.tsx b/src/components/code-editor/view/CodeEditor.tsx
index 5861ce715..f153f7b88 100644
--- a/src/components/code-editor/view/CodeEditor.tsx
+++ b/src/components/code-editor/view/CodeEditor.tsx
@@ -4,6 +4,7 @@ import type { Extension } from '@codemirror/state';
import { useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { usePaletteOps } from '../../../contexts/PaletteOpsContext';
+import { useTheme } from '../../../contexts/ThemeContext';
import { useCodeEditorDocument } from '../hooks/useCodeEditorDocument';
import { useCodeEditorSettings } from '../hooks/useCodeEditorSettings';
import { useEditorKeyboardShortcuts } from '../hooks/useEditorKeyboardShortcuts';
@@ -42,8 +43,10 @@ export default function CodeEditor({
const [showDiff, setShowDiff] = useState(Boolean(file.diffInfo));
const [markdownPreview, setMarkdownPreview] = useState(false);
+ // The code editor follows the app-wide theme; it has no theme of its own.
+ const { isDarkMode } = useTheme();
+
const {
- isDarkMode,
wordWrap,
minimapEnabled,
showLineNumbers,
diff --git a/src/components/settings/constants/constants.ts b/src/components/settings/constants/constants.ts
index 8e5bfebe3..366c5989c 100644
--- a/src/components/settings/constants/constants.ts
+++ b/src/components/settings/constants/constants.ts
@@ -45,7 +45,6 @@ export const AGENT_CATEGORIES: AgentCategory[] = ['account', 'permissions', 'mcp
export const DEFAULT_PROJECT_SORT_ORDER: ProjectSortOrder = 'name';
export const DEFAULT_SAVE_STATUS = null;
export const DEFAULT_CODE_EDITOR_SETTINGS: CodeEditorSettingsState = {
- theme: 'dark',
wordWrap: false,
showMinimap: true,
lineNumbers: true,
diff --git a/src/components/settings/hooks/useSettingsController.ts b/src/components/settings/hooks/useSettingsController.ts
index abf62cecb..e42a1e1be 100644
--- a/src/components/settings/hooks/useSettingsController.ts
+++ b/src/components/settings/hooks/useSettingsController.ts
@@ -86,7 +86,6 @@ const toCodexPermissionMode = (value: unknown): CodexPermissionMode => {
};
const readCodeEditorSettings = (): CodeEditorSettingsState => ({
- theme: localStorage.getItem('codeEditorTheme') === 'light' ? 'light' : 'dark',
wordWrap: localStorage.getItem('codeEditorWordWrap') === 'true',
showMinimap: localStorage.getItem('codeEditorShowMinimap') !== 'false',
lineNumbers: localStorage.getItem('codeEditorLineNumbers') !== 'false',
@@ -330,7 +329,6 @@ export function useSettingsController({ isOpen, initialTab }: UseSettingsControl
}, [notificationPreferences.channels.sound]);
useEffect(() => {
- localStorage.setItem('codeEditorTheme', codeEditorSettings.theme);
localStorage.setItem('codeEditorWordWrap', String(codeEditorSettings.wordWrap));
localStorage.setItem('codeEditorShowMinimap', String(codeEditorSettings.showMinimap));
localStorage.setItem('codeEditorLineNumbers', String(codeEditorSettings.lineNumbers));
diff --git a/src/components/settings/types/types.ts b/src/components/settings/types/types.ts
index 7d8f7c377..c6801f393 100644
--- a/src/components/settings/types/types.ts
+++ b/src/components/settings/types/types.ts
@@ -47,7 +47,6 @@ export type CursorPermissionsState = {
};
export type CodeEditorSettingsState = {
- theme: 'dark' | 'light';
wordWrap: boolean;
showMinimap: boolean;
lineNumbers: boolean;
diff --git a/src/components/settings/view/Settings.tsx b/src/components/settings/view/Settings.tsx
index 96eaa0c6c..724995569 100644
--- a/src/components/settings/view/Settings.tsx
+++ b/src/components/settings/view/Settings.tsx
@@ -168,7 +168,6 @@ function Settings({ isOpen, onClose, projects = [], initialTab = 'agents' }: Set
projectSortOrder={projectSortOrder}
onProjectSortOrderChange={setProjectSortOrder}
codeEditorSettings={codeEditorSettings}
- onCodeEditorThemeChange={(value) => updateCodeEditorSetting('theme', value)}
onCodeEditorWordWrapChange={(value) => updateCodeEditorSetting('wordWrap', value)}
onCodeEditorShowMinimapChange={(value) => updateCodeEditorSetting('showMinimap', value)}
onCodeEditorLineNumbersChange={(value) => updateCodeEditorSetting('lineNumbers', value)}
diff --git a/src/components/settings/view/tabs/AppearanceSettingsTab.tsx b/src/components/settings/view/tabs/AppearanceSettingsTab.tsx
index b320ec5fc..7b11645a2 100644
--- a/src/components/settings/view/tabs/AppearanceSettingsTab.tsx
+++ b/src/components/settings/view/tabs/AppearanceSettingsTab.tsx
@@ -11,7 +11,6 @@ type AppearanceSettingsTabProps = {
projectSortOrder: ProjectSortOrder;
onProjectSortOrderChange: (value: ProjectSortOrder) => void;
codeEditorSettings: CodeEditorSettingsState;
- onCodeEditorThemeChange: (value: 'dark' | 'light') => void;
onCodeEditorWordWrapChange: (value: boolean) => void;
onCodeEditorShowMinimapChange: (value: boolean) => void;
onCodeEditorLineNumbersChange: (value: boolean) => void;
@@ -22,7 +21,6 @@ export default function AppearanceSettingsTab({
projectSortOrder,
onProjectSortOrderChange,
codeEditorSettings,
- onCodeEditorThemeChange,
onCodeEditorWordWrapChange,
onCodeEditorShowMinimapChange,
onCodeEditorLineNumbersChange,
@@ -69,17 +67,6 @@ export default function AppearanceSettingsTab({
-
- onCodeEditorThemeChange(enabled ? 'dark' : 'light')}
- ariaLabel={t('appearanceSettings.codeEditor.theme.label')}
- />
-
-
Date: Mon, 29 Jun 2026 23:56:10 +0300
Subject: [PATCH 11/22] style(chat): unify composer toolbar heights and
declutter slash-command modal
- Composer: give the permission-mode and token-usage buttons a fixed
h-8 so every bottom-toolbar control shares one height
- CommandResultModal: replace the blue gradient header (gradient fill,
glow blobs, blue eyebrow + icon chip) with a clean neutral header on
popover/muted tokens
---
.../chat/view/subcomponents/ChatComposer.tsx | 2 +-
.../view/subcomponents/CommandResultModal.tsx | 67 +++++++++----------
.../view/subcomponents/TokenUsageSummary.tsx | 2 +-
3 files changed, 33 insertions(+), 38 deletions(-)
diff --git a/src/components/chat/view/subcomponents/ChatComposer.tsx b/src/components/chat/view/subcomponents/ChatComposer.tsx
index c021d9197..32ef91e2e 100644
--- a/src/components/chat/view/subcomponents/ChatComposer.tsx
+++ b/src/components/chat/view/subcomponents/ChatComposer.tsx
@@ -331,7 +331,7 @@ export default function ChatComposer({
{activeMeta?.title || 'Command Result'}
-
-
-
-
-
-
-
-
-
-
- {activeMeta?.eyebrow}
-
-
- {activeMeta?.title}
-
-
- {activeMeta?.subtitle}
-
-
-
-
-
+
-
-
+
+
+
+
+ {activeMeta?.eyebrow}
+
+
+ {activeMeta?.title}
+
+
+ {activeMeta?.subtitle}
+
+
+
+
+
+
diff --git a/src/components/chat/view/subcomponents/TokenUsageSummary.tsx b/src/components/chat/view/subcomponents/TokenUsageSummary.tsx
index f3d25f4b7..51dd8ed01 100644
--- a/src/components/chat/view/subcomponents/TokenUsageSummary.tsx
+++ b/src/components/chat/view/subcomponents/TokenUsageSummary.tsx
@@ -43,7 +43,7 @@ export default function TokenUsageSummary({ usage, onClick }: TokenUsageSummaryP
From c420c6d63eda6f49fb816e41088d585983ee0559 Mon Sep 17 00:00:00 2001
From: Haileyesus <118998054+blackmammoth@users.noreply.github.com>
Date: Tue, 30 Jun 2026 00:06:25 +0300
Subject: [PATCH 12/22] fix(chat): header ellipsis, Codex logo on light theme,
portal copy menu
- MainContentTitle: truncate the session title with an ellipsis instead
of horizontal-scrolling it
- MessageComponent: use text-foreground for the provider logo chip so the
currentColor Codex/OpenAI mark is visible on the light theme
- MessageCopyControl: render the copy-format dropdown in a portal so it
escapes the chat message's `contain: paint` clip box; anchor it to the
trigger, flip above near the viewport bottom, close on scroll/resize
---
.../view/subcomponents/MessageComponent.tsx | 2 +-
.../view/subcomponents/MessageCopyControl.tsx | 61 ++++++++++++++++---
.../view/subcomponents/MainContentTitle.tsx | 2 +-
3 files changed, 53 insertions(+), 12 deletions(-)
diff --git a/src/components/chat/view/subcomponents/MessageComponent.tsx b/src/components/chat/view/subcomponents/MessageComponent.tsx
index b326a8769..552b31cbc 100644
--- a/src/components/chat/view/subcomponents/MessageComponent.tsx
+++ b/src/components/chat/view/subcomponents/MessageComponent.tsx
@@ -166,7 +166,7 @@ const MessageComponent = memo(({ message, prevMessage, createDiff, onFileOpen, a
🔧
) : (
-
+
)}
diff --git a/src/components/chat/view/subcomponents/MessageCopyControl.tsx b/src/components/chat/view/subcomponents/MessageCopyControl.tsx
index aeacd45c3..c02b5676a 100644
--- a/src/components/chat/view/subcomponents/MessageCopyControl.tsx
+++ b/src/components/chat/view/subcomponents/MessageCopyControl.tsx
@@ -1,4 +1,6 @@
import { useEffect, useMemo, useRef, useState } from 'react';
+import type { CSSProperties } from 'react';
+import { createPortal } from 'react-dom';
import { useTranslation } from 'react-i18next';
import { copyTextToClipboard } from '../../../../utils/clipboard';
@@ -49,9 +51,32 @@ const MessageCopyControl = ({
const [selectedFormat, setSelectedFormat] = useState
(defaultFormat);
const [copied, setCopied] = useState(false);
const [isDropdownOpen, setIsDropdownOpen] = useState(false);
+ const [menuStyle, setMenuStyle] = useState({});
const dropdownRef = useRef(null);
+ const triggerRef = useRef(null);
+ const menuRef = useRef(null);
const copyFeedbackTimerRef = useRef | null>(null);
+ // The dropdown is rendered in a portal so it escapes the chat message's
+ // `contain: paint` box (which would otherwise clip it). Anchor it to the
+ // trigger, flipping above when there isn't room below.
+ const openDropdown = () => {
+ const rect = triggerRef.current?.getBoundingClientRect();
+ if (rect) {
+ const ESTIMATED_MENU_HEIGHT = 84;
+ const openUp = rect.bottom + ESTIMATED_MENU_HEIGHT + 8 > window.innerHeight;
+ setMenuStyle({
+ position: 'fixed',
+ right: Math.max(8, window.innerWidth - rect.right),
+ zIndex: 1000,
+ ...(openUp
+ ? { bottom: window.innerHeight - rect.top + 4 }
+ : { top: rect.bottom + 4 }),
+ });
+ }
+ setIsDropdownOpen(true);
+ };
+
const copyFormatOptions: CopyFormatOption[] = useMemo(
() => [
{
@@ -83,18 +108,28 @@ const MessageCopyControl = ({
}, [defaultFormat]);
useEffect(() => {
- // Close the dropdown when clicking anywhere outside this control.
+ if (!isDropdownOpen) return;
+
+ // Close when clicking outside both the control and the portaled menu.
const closeOnOutsideClick = (event: MouseEvent) => {
- if (!isDropdownOpen) return;
const target = event.target as Node;
- if (dropdownRef.current && !dropdownRef.current.contains(target)) {
- setIsDropdownOpen(false);
+ if (dropdownRef.current?.contains(target) || menuRef.current?.contains(target)) {
+ return;
}
+ setIsDropdownOpen(false);
};
+ // The menu is fixed-positioned; close it if the page scrolls so it can't
+ // detach from the trigger.
+ const closeOnScroll = () => setIsDropdownOpen(false);
+
window.addEventListener('mousedown', closeOnOutsideClick);
+ window.addEventListener('scroll', closeOnScroll, true);
+ window.addEventListener('resize', closeOnScroll);
return () => {
window.removeEventListener('mousedown', closeOnOutsideClick);
+ window.removeEventListener('scroll', closeOnScroll, true);
+ window.removeEventListener('resize', closeOnScroll);
};
}, [isDropdownOpen]);
@@ -170,8 +205,9 @@ const MessageCopyControl = ({
{canSelectCopyFormat && (
<>
setIsDropdownOpen((prev) => !prev)}
+ onClick={() => (isDropdownOpen ? setIsDropdownOpen(false) : openDropdown())}
className={`rounded px-1 py-0.5 transition-colors ${toneClass}`}
aria-label={t('copyMessage.selectFormat', { defaultValue: 'Select copy format' })}
title={t('copyMessage.selectFormat', { defaultValue: 'Select copy format' })}
@@ -186,8 +222,12 @@ const MessageCopyControl = ({
- {isDropdownOpen && (
-
+ {isDropdownOpen && createPortal(
+
{copyFormatOptions.map((option) => {
const isSelected = option.format === selectedFormat;
return (
@@ -196,15 +236,16 @@ const MessageCopyControl = ({
type="button"
onClick={() => handleFormatChange(option.format)}
className={`block w-full rounded px-2 py-1.5 text-left transition-colors ${isSelected
- ? 'bg-gray-100 text-gray-900 dark:bg-gray-800 dark:text-gray-100'
- : 'text-gray-700 hover:bg-gray-50 dark:text-gray-300 dark:hover:bg-gray-800/60'
+ ? 'bg-accent text-foreground'
+ : 'text-foreground hover:bg-accent'
}`}
>
{option.label}
);
})}
-
+
,
+ document.body,
)}
>
)}
diff --git a/src/components/main-content/view/subcomponents/MainContentTitle.tsx b/src/components/main-content/view/subcomponents/MainContentTitle.tsx
index af8b0decc..e3d8776f2 100644
--- a/src/components/main-content/view/subcomponents/MainContentTitle.tsx
+++ b/src/components/main-content/view/subcomponents/MainContentTitle.tsx
@@ -70,7 +70,7 @@ export default function MainContentTitle({
{activeTab === 'chat' && selectedSession ? (
-
+
{getSessionTitle(selectedSession)}
{selectedProject.displayName}
From a7b455aeac7562cf3ddc9e225bd33cc3db245b7a Mon Sep 17 00:00:00 2001
From: Haileyesus <118998054+blackmammoth@users.noreply.github.com>
Date: Tue, 30 Jun 2026 00:13:02 +0300
Subject: [PATCH 13/22] style(mcp): remove purple accents and portal the server
form modal
- Replace the purple provider-button colors, heading icon, and form
submit button with the primary token (no purple in the MCP UI)
- Portal the add/edit MCP server modal to document.body so its fixed
overlay covers the full viewport, fixing the white band at the top
caused by the Settings dialog's transformed tab content becoming the
containing block
---
src/components/mcp/constants.ts | 10 +++++-----
src/components/mcp/view/McpServers.tsx | 2 +-
src/components/mcp/view/modals/McpServerFormModal.tsx | 10 ++++++----
3 files changed, 12 insertions(+), 10 deletions(-)
diff --git a/src/components/mcp/constants.ts b/src/components/mcp/constants.ts
index ab6396ff7..2e23c5cbe 100644
--- a/src/components/mcp/constants.ts
+++ b/src/components/mcp/constants.ts
@@ -29,11 +29,11 @@ export const MCP_GLOBAL_SUPPORTED_SCOPES: McpScope[] = ['user', 'project'];
export const MCP_GLOBAL_SUPPORTED_TRANSPORTS: McpTransport[] = ['stdio', 'http'];
export const MCP_PROVIDER_BUTTON_CLASSES: Record = {
- claude: 'bg-purple-600 text-white hover:bg-purple-700',
- cursor: 'bg-purple-600 text-white hover:bg-purple-700',
- codex: 'bg-gray-800 text-white hover:bg-gray-900 dark:bg-gray-700 dark:hover:bg-gray-600',
- gemini: 'bg-blue-600 text-white hover:bg-blue-700',
- opencode: 'bg-zinc-900 text-white hover:bg-zinc-800 dark:bg-zinc-700 dark:hover:bg-zinc-600',
+ claude: 'bg-primary text-primary-foreground hover:bg-primary/90',
+ cursor: 'bg-primary text-primary-foreground hover:bg-primary/90',
+ codex: 'bg-primary text-primary-foreground hover:bg-primary/90',
+ gemini: 'bg-primary text-primary-foreground hover:bg-primary/90',
+ opencode: 'bg-primary text-primary-foreground hover:bg-primary/90',
};
export const MCP_SUPPORTS_WORKING_DIRECTORY: Record = {
diff --git a/src/components/mcp/view/McpServers.tsx b/src/components/mcp/view/McpServers.tsx
index a77117fe2..9e15deeb0 100644
--- a/src/components/mcp/view/McpServers.tsx
+++ b/src/components/mcp/view/McpServers.tsx
@@ -135,7 +135,7 @@ export default function McpServers({ selectedProvider, currentProjects }: McpSer
return (
-
+
{t('mcpServers.title')}
{description}
diff --git a/src/components/mcp/view/modals/McpServerFormModal.tsx b/src/components/mcp/view/modals/McpServerFormModal.tsx
index afffa512a..8ce76e9d5 100644
--- a/src/components/mcp/view/modals/McpServerFormModal.tsx
+++ b/src/components/mcp/view/modals/McpServerFormModal.tsx
@@ -1,4 +1,5 @@
import { FolderOpen, Globe, X } from 'lucide-react';
+import { createPortal } from 'react-dom';
import { useTranslation } from 'react-i18next';
import { Button, Input } from '../../../../shared/view/ui';
@@ -119,8 +120,8 @@ export default function McpServerFormModal({
const supportsWorkingDirectory = !isGlobalMode && MCP_SUPPORTS_WORKING_DIRECTORY[provider];
const showCodexOnlyFields = provider === 'codex' && !isGlobalMode;
- return (
-
+ return createPortal(
+
{modalTitle}
@@ -418,7 +419,7 @@ export default function McpServerFormModal({
{isSubmitting
? t('mcpForm.actions.saving')
@@ -429,6 +430,7 @@ export default function McpServerFormModal({
-
+
,
+ document.body,
);
}
From 57982461356e1bb2f3ee511fd45708fe574f5ca0 Mon Sep 17 00:00:00 2001
From: Haileyesus <118998054+blackmammoth@users.noreply.github.com>
Date: Tue, 30 Jun 2026 00:22:33 +0300
Subject: [PATCH 14/22] style(ui): use Merriweather serif for chat text and
Encode Sans for the rest of the UI
---
index.html | 10 +++++++++-
.../chat/view/subcomponents/MessageComponent.tsx | 10 +++++-----
src/index.css | 2 +-
tailwind.config.js | 4 ++++
4 files changed, 19 insertions(+), 7 deletions(-)
diff --git a/index.html b/index.html
index 37d2217d7..1fdfcc7cb 100644
--- a/index.html
+++ b/index.html
@@ -6,7 +6,15 @@
CloudCLI UI
-
+
+
+
+
+
+
diff --git a/src/components/chat/view/subcomponents/MessageComponent.tsx b/src/components/chat/view/subcomponents/MessageComponent.tsx
index 552b31cbc..cfe852fed 100644
--- a/src/components/chat/view/subcomponents/MessageComponent.tsx
+++ b/src/components/chat/view/subcomponents/MessageComponent.tsx
@@ -115,7 +115,7 @@ const MessageComponent = memo(({ message, prevMessage, createDiff, onFileOpen, a
/* User message bubble on the right */
-
+
{message.content}
{message.images && message.images.length > 0 && (
@@ -194,7 +194,7 @@ const MessageComponent = memo(({ message, prevMessage, createDiff, onFileOpen, a
<>
-
+
{String(message.displayText || '')}
@@ -233,7 +233,7 @@ const MessageComponent = memo(({ message, prevMessage, createDiff, onFileOpen, a
{t('messageTypes.error')}
-
+
{String(message.toolResult.content || '')}
@@ -342,7 +342,7 @@ const MessageComponent = memo(({ message, prevMessage, createDiff, onFileOpen, a
-
+
{message.content}
@@ -399,7 +399,7 @@ const MessageComponent = memo(({ message, prevMessage, createDiff, onFileOpen, a
// Normal rendering for non-JSON content
return message.type === 'assistant' ? (
-
+
{content}
) : (
diff --git a/src/index.css b/src/index.css
index ed7f4f5ab..195ae1d3a 100644
--- a/src/index.css
+++ b/src/index.css
@@ -128,7 +128,7 @@
body {
@apply bg-background text-foreground;
- font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
+ font-family: "Encode Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
margin: 0;
diff --git a/tailwind.config.js b/tailwind.config.js
index 0b2517d04..5d67ef830 100755
--- a/tailwind.config.js
+++ b/tailwind.config.js
@@ -14,6 +14,10 @@ export default {
},
},
extend: {
+ fontFamily: {
+ sans: ['"Encode Sans"', '-apple-system', 'BlinkMacSystemFont', '"Segoe UI"', 'Roboto', '"Helvetica Neue"', 'Arial', 'sans-serif'],
+ serif: ['Merriweather', 'Georgia', 'Cambria', '"Times New Roman"', 'serif'],
+ },
colors: {
border: "hsl(var(--border))",
input: "hsl(var(--input))",
From eed37b51d41bbd69eac23a89120706bc88d74ccd Mon Sep 17 00:00:00 2001
From: Haileyesus <118998054+blackmammoth@users.noreply.github.com>
Date: Tue, 30 Jun 2026 01:31:51 +0300
Subject: [PATCH 15/22] fix: align activity indicator with composer input width
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Wrap ActivityIndicator in the same mx-auto max-w-3xl container as the
text input so the "Analyzing…" label and Stop button stay within the
input's boundaries instead of spanning the full window width.
---
src/components/chat/view/subcomponents/ActivityIndicator.tsx | 4 ++--
src/components/chat/view/subcomponents/ChatComposer.tsx | 4 +++-
2 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/src/components/chat/view/subcomponents/ActivityIndicator.tsx b/src/components/chat/view/subcomponents/ActivityIndicator.tsx
index afb30af4b..810d2a2e0 100644
--- a/src/components/chat/view/subcomponents/ActivityIndicator.tsx
+++ b/src/components/chat/view/subcomponents/ActivityIndicator.tsx
@@ -52,8 +52,8 @@ export default function ActivityIndicator({ activity, onAbort }: ActivityIndicat
: t('claudeStatus.elapsed.minutesSeconds', { minutes, seconds, defaultValue: '{{minutes}}m {{seconds}}s' });
return (
-
-
+
+
{`${label}…`}
{elapsedLabel}
diff --git a/src/components/chat/view/subcomponents/ChatComposer.tsx b/src/components/chat/view/subcomponents/ChatComposer.tsx
index 32ef91e2e..1b099c3c7 100644
--- a/src/components/chat/view/subcomponents/ChatComposer.tsx
+++ b/src/components/chat/view/subcomponents/ChatComposer.tsx
@@ -199,7 +199,9 @@ export default function ChatComposer({
return (
{!hasPendingPermissions && (
-
+
)}
{pendingPermissionRequests.length > 0 && (
From 7d5bd753d4bac4a3a38ac3a66094af577b638503 Mon Sep 17 00:00:00 2001
From: Haileyesus <118998054+blackmammoth@users.noreply.github.com>
Date: Tue, 30 Jun 2026 11:20:32 +0300
Subject: [PATCH 16/22] style: improve thinking and stop button placements
---
src/components/chat/view/ChatInterface.tsx | 3 +-
.../view/subcomponents/ActivityIndicator.tsx | 56 +++++++++++++++----
.../chat/view/subcomponents/ChatComposer.tsx | 14 +++--
src/index.css | 49 +++++++++++++++-
4 files changed, 105 insertions(+), 17 deletions(-)
diff --git a/src/components/chat/view/ChatInterface.tsx b/src/components/chat/view/ChatInterface.tsx
index c4a3d202b..103dea817 100644
--- a/src/components/chat/view/ChatInterface.tsx
+++ b/src/components/chat/view/ChatInterface.tsx
@@ -184,7 +184,7 @@ function ChatInterface({
handlePermissionDecision,
handleGrantToolPermission,
handleInputFocusChange,
- isInputFocused: _isInputFocused,
+ isInputFocused,
commandModalPayload,
closeCommandModal,
showCostModal,
@@ -424,6 +424,7 @@ function ChatInterface({
onTextareaPaste={handlePaste}
onTextareaScrollSync={syncInputOverlayScroll}
onTextareaInput={handleTextareaInput}
+ isInputFocused={isInputFocused}
onInputFocusChange={handleInputFocusChange}
placeholder={t('input.placeholder', {
provider:
diff --git a/src/components/chat/view/subcomponents/ActivityIndicator.tsx b/src/components/chat/view/subcomponents/ActivityIndicator.tsx
index 810d2a2e0..f235c2fb0 100644
--- a/src/components/chat/view/subcomponents/ActivityIndicator.tsx
+++ b/src/components/chat/view/subcomponents/ActivityIndicator.tsx
@@ -7,6 +7,7 @@ import type { SessionActivity } from '../../../../hooks/useSessionProtection';
type ActivityIndicatorProps = {
activity: SessionActivity | null;
onAbort?: () => void;
+ isInputFocused?: boolean;
};
const ACTION_KEYS = [
@@ -18,6 +19,7 @@ const ACTION_KEYS = [
'claudeStatus.actions.reasoning',
];
const DEFAULT_ACTION_WORDS = ['Thinking', 'Processing', 'Analyzing', 'Working', 'Computing', 'Reasoning'];
+const EXIT_ANIMATION_MS = 220;
/**
* Minimal response-in-progress indicator, in the spirit of the inline status
@@ -26,11 +28,31 @@ const DEFAULT_ACTION_WORDS = ['Thinking', 'Processing', 'Analyzing', 'Working',
* session has an entry in the processing map; it disappears the instant that
* entry is removed.
*/
-export default function ActivityIndicator({ activity, onAbort }: ActivityIndicatorProps) {
+export default function ActivityIndicator({ activity, onAbort, isInputFocused = false }: ActivityIndicatorProps) {
const { t } = useTranslation('chat');
- const startedAt = activity?.startedAt ?? null;
+ const [renderedActivity, setRenderedActivity] = useState
(activity);
+ const [isExiting, setIsExiting] = useState(false);
+ const startedAt = renderedActivity?.startedAt ?? null;
const [elapsedSeconds, setElapsedSeconds] = useState(0);
+ useEffect(() => {
+ if (activity) {
+ setRenderedActivity(activity);
+ setIsExiting(false);
+ return;
+ }
+
+ if (!renderedActivity) return;
+
+ setIsExiting(true);
+ const timer = setTimeout(() => {
+ setRenderedActivity(null);
+ setIsExiting(false);
+ }, EXIT_ANIMATION_MS);
+
+ return () => clearTimeout(timer);
+ }, [activity, renderedActivity]);
+
useEffect(() => {
if (startedAt === null) return;
const update = () => setElapsedSeconds(Math.max(0, Math.floor((Date.now() - startedAt) / 1000)));
@@ -39,10 +61,10 @@ export default function ActivityIndicator({ activity, onAbort }: ActivityIndicat
return () => clearInterval(timer);
}, [startedAt]);
- if (!activity) return null;
+ if (!renderedActivity) return null;
const actionWords = ACTION_KEYS.map((key, i) => t(key, { defaultValue: DEFAULT_ACTION_WORDS[i] }));
- const label = (activity.statusText || actionWords[Math.floor(elapsedSeconds / 4) % actionWords.length])
+ const label = (renderedActivity.statusText || actionWords[Math.floor(elapsedSeconds / 4) % actionWords.length])
.replace(/\.+$/, '');
const minutes = Math.floor(elapsedSeconds / 60);
@@ -50,19 +72,31 @@ export default function ActivityIndicator({ activity, onAbort }: ActivityIndicat
const elapsedLabel = minutes < 1
? t('claudeStatus.elapsed.seconds', { count: seconds, defaultValue: '{{count}}s' })
: t('claudeStatus.elapsed.minutesSeconds', { minutes, seconds, defaultValue: '{{minutes}}m {{seconds}}s' });
+ const tabSurfaceClassName = [
+ 'chat-activity-tab inline-flex h-8 items-center rounded-b-none rounded-t-lg border border-b-0 bg-card px-3 text-xs transition-all duration-200',
+ isInputFocused
+ ? 'border-primary/30 shadow-[0_-1px_2px_hsl(var(--foreground)/0.08),1px_0_2px_hsl(var(--foreground)/0.06),-1px_0_2px_hsl(var(--foreground)/0.06)]'
+ : 'border-border/50 shadow-[0_-1px_1px_hsl(var(--foreground)/0.04),1px_0_1px_hsl(var(--foreground)/0.03),-1px_0_1px_hsl(var(--foreground)/0.03)]',
+ ].join(' ');
return (
-
-
-
-
{`${label}…`}
-
{elapsedLabel}
+
+
+
+
+ {`${label}…`}
+ {elapsedLabel}
+
- {activity.canInterrupt && onAbort && (
+ {renderedActivity.canInterrupt && onAbort && (
diff --git a/src/components/chat/view/subcomponents/ChatComposer.tsx b/src/components/chat/view/subcomponents/ChatComposer.tsx
index 1b099c3c7..02eeaac6a 100644
--- a/src/components/chat/view/subcomponents/ChatComposer.tsx
+++ b/src/components/chat/view/subcomponents/ChatComposer.tsx
@@ -98,6 +98,7 @@ interface ChatComposerProps {
onTextareaPaste: (event: ClipboardEvent) => void;
onTextareaScrollSync: (target: HTMLTextAreaElement) => void;
onTextareaInput: (event: FormEvent) => void;
+ isInputFocused?: boolean;
onInputFocusChange?: (focused: boolean) => void;
placeholder: string;
isTextareaExpanded: boolean;
@@ -149,6 +150,7 @@ export default function ChatComposer({
onTextareaPaste,
onTextareaScrollSync,
onTextareaInput,
+ isInputFocused = false,
onInputFocusChange,
placeholder,
isTextareaExpanded,
@@ -195,12 +197,13 @@ export default function ChatComposer({
// Hide the thinking/status bar while any permission request is pending
const hasPendingPermissions = pendingPermissionRequests.length > 0;
+ const hasActivityIndicator = Boolean(activity && !hasPendingPermissions);
return (
-
+
{!hasPendingPermissions && (
-
-
+
)}
@@ -255,7 +258,10 @@ export default function ChatComposer({
) => void}
status={isLoading ? 'streaming' : 'ready'}
- className={isTextareaExpanded ? 'chat-input-expanded' : ''}
+ className={[
+ isTextareaExpanded ? 'chat-input-expanded' : '',
+ hasActivityIndicator ? 'rounded-t-none' : '',
+ ].filter(Boolean).join(' ')}
{...getRootProps()}
>
{isDragActive && (
diff --git a/src/index.css b/src/index.css
index 195ae1d3a..58ef2874d 100644
--- a/src/index.css
+++ b/src/index.css
@@ -568,7 +568,23 @@
}
.chat-composer-shell {
- contain: layout style paint;
+ contain: layout style;
+ }
+
+ .chat-activity-enter {
+ animation: chat-activity-enter 320ms cubic-bezier(0.22, 1, 0.36, 1) both;
+ transform-origin: bottom center;
+ will-change: transform, opacity, filter;
+ }
+
+ .chat-activity-exit {
+ animation: chat-activity-exit 220ms cubic-bezier(0.4, 0, 1, 1) both;
+ transform-origin: bottom center;
+ will-change: transform, opacity, filter;
+ }
+
+ .chat-activity-tab {
+ clip-path: inset(-8px -8px 0 -8px);
}
.chat-message {
@@ -947,6 +963,37 @@
animation: settings-fade-in 150ms ease-out;
}
+ @keyframes chat-activity-enter {
+ from {
+ opacity: 0;
+ filter: blur(3px);
+ transform: translateY(18px) scaleY(0.92);
+ }
+ 65% {
+ opacity: 1;
+ filter: blur(0);
+ transform: translateY(-2px) scaleY(1.01);
+ }
+ to {
+ opacity: 1;
+ filter: blur(0);
+ transform: translateY(0) scaleY(1);
+ }
+ }
+
+ @keyframes chat-activity-exit {
+ from {
+ opacity: 1;
+ filter: blur(0);
+ transform: translateY(0) scaleY(1);
+ }
+ to {
+ opacity: 0;
+ filter: blur(2px);
+ transform: translateY(14px) scaleY(0.96);
+ }
+ }
+
/* Search result highlight flash */
.search-highlight-flash {
animation: search-flash 4s ease-out;
From 1a7f0291b2e20c1f96f06a5827d86d8e28d4a308 Mon Sep 17 00:00:00 2001
From: Haileyesus <118998054+blackmammoth@users.noreply.github.com>
Date: Tue, 30 Jun 2026 11:45:14 +0300
Subject: [PATCH 17/22] style(auth): modernize login, setup, and onboarding
screens
---
src/components/auth/view/AuthErrorAlert.tsx | 7 ++-
src/components/auth/view/AuthInputField.tsx | 58 ++++++++++++++-----
.../auth/view/AuthLoadingScreen.tsx | 26 ++++-----
src/components/auth/view/AuthScreenLayout.tsx | 34 ++++++-----
src/components/auth/view/LoginForm.tsx | 14 ++++-
src/components/auth/view/SetupForm.tsx | 27 +++++++--
src/components/onboarding/view/Onboarding.tsx | 24 +++++---
.../subcomponents/AgentConnectionCard.tsx | 18 +++---
.../subcomponents/AgentConnectionsStep.tsx | 14 ++---
.../subcomponents/GitConfigurationStep.tsx | 16 ++---
.../subcomponents/OnboardingStepProgress.tsx | 16 ++---
11 files changed, 163 insertions(+), 91 deletions(-)
diff --git a/src/components/auth/view/AuthErrorAlert.tsx b/src/components/auth/view/AuthErrorAlert.tsx
index 96a6be411..0325759fe 100644
--- a/src/components/auth/view/AuthErrorAlert.tsx
+++ b/src/components/auth/view/AuthErrorAlert.tsx
@@ -1,3 +1,5 @@
+import { AlertCircle } from 'lucide-react';
+
type AuthErrorAlertProps = {
errorMessage: string;
};
@@ -8,8 +10,9 @@ export default function AuthErrorAlert({ errorMessage }: AuthErrorAlertProps) {
}
return (
-
-
{errorMessage}
+
);
}
diff --git a/src/components/auth/view/AuthInputField.tsx b/src/components/auth/view/AuthInputField.tsx
index b382a059f..a6fa64beb 100644
--- a/src/components/auth/view/AuthInputField.tsx
+++ b/src/components/auth/view/AuthInputField.tsx
@@ -1,3 +1,7 @@
+import { useState } from 'react';
+import type { ComponentType } from 'react';
+import { Eye, EyeOff } from 'lucide-react';
+
type AuthInputFieldProps = {
id: string;
label: string;
@@ -8,13 +12,14 @@ type AuthInputFieldProps = {
type?: 'text' | 'password' | 'email';
name?: string;
autoComplete?: string;
+ icon?: ComponentType<{ className?: string }>;
};
/**
* A labelled input field for authentication forms.
* Renders a `
` / ` ` pair and forwards browser autofill hints
* (`name`, `autoComplete`) so that password managers can identify and fill
- * the field correctly.
+ * the field correctly. Password fields gain a show/hide visibility toggle.
*/
export default function AuthInputField({
id,
@@ -26,24 +31,49 @@ export default function AuthInputField({
type = 'text',
name,
autoComplete,
+ icon: Icon,
}: AuthInputFieldProps) {
+ const [isPasswordVisible, setIsPasswordVisible] = useState(false);
+
+ const isPasswordField = type === 'password';
+ const resolvedType = isPasswordField && isPasswordVisible ? 'text' : type;
+
return (
);
}
diff --git a/src/components/auth/view/AuthLoadingScreen.tsx b/src/components/auth/view/AuthLoadingScreen.tsx
index 9b4987d5c..da151f285 100644
--- a/src/components/auth/view/AuthLoadingScreen.tsx
+++ b/src/components/auth/view/AuthLoadingScreen.tsx
@@ -1,30 +1,30 @@
-import { MessageSquare } from 'lucide-react';
-
-const loadingDotAnimationDelays = ['0s', '0.1s', '0.2s'];
+const loadingDotAnimationDelays = ['0s', '0.15s', '0.3s'];
export default function AuthLoadingScreen() {
return (
-
-
-
-
-
+
+
+
+
+
+
+
-
CloudCLI
+
CloudCLI
-
+
{loadingDotAnimationDelays.map((delay) => (
))}
-
-
Loading...
);
diff --git a/src/components/auth/view/AuthScreenLayout.tsx b/src/components/auth/view/AuthScreenLayout.tsx
index d53ff95f0..6f7f66beb 100644
--- a/src/components/auth/view/AuthScreenLayout.tsx
+++ b/src/components/auth/view/AuthScreenLayout.tsx
@@ -1,5 +1,4 @@
import type { ReactNode } from 'react';
-import { MessageSquare } from 'lucide-react';
import { IS_PLATFORM } from '../../../constants/config';
type AuthScreenLayoutProps = {
@@ -18,29 +17,38 @@ export default function AuthScreenLayout({
logo,
}: AuthScreenLayoutProps) {
return (
-
-
-
+
+ {/* Ambient, on-brand backdrop that gives the screen depth without
+ competing with the card content. Fixed so it stays put while the
+ form scrolls on short viewports. */}
+
+
+
+
-
+
{logo ?? (
-
-
+
+
)}
-
{title}
-
{description}
+
{title}
+
{description}
- {children}
+
{children}
-
-
{footerText}
+
{!IS_PLATFORM && (
-
+
diff --git a/src/components/auth/view/LoginForm.tsx b/src/components/auth/view/LoginForm.tsx
index cf26ca3d9..c806f4209 100644
--- a/src/components/auth/view/LoginForm.tsx
+++ b/src/components/auth/view/LoginForm.tsx
@@ -1,6 +1,7 @@
import { useCallback, useState } from 'react';
import type { FormEvent } from 'react';
import { useTranslation } from 'react-i18next';
+import { Loader2, Lock, User } from 'lucide-react';
import { useAuth } from '../context/AuthContext';
import AuthErrorAlert from './AuthErrorAlert';
import AuthInputField from './AuthInputField';
@@ -69,6 +70,7 @@ export default function LoginForm() {
placeholder={t('login.placeholders.username')}
isDisabled={isSubmitting}
autoComplete="username"
+ icon={User}
/>
@@ -87,9 +90,16 @@ export default function LoginForm() {
- {isSubmitting ? t('login.loading') : t('login.submit')}
+ {isSubmitting ? (
+ <>
+
+ {t('login.loading')}
+ >
+ ) : (
+ t('login.submit')
+ )}
diff --git a/src/components/auth/view/SetupForm.tsx b/src/components/auth/view/SetupForm.tsx
index 213ce165f..c657658e6 100644
--- a/src/components/auth/view/SetupForm.tsx
+++ b/src/components/auth/view/SetupForm.tsx
@@ -1,5 +1,6 @@
import { useCallback, useState } from 'react';
import type { FormEvent } from 'react';
+import { Loader2, Lock, ShieldCheck, User } from 'lucide-react';
import { useAuth } from '../context/AuthContext';
import AuthErrorAlert from './AuthErrorAlert';
import AuthInputField from './AuthInputField';
@@ -85,7 +86,6 @@ export default function SetupForm() {
title="Welcome to CloudCLI"
description="Set up your account to get started"
footerText="This is a single-user system. Only one account can be created."
- logo={
}
>
diff --git a/src/components/onboarding/view/Onboarding.tsx b/src/components/onboarding/view/Onboarding.tsx
index 6d9a69cab..900fb8975 100644
--- a/src/components/onboarding/view/Onboarding.tsx
+++ b/src/components/onboarding/view/Onboarding.tsx
@@ -148,11 +148,18 @@ export default function Onboarding({ onComplete }: OnboardingProps) {
return (
<>
-
-
+
+
+
+
+
-
+
{currentStep === 0 ? (
- {errorMessage}
+
)}
-
+
{isSubmitting ? (
<>
@@ -207,7 +214,7 @@ export default function Onboarding({ onComplete }: OnboardingProps) {
{isSubmitting ? (
<>
@@ -225,6 +232,7 @@ export default function Onboarding({ onComplete }: OnboardingProps) {
+
diff --git a/src/components/onboarding/view/subcomponents/AgentConnectionCard.tsx b/src/components/onboarding/view/subcomponents/AgentConnectionCard.tsx
index 3737ad54c..84d8933e8 100644
--- a/src/components/onboarding/view/subcomponents/AgentConnectionCard.tsx
+++ b/src/components/onboarding/view/subcomponents/AgentConnectionCard.tsx
@@ -31,26 +31,26 @@ export default function AgentConnectionCard({
: status.error || 'Not connected';
return (
-
-
-
-
+
+
+
+
-
-
+
+
{title}
- {status.authenticated && }
+ {status.authenticated && }
-
{statusText}
+
{statusText}
{!status.authenticated && !status.loading && (
Login
diff --git a/src/components/onboarding/view/subcomponents/AgentConnectionsStep.tsx b/src/components/onboarding/view/subcomponents/AgentConnectionsStep.tsx
index 5c66997a1..776e98238 100644
--- a/src/components/onboarding/view/subcomponents/AgentConnectionsStep.tsx
+++ b/src/components/onboarding/view/subcomponents/AgentConnectionsStep.tsx
@@ -51,15 +51,15 @@ export default function AgentConnectionsStep({
onOpenProviderLogin,
}: AgentConnectionsStepProps) {
return (
-
-
-
Connect Your AI Agents
-
+
+
+
Connect Your AI Agents
+
Login to one or more AI coding assistants. All are optional.
-
+
{providerCards.map((providerCard) => (
-
-
You can configure these later in Settings.
-
+ You can configure these later in Settings.
);
}
diff --git a/src/components/onboarding/view/subcomponents/GitConfigurationStep.tsx b/src/components/onboarding/view/subcomponents/GitConfigurationStep.tsx
index 9e1e7b50e..e567a799d 100644
--- a/src/components/onboarding/view/subcomponents/GitConfigurationStep.tsx
+++ b/src/components/onboarding/view/subcomponents/GitConfigurationStep.tsx
@@ -16,13 +16,13 @@ export default function GitConfigurationStep({
onGitEmailChange,
}: GitConfigurationStepProps) {
return (
-
-
-
-
+
+
+
+
-
Git Configuration
-
+
Git Configuration
+
Configure your git identity to ensure proper attribution for commits.
@@ -38,7 +38,7 @@ export default function GitConfigurationStep({
id="gitName"
value={gitName}
onChange={(event) => onGitNameChange(event.target.value)}
- className="w-full rounded-lg border border-border bg-background px-4 py-3 text-foreground focus:border-transparent focus:outline-none focus:ring-2 focus:ring-blue-500"
+ className="w-full rounded-xl border border-border bg-background/60 px-4 py-2.5 text-foreground shadow-sm transition-colors placeholder:text-muted-foreground/60 hover:border-foreground/20 focus:border-primary focus:outline-none focus:ring-2 focus:ring-primary/30"
placeholder="John Doe"
required
disabled={isSubmitting}
@@ -56,7 +56,7 @@ export default function GitConfigurationStep({
id="gitEmail"
value={gitEmail}
onChange={(event) => onGitEmailChange(event.target.value)}
- className="w-full rounded-lg border border-border bg-background px-4 py-3 text-foreground focus:border-transparent focus:outline-none focus:ring-2 focus:ring-blue-500"
+ className="w-full rounded-xl border border-border bg-background/60 px-4 py-2.5 text-foreground shadow-sm transition-colors placeholder:text-muted-foreground/60 hover:border-foreground/20 focus:border-primary focus:outline-none focus:ring-2 focus:ring-primary/30"
placeholder="john@example.com"
required
disabled={isSubmitting}
diff --git a/src/components/onboarding/view/subcomponents/OnboardingStepProgress.tsx b/src/components/onboarding/view/subcomponents/OnboardingStepProgress.tsx
index f4ce0a115..4a25301bc 100644
--- a/src/components/onboarding/view/subcomponents/OnboardingStepProgress.tsx
+++ b/src/components/onboarding/view/subcomponents/OnboardingStepProgress.tsx
@@ -11,7 +11,7 @@ const onboardingSteps = [
export default function OnboardingStepProgress({ currentStep }: OnboardingStepProgressProps) {
return (
-
+
{onboardingSteps.map((step, index) => {
const isCompleted = index < currentStep;
@@ -22,18 +22,18 @@ export default function OnboardingStepProgress({ currentStep }: OnboardingStepPr
- {isCompleted ? : }
+ {isCompleted ? : }
-
+
{step.title}
@@ -42,7 +42,7 @@ export default function OnboardingStepProgress({ currentStep }: OnboardingStepPr
{index < onboardingSteps.length - 1 && (
-
+
)}
);
From 858bed609a7b8282d2e270a421550192be4dba2d Mon Sep 17 00:00:00 2001
From: Haileyesus <118998054+blackmammoth@users.noreply.github.com>
Date: Tue, 30 Jun 2026 15:29:18 +0300
Subject: [PATCH 18/22] fix(chat): correct invalid dark-mode hover on
AskUserQuestion options
---
.../components/InteractiveRenderers/AskUserQuestionPanel.tsx | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/components/chat/tools/components/InteractiveRenderers/AskUserQuestionPanel.tsx b/src/components/chat/tools/components/InteractiveRenderers/AskUserQuestionPanel.tsx
index 5a75390fb..ed7e8c97b 100644
--- a/src/components/chat/tools/components/InteractiveRenderers/AskUserQuestionPanel.tsx
+++ b/src/components/chat/tools/components/InteractiveRenderers/AskUserQuestionPanel.tsx
@@ -229,7 +229,7 @@ export const AskUserQuestionPanel: React.FC
= ({
className={`group flex w-full items-center gap-2.5 rounded-lg border px-3 py-2 text-left transition-all duration-150 ${
isSelected
? 'border-blue-300 bg-blue-50/80 ring-1 ring-blue-200/50 dark:border-blue-600 dark:bg-blue-900/25 dark:ring-blue-700/30'
- : 'dark:hover:bg-gray-750/50 border-gray-200 hover:border-gray-300 hover:bg-gray-50/60 dark:border-gray-700/60 dark:hover:border-gray-600'
+ : 'border-gray-200 hover:border-gray-300 hover:bg-gray-50/60 dark:border-gray-700/60 dark:hover:border-gray-600 dark:hover:bg-gray-700/40'
}`}
>
{/* Keyboard hint */}
@@ -277,7 +277,7 @@ export const AskUserQuestionPanel: React.FC = ({
className={`group flex w-full items-center gap-2.5 rounded-lg border px-3 py-2 text-left transition-all duration-150 ${
isOtherOn
? 'border-blue-300 bg-blue-50/80 ring-1 ring-blue-200/50 dark:border-blue-600 dark:bg-blue-900/25 dark:ring-blue-700/30'
- : 'dark:hover:bg-gray-750/50 border-dashed border-gray-200 hover:border-gray-300 hover:bg-gray-50/60 dark:border-gray-700/60 dark:hover:border-gray-600'
+ : 'border-dashed border-gray-200 hover:border-gray-300 hover:bg-gray-50/60 dark:border-gray-700/60 dark:hover:border-gray-600 dark:hover:bg-gray-700/40'
}`}
>
Date: Tue, 30 Jun 2026 16:12:23 +0300
Subject: [PATCH 19/22] fix: remove unnecessary auto expand tools
---
src/components/chat/tools/ToolRenderer.tsx | 10 +++---
src/components/chat/types/types.ts | 1 -
src/components/chat/view/ChatInterface.tsx | 2 --
.../view/subcomponents/ChatMessagesPane.tsx | 4 ---
.../view/subcomponents/MessageComponent.tsx | 34 ++-----------------
.../view/subcomponents/ToolGroupContainer.tsx | 3 --
.../main-content/view/MainContent.tsx | 3 +-
.../quick-settings-panel/constants.ts | 6 ----
src/components/quick-settings-panel/types.ts | 1 -
.../view/QuickSettingsPanelView.tsx | 2 --
src/hooks/useUiPreferences.ts | 2 --
src/i18n/locales/de/settings.json | 1 -
src/i18n/locales/en/settings.json | 1 -
src/i18n/locales/fr/settings.json | 1 -
src/i18n/locales/it/settings.json | 1 -
src/i18n/locales/ja/settings.json | 1 -
src/i18n/locales/ko/settings.json | 1 -
src/i18n/locales/ru/settings.json | 1 -
src/i18n/locales/tr/settings.json | 1 -
src/i18n/locales/zh-CN/settings.json | 1 -
src/i18n/locales/zh-TW/settings.json | 1 -
21 files changed, 7 insertions(+), 71 deletions(-)
diff --git a/src/components/chat/tools/ToolRenderer.tsx b/src/components/chat/tools/ToolRenderer.tsx
index 0d9e1f6a8..f9ebfbe5e 100644
--- a/src/components/chat/tools/ToolRenderer.tsx
+++ b/src/components/chat/tools/ToolRenderer.tsx
@@ -24,7 +24,6 @@ interface ToolRendererProps {
onFileOpen?: (filePath: string, diffInfo?: any) => void;
createDiff?: (oldStr: string, newStr: string) => DiffLine[];
selectedProject?: Project | null;
- autoExpandTools?: boolean;
showRawParameters?: boolean;
rawToolInput?: string;
isSubagentContainer?: boolean;
@@ -80,7 +79,6 @@ export const ToolRenderer: React.FC = memo(({
onFileOpen,
createDiff,
selectedProject,
- autoExpandTools = false,
showRawParameters = false,
rawToolInput,
isSubagentContainer,
@@ -151,8 +149,8 @@ export const ToolRenderer: React.FC = memo(({
output={output}
isError={Boolean(toolResult?.isError)}
status={toolStatus !== 'completed' ? toolStatus : undefined}
- // Commands stay collapsed by default (even consecutive ones); only
- // failures auto-expand so they remain visible.
+ // Commands stay collapsed by default; only failures auto-expand so they
+ // remain visible.
defaultOpen={false}
/>
);
@@ -199,7 +197,7 @@ export const ToolRenderer: React.FC = memo(({
= memo(({
const defaultOpen = displayConfig.defaultOpen !== undefined
? displayConfig.defaultOpen
- : autoExpandTools;
+ : false;
const contentProps = displayConfig.getContentProps?.(parsedData, {
selectedProject,
diff --git a/src/components/chat/types/types.ts b/src/components/chat/types/types.ts
index fdeab8df5..15cb90b84 100644
--- a/src/components/chat/types/types.ts
+++ b/src/components/chat/types/types.ts
@@ -126,7 +126,6 @@ export interface ChatInterfaceProps {
onNavigateToSession?: (targetSessionId: string, options?: SessionNavigationOptions) => void;
onSessionEstablished?: (sessionId: string, context: SessionEstablishedContext) => void;
onShowSettings?: () => void;
- autoExpandTools?: boolean;
showRawParameters?: boolean;
showThinking?: boolean;
sendByCtrlEnter?: boolean;
diff --git a/src/components/chat/view/ChatInterface.tsx b/src/components/chat/view/ChatInterface.tsx
index 103dea817..96980179f 100644
--- a/src/components/chat/view/ChatInterface.tsx
+++ b/src/components/chat/view/ChatInterface.tsx
@@ -31,7 +31,6 @@ function ChatInterface({
onNavigateToSession,
onSessionEstablished,
onShowSettings,
- autoExpandTools,
showRawParameters,
showThinking,
sendByCtrlEnter,
@@ -355,7 +354,6 @@ function ChatInterface({
onFileOpen={onFileOpen}
onShowSettings={onShowSettings}
onGrantToolPermission={handleGrantToolPermission}
- autoExpandTools={autoExpandTools}
showRawParameters={showRawParameters}
showThinking={showThinking}
selectedProject={selectedProject}
diff --git a/src/components/chat/view/subcomponents/ChatMessagesPane.tsx b/src/components/chat/view/subcomponents/ChatMessagesPane.tsx
index a437a4f89..0b716c3b5 100644
--- a/src/components/chat/view/subcomponents/ChatMessagesPane.tsx
+++ b/src/components/chat/view/subcomponents/ChatMessagesPane.tsx
@@ -62,7 +62,6 @@ interface ChatMessagesPaneProps {
onFileOpen?: (filePath: string, diffInfo?: unknown) => void;
onShowSettings?: () => void;
onGrantToolPermission: (suggestion: { entry: string; toolName: string }) => { success: boolean };
- autoExpandTools?: boolean;
showRawParameters?: boolean;
showThinking?: boolean;
selectedProject: Project;
@@ -112,7 +111,6 @@ function ChatMessagesPane({
onFileOpen,
onShowSettings,
onGrantToolPermission,
- autoExpandTools,
showRawParameters,
showThinking,
selectedProject,
@@ -264,7 +262,6 @@ function ChatMessagesPane({
onFileOpen={onFileOpen}
onShowSettings={onShowSettings}
onGrantToolPermission={onGrantToolPermission}
- autoExpandTools={autoExpandTools}
showRawParameters={showRawParameters}
showThinking={showThinking}
selectedProject={selectedProject}
@@ -285,7 +282,6 @@ function ChatMessagesPane({
onFileOpen={onFileOpen}
onShowSettings={onShowSettings}
onGrantToolPermission={onGrantToolPermission}
- autoExpandTools={autoExpandTools}
showRawParameters={showRawParameters}
showThinking={showThinking}
selectedProject={selectedProject}
diff --git a/src/components/chat/view/subcomponents/MessageComponent.tsx b/src/components/chat/view/subcomponents/MessageComponent.tsx
index cfe852fed..b486da614 100644
--- a/src/components/chat/view/subcomponents/MessageComponent.tsx
+++ b/src/components/chat/view/subcomponents/MessageComponent.tsx
@@ -1,4 +1,4 @@
-import { memo, useEffect, useMemo, useRef, useState } from 'react';
+import { memo, useMemo, useRef } from 'react';
import { useTranslation } from 'react-i18next';
import SessionProviderLogo from '../../../llm-logo-provider/SessionProviderLogo';
@@ -30,7 +30,6 @@ type MessageComponentProps = {
onFileOpen?: (filePath: string, diffInfo?: unknown) => void;
onShowSettings?: () => void;
onGrantToolPermission?: (suggestion: ClaudePermissionSuggestion) => PermissionGrantResult | null | undefined;
- autoExpandTools?: boolean;
showRawParameters?: boolean;
showThinking?: boolean;
selectedProject?: Project | null;
@@ -45,7 +44,7 @@ type InteractiveOption = {
const COPY_HIDDEN_TOOL_NAMES = new Set(['Bash', 'Edit', 'Write', 'ApplyPatch']);
-const MessageComponent = memo(({ message, prevMessage, createDiff, onFileOpen, autoExpandTools, showRawParameters, showThinking, selectedProject, provider }: MessageComponentProps) => {
+const MessageComponent = memo(({ message, prevMessage, createDiff, onFileOpen, showRawParameters, showThinking, selectedProject, provider }: MessageComponentProps) => {
const { t } = useTranslation('chat');
const isGrouped = prevMessage && prevMessage.type === message.type &&
((prevMessage.type === 'assistant') ||
@@ -53,7 +52,6 @@ const MessageComponent = memo(({ message, prevMessage, createDiff, onFileOpen, a
(prevMessage.type === 'tool') ||
(prevMessage.type === 'error'));
const messageRef = useRef(null);
- const [isExpanded, setIsExpanded] = useState(false);
const userCopyContent = String(message.content || '');
const formattedMessageContent = useMemo(
() => formatUsageLimitText(String(message.content || '')),
@@ -72,32 +70,6 @@ const MessageComponent = memo(({ message, prevMessage, createDiff, onFileOpen, a
!message.isThinking;
- useEffect(() => {
- const node = messageRef.current;
- if (!autoExpandTools || !node || !message.isToolUse) return;
-
- const observer = new IntersectionObserver(
- (entries) => {
- entries.forEach((entry) => {
- if (entry.isIntersecting && !isExpanded) {
- setIsExpanded(true);
- const details = node.querySelectorAll('details');
- details.forEach((detail) => {
- detail.open = true;
- });
- }
- });
- },
- { threshold: 0.1 }
- );
-
- observer.observe(node);
-
- return () => {
- observer.unobserve(node);
- };
- }, [autoExpandTools, isExpanded, message.isToolUse]);
-
const formattedTime = useMemo(() => new Date(message.timestamp).toLocaleTimeString(), [message.timestamp]);
const shouldHideThinkingMessage = Boolean(message.isThinking && !showThinking);
@@ -210,7 +182,6 @@ const MessageComponent = memo(({ message, prevMessage, createDiff, onFileOpen, a
onFileOpen={onFileOpen}
createDiff={createDiff}
selectedProject={selectedProject}
- autoExpandTools={autoExpandTools}
showRawParameters={showRawParameters}
rawToolInput={typeof message.toolInput === 'string' ? message.toolInput : undefined}
isSubagentContainer={message.isSubagentContainer}
@@ -250,7 +221,6 @@ const MessageComponent = memo(({ message, prevMessage, createDiff, onFileOpen, a
onFileOpen={onFileOpen}
createDiff={createDiff}
selectedProject={selectedProject}
- autoExpandTools={autoExpandTools}
/>
)
diff --git a/src/components/chat/view/subcomponents/ToolGroupContainer.tsx b/src/components/chat/view/subcomponents/ToolGroupContainer.tsx
index 5fc5e8379..79e1a02df 100644
--- a/src/components/chat/view/subcomponents/ToolGroupContainer.tsx
+++ b/src/components/chat/view/subcomponents/ToolGroupContainer.tsx
@@ -22,7 +22,6 @@ interface ToolGroupContainerProps {
onFileOpen?: (filePath: string, diffInfo?: unknown) => void;
onShowSettings?: () => void;
onGrantToolPermission?: (suggestion: ClaudePermissionSuggestion) => PermissionGrantResult | null | undefined;
- autoExpandTools?: boolean;
showRawParameters?: boolean;
showThinking?: boolean;
selectedProject?: Project | null;
@@ -66,7 +65,6 @@ export default function ToolGroupContainer({
onFileOpen,
onShowSettings,
onGrantToolPermission,
- autoExpandTools,
showRawParameters,
showThinking,
selectedProject,
@@ -133,7 +131,6 @@ export default function ToolGroupContainer({
onFileOpen={onFileOpen}
onShowSettings={onShowSettings}
onGrantToolPermission={onGrantToolPermission}
- autoExpandTools={autoExpandTools}
showRawParameters={showRawParameters}
showThinking={showThinking}
selectedProject={selectedProject}
diff --git a/src/components/main-content/view/MainContent.tsx b/src/components/main-content/view/MainContent.tsx
index 9b00f926f..6f7468578 100644
--- a/src/components/main-content/view/MainContent.tsx
+++ b/src/components/main-content/view/MainContent.tsx
@@ -54,7 +54,7 @@ function MainContent({
newSessionTrigger,
}: MainContentProps) {
const { preferences } = useUiPreferences();
- const { autoExpandTools, showRawParameters, showThinking, sendByCtrlEnter } = preferences;
+ const { showRawParameters, showThinking, sendByCtrlEnter } = preferences;
const { currentProject, setCurrentProject } = useTaskMaster() as TaskMasterContextValue;
const { tasksEnabled, isTaskMasterInstalled } = useTasksSettings() as TasksSettingsContextValue;
@@ -170,7 +170,6 @@ function MainContent({
onNavigateToSession={onNavigateToSession}
onSessionEstablished={onSessionEstablished}
onShowSettings={onShowSettings}
- autoExpandTools={autoExpandTools}
showRawParameters={showRawParameters}
showThinking={showThinking}
sendByCtrlEnter={sendByCtrlEnter}
diff --git a/src/components/quick-settings-panel/constants.ts b/src/components/quick-settings-panel/constants.ts
index 3810d9ba2..91cfbafc4 100644
--- a/src/components/quick-settings-panel/constants.ts
+++ b/src/components/quick-settings-panel/constants.ts
@@ -2,7 +2,6 @@ import {
Brain,
Eye,
Languages,
- Maximize2,
Mic,
} from 'lucide-react';
@@ -24,11 +23,6 @@ export const CHECKBOX_CLASS =
'h-4 w-4 rounded border-gray-300 dark:border-gray-600 text-blue-600 dark:text-blue-500 focus:ring-blue-500 focus:ring-2 dark:focus:ring-blue-400 bg-gray-100 dark:bg-gray-800 checked:bg-blue-600 dark:checked:bg-blue-600';
export const TOOL_DISPLAY_TOGGLES: PreferenceToggleItem[] = [
- {
- key: 'autoExpandTools',
- labelKey: 'quickSettings.autoExpandTools',
- icon: Maximize2,
- },
{
key: 'showRawParameters',
labelKey: 'quickSettings.showRawParameters',
diff --git a/src/components/quick-settings-panel/types.ts b/src/components/quick-settings-panel/types.ts
index a02401e8f..8bb760d5b 100644
--- a/src/components/quick-settings-panel/types.ts
+++ b/src/components/quick-settings-panel/types.ts
@@ -2,7 +2,6 @@ import type { CSSProperties } from 'react';
import type { LucideIcon } from 'lucide-react';
export type PreferenceToggleKey =
- | 'autoExpandTools'
| 'showRawParameters'
| 'showThinking'
| 'sendByCtrlEnter'
diff --git a/src/components/quick-settings-panel/view/QuickSettingsPanelView.tsx b/src/components/quick-settings-panel/view/QuickSettingsPanelView.tsx
index d42a73062..07535d258 100644
--- a/src/components/quick-settings-panel/view/QuickSettingsPanelView.tsx
+++ b/src/components/quick-settings-panel/view/QuickSettingsPanelView.tsx
@@ -24,13 +24,11 @@ export default function QuickSettingsPanelView() {
} = useQuickSettingsDrag({ isMobile });
const quickSettingsPreferences = useMemo
(() => ({
- autoExpandTools: preferences.autoExpandTools,
showRawParameters: preferences.showRawParameters,
showThinking: preferences.showThinking,
sendByCtrlEnter: preferences.sendByCtrlEnter,
voiceEnabled: preferences.voiceEnabled,
}), [
- preferences.autoExpandTools,
preferences.sendByCtrlEnter,
preferences.showRawParameters,
preferences.showThinking,
diff --git a/src/hooks/useUiPreferences.ts b/src/hooks/useUiPreferences.ts
index b4531ba96..35e03aeb7 100644
--- a/src/hooks/useUiPreferences.ts
+++ b/src/hooks/useUiPreferences.ts
@@ -1,7 +1,6 @@
import { useEffect, useReducer, useRef } from 'react';
type UiPreferences = {
- autoExpandTools: boolean;
showRawParameters: boolean;
showThinking: boolean;
sendByCtrlEnter: boolean;
@@ -33,7 +32,6 @@ type UiPreferencesAction =
| ResetPreferencesAction;
const DEFAULTS: UiPreferences = {
- autoExpandTools: false,
showRawParameters: false,
showThinking: true,
sendByCtrlEnter: false,
diff --git a/src/i18n/locales/de/settings.json b/src/i18n/locales/de/settings.json
index 85fb4c845..958735bd9 100644
--- a/src/i18n/locales/de/settings.json
+++ b/src/i18n/locales/de/settings.json
@@ -57,7 +57,6 @@
"inputSettings": "Eingabeeinstellungen"
},
"darkMode": "Darkmode",
- "autoExpandTools": "Werkzeuge automatisch erweitern",
"showRawParameters": "Rohe Parameter anzeigen",
"showThinking": "Denken anzeigen",
"sendByCtrlEnter": "Mit Strg+Enter senden",
diff --git a/src/i18n/locales/en/settings.json b/src/i18n/locales/en/settings.json
index 7c779d219..aabfc1438 100644
--- a/src/i18n/locales/en/settings.json
+++ b/src/i18n/locales/en/settings.json
@@ -73,7 +73,6 @@
"inputSettings": "Input Settings"
},
"darkMode": "Dark Mode",
- "autoExpandTools": "Auto-expand tools",
"showRawParameters": "Show raw parameters",
"showThinking": "Show thinking",
"sendByCtrlEnter": "Send by Ctrl+Enter",
diff --git a/src/i18n/locales/fr/settings.json b/src/i18n/locales/fr/settings.json
index ec3c59ec7..bb25cd8a1 100644
--- a/src/i18n/locales/fr/settings.json
+++ b/src/i18n/locales/fr/settings.json
@@ -57,7 +57,6 @@
"inputSettings": "Paramètres de saisie"
},
"darkMode": "Mode sombre",
- "autoExpandTools": "Développer automatiquement les outils",
"showRawParameters": "Afficher les paramètres bruts",
"showThinking": "Afficher la réflexion",
"sendByCtrlEnter": "Envoyer avec Ctrl+Entrée",
diff --git a/src/i18n/locales/it/settings.json b/src/i18n/locales/it/settings.json
index 28e8a1e30..45f320f18 100644
--- a/src/i18n/locales/it/settings.json
+++ b/src/i18n/locales/it/settings.json
@@ -57,7 +57,6 @@
"inputSettings": "Impostazioni input"
},
"darkMode": "Modalità scura",
- "autoExpandTools": "Espandi strumenti automaticamente",
"showRawParameters": "Mostra parametri grezzi",
"showThinking": "Mostra ragionamento",
"sendByCtrlEnter": "Invia con Ctrl+Invio",
diff --git a/src/i18n/locales/ja/settings.json b/src/i18n/locales/ja/settings.json
index d59e32a03..ee3b7f204 100644
--- a/src/i18n/locales/ja/settings.json
+++ b/src/i18n/locales/ja/settings.json
@@ -57,7 +57,6 @@
"inputSettings": "入力設定"
},
"darkMode": "ダークモード",
- "autoExpandTools": "ツールを自動展開",
"showRawParameters": "生パラメータを表示",
"showThinking": "思考を表示",
"sendByCtrlEnter": "Ctrl+Enterで送信",
diff --git a/src/i18n/locales/ko/settings.json b/src/i18n/locales/ko/settings.json
index c45c7227b..6a23ac6c6 100644
--- a/src/i18n/locales/ko/settings.json
+++ b/src/i18n/locales/ko/settings.json
@@ -57,7 +57,6 @@
"inputSettings": "입력 설정"
},
"darkMode": "다크 모드",
- "autoExpandTools": "도구 자동 펼치기",
"showRawParameters": "Raw 파라미터 표시",
"showThinking": "생각 과정 표시",
"sendByCtrlEnter": "Ctrl+Enter로 전송",
diff --git a/src/i18n/locales/ru/settings.json b/src/i18n/locales/ru/settings.json
index f83881dcb..480cbcdfd 100644
--- a/src/i18n/locales/ru/settings.json
+++ b/src/i18n/locales/ru/settings.json
@@ -57,7 +57,6 @@
"inputSettings": "Настройки ввода"
},
"darkMode": "Темная тема",
- "autoExpandTools": "Автоматически разворачивать инструменты",
"showRawParameters": "Показывать сырые параметры",
"showThinking": "Показывать размышления",
"sendByCtrlEnter": "Отправка по Ctrl+Enter",
diff --git a/src/i18n/locales/tr/settings.json b/src/i18n/locales/tr/settings.json
index 4c56722a4..00b0465bd 100644
--- a/src/i18n/locales/tr/settings.json
+++ b/src/i18n/locales/tr/settings.json
@@ -57,7 +57,6 @@
"inputSettings": "Girdi Ayarları"
},
"darkMode": "Koyu Mod",
- "autoExpandTools": "Araçları otomatik genişlet",
"showRawParameters": "Ham parametreleri göster",
"showThinking": "Düşünmeyi göster",
"sendByCtrlEnter": "Ctrl+Enter ile gönder",
diff --git a/src/i18n/locales/zh-CN/settings.json b/src/i18n/locales/zh-CN/settings.json
index 518edb43b..e383f84fe 100644
--- a/src/i18n/locales/zh-CN/settings.json
+++ b/src/i18n/locales/zh-CN/settings.json
@@ -57,7 +57,6 @@
"inputSettings": "输入设置"
},
"darkMode": "深色模式",
- "autoExpandTools": "自动展开工具",
"showRawParameters": "显示原始参数",
"showThinking": "显示思考过程",
"sendByCtrlEnter": "使用 Ctrl+Enter 发送",
diff --git a/src/i18n/locales/zh-TW/settings.json b/src/i18n/locales/zh-TW/settings.json
index 7bda49eef..1f1fe22fa 100644
--- a/src/i18n/locales/zh-TW/settings.json
+++ b/src/i18n/locales/zh-TW/settings.json
@@ -57,7 +57,6 @@
"inputSettings": "輸入設定"
},
"darkMode": "深色模式",
- "autoExpandTools": "自動展開工具",
"showRawParameters": "顯示原始參數",
"showThinking": "顯示思考過程",
"sendByCtrlEnter": "使用 Ctrl+Enter 傳送",
From 71ef31441b143bcffbf87d9820a7f18ab5da3c3d Mon Sep 17 00:00:00 2001
From: Haileyesus <118998054+blackmammoth@users.noreply.github.com>
Date: Wed, 1 Jul 2026 11:40:39 +0300
Subject: [PATCH 20/22] fix: resolve coderabbit comments
---
src/components/auth/view/AuthErrorAlert.tsx | 5 ++++-
src/components/auth/view/AuthInputField.tsx | 3 +--
src/components/auth/view/AuthLoadingScreen.tsx | 6 +++---
src/components/chat/view/ChatInterface.tsx | 3 ++-
.../view/subcomponents/MainContentTitle.tsx | 2 +-
src/components/onboarding/view/Onboarding.tsx | 13 ++++++++-----
.../view/subcomponents/AgentConnectionCard.tsx | 2 +-
src/index.css | 9 +++++----
8 files changed, 25 insertions(+), 18 deletions(-)
diff --git a/src/components/auth/view/AuthErrorAlert.tsx b/src/components/auth/view/AuthErrorAlert.tsx
index 0325759fe..b9b656252 100644
--- a/src/components/auth/view/AuthErrorAlert.tsx
+++ b/src/components/auth/view/AuthErrorAlert.tsx
@@ -10,7 +10,10 @@ export default function AuthErrorAlert({ errorMessage }: AuthErrorAlertProps) {
}
return (
-
+
diff --git a/src/components/auth/view/AuthInputField.tsx b/src/components/auth/view/AuthInputField.tsx
index a6fa64beb..86b688543 100644
--- a/src/components/auth/view/AuthInputField.tsx
+++ b/src/components/auth/view/AuthInputField.tsx
@@ -66,9 +66,8 @@ export default function AuthInputField({
type="button"
onClick={() => setIsPasswordVisible((previous) => !previous)}
disabled={isDisabled}
- tabIndex={-1}
aria-label={isPasswordVisible ? 'Hide password' : 'Show password'}
- className="absolute right-2 top-1/2 flex h-7 w-7 -translate-y-1/2 items-center justify-center rounded-lg text-muted-foreground transition-colors hover:bg-muted hover:text-foreground disabled:opacity-60"
+ className="absolute right-2 top-1/2 flex h-7 w-7 -translate-y-1/2 items-center justify-center rounded-lg text-muted-foreground transition-colors hover:bg-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/40 disabled:opacity-60"
>
{isPasswordVisible ?
:
}
diff --git a/src/components/auth/view/AuthLoadingScreen.tsx b/src/components/auth/view/AuthLoadingScreen.tsx
index da151f285..5855e56a4 100644
--- a/src/components/auth/view/AuthLoadingScreen.tsx
+++ b/src/components/auth/view/AuthLoadingScreen.tsx
@@ -7,7 +7,7 @@ export default function AuthLoadingScreen() {
-
+
@@ -15,8 +15,8 @@ export default function AuthLoadingScreen() {
CloudCLI
-
-
+
Loading authentication state…
+
{loadingDotAnimationDelays.map((delay) => (
)}
diff --git a/src/components/main-content/view/subcomponents/MainContentTitle.tsx b/src/components/main-content/view/subcomponents/MainContentTitle.tsx
index e3d8776f2..bc53d3a11 100644
--- a/src/components/main-content/view/subcomponents/MainContentTitle.tsx
+++ b/src/components/main-content/view/subcomponents/MainContentTitle.tsx
@@ -70,7 +70,7 @@ export default function MainContentTitle({
{activeTab === 'chat' && selectedSession ? (
-
+
{getSessionTitle(selectedSession)}
{selectedProject.displayName}
diff --git a/src/components/onboarding/view/Onboarding.tsx b/src/components/onboarding/view/Onboarding.tsx
index 900fb8975..5416a8e27 100644
--- a/src/components/onboarding/view/Onboarding.tsx
+++ b/src/components/onboarding/view/Onboarding.tsx
@@ -175,11 +175,14 @@ export default function Onboarding({ onComplete }: OnboardingProps) {
/>
)}
- {errorMessage && (
-
- )}
+ {errorMessage && (
+
+ )}
}
- {statusText}
+ {statusText}
diff --git a/src/index.css b/src/index.css
index 58ef2874d..adbcb0dea 100644
--- a/src/index.css
+++ b/src/index.css
@@ -128,6 +128,7 @@
body {
@apply bg-background text-foreground;
+
font-family: "Encode Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
@@ -964,7 +965,7 @@
}
@keyframes chat-activity-enter {
- from {
+ 0% {
opacity: 0;
filter: blur(3px);
transform: translateY(18px) scaleY(0.92);
@@ -974,7 +975,7 @@
filter: blur(0);
transform: translateY(-2px) scaleY(1.01);
}
- to {
+ 100% {
opacity: 1;
filter: blur(0);
transform: translateY(0) scaleY(1);
@@ -982,12 +983,12 @@
}
@keyframes chat-activity-exit {
- from {
+ 0% {
opacity: 1;
filter: blur(0);
transform: translateY(0) scaleY(1);
}
- to {
+ 100% {
opacity: 0;
filter: blur(2px);
transform: translateY(14px) scaleY(0.96);
From 2071162842487cbd4d201fd8e30b370728f834e5 Mon Sep 17 00:00:00 2001
From: Haileyesus <118998054+blackmammoth@users.noreply.github.com>
Date: Wed, 1 Jul 2026 14:32:18 +0300
Subject: [PATCH 21/22] fix(chat): widen chat layout and sidebar titles
---
src/components/chat/view/subcomponents/ChatComposer.tsx | 6 +++---
src/components/chat/view/subcomponents/ChatMessagesPane.tsx | 2 +-
.../chat/view/subcomponents/ProviderSelectionEmptyState.tsx | 4 ++--
.../sidebar/view/subcomponents/SidebarSessionItem.tsx | 4 ++--
4 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/src/components/chat/view/subcomponents/ChatComposer.tsx b/src/components/chat/view/subcomponents/ChatComposer.tsx
index 02eeaac6a..cc3f397c8 100644
--- a/src/components/chat/view/subcomponents/ChatComposer.tsx
+++ b/src/components/chat/view/subcomponents/ChatComposer.tsx
@@ -202,13 +202,13 @@ export default function ChatComposer({
return (
{!hasPendingPermissions && (
-
+
)}
{pendingPermissionRequests.length > 0 && (
-
+
)}
- {!hasQuestionPanel &&
+ {!hasQuestionPanel &&
{showFileDropdown && filteredFiles.length > 0 && (
{filteredFiles.map((file, index) => (
diff --git a/src/components/chat/view/subcomponents/ChatMessagesPane.tsx b/src/components/chat/view/subcomponents/ChatMessagesPane.tsx
index 0b716c3b5..6c9ba116d 100644
--- a/src/components/chat/view/subcomponents/ChatMessagesPane.tsx
+++ b/src/components/chat/view/subcomponents/ChatMessagesPane.tsx
@@ -163,7 +163,7 @@ function ChatMessagesPane({
onTouchMove={onTouchMove}
className="chat-messages-pane relative min-h-0 flex-1 overflow-y-auto overflow-x-hidden py-3 sm:py-4"
>
-
+
{(isLoadingSessionMessages || isProcessing) && chatMessages.length === 0 ? (
diff --git a/src/components/chat/view/subcomponents/ProviderSelectionEmptyState.tsx b/src/components/chat/view/subcomponents/ProviderSelectionEmptyState.tsx
index 6d97ca886..a2bc74e82 100644
--- a/src/components/chat/view/subcomponents/ProviderSelectionEmptyState.tsx
+++ b/src/components/chat/view/subcomponents/ProviderSelectionEmptyState.tsx
@@ -186,7 +186,7 @@ export default function ProviderSelectionEmptyState({
if (!selectedSession && !currentSessionId) {
return (
-
+
{t("providerSelection.title")}
@@ -352,7 +352,7 @@ export default function ProviderSelectionEmptyState({
if (selectedSession) {
return (
-
+
{t("session.continue.title")}
diff --git a/src/components/sidebar/view/subcomponents/SidebarSessionItem.tsx b/src/components/sidebar/view/subcomponents/SidebarSessionItem.tsx
index 1ab404756..85a252509 100644
--- a/src/components/sidebar/view/subcomponents/SidebarSessionItem.tsx
+++ b/src/components/sidebar/view/subcomponents/SidebarSessionItem.tsx
@@ -157,7 +157,7 @@ export default function SidebarSessionItem({
-
{sessionView.sessionName}
+
{sessionView.sessionName}
{isProcessing ? (
@@ -226,7 +226,7 @@ export default function SidebarSessionItem({
-
{sessionView.sessionName}
+
{sessionView.sessionName}
{isProcessing ? (
Date: Wed, 1 Jul 2026 14:37:00 +0300
Subject: [PATCH 22/22] fix(branding): update CloudCLI wordmark styling
---
src/components/auth/view/AuthLoadingScreen.tsx | 9 ++++++++-
src/components/settings/view/tabs/AboutTab.tsx | 12 +++++++++---
.../api-settings/sections/VersionInfoSection.tsx | 9 ++++++++-
.../sidebar/view/subcomponents/SidebarHeader.tsx | 8 +++++++-
src/constants/branding.ts | 2 ++
5 files changed, 34 insertions(+), 6 deletions(-)
create mode 100644 src/constants/branding.ts
diff --git a/src/components/auth/view/AuthLoadingScreen.tsx b/src/components/auth/view/AuthLoadingScreen.tsx
index 5855e56a4..86a80ce2d 100644
--- a/src/components/auth/view/AuthLoadingScreen.tsx
+++ b/src/components/auth/view/AuthLoadingScreen.tsx
@@ -1,3 +1,5 @@
+import { CLOUDCLI_WORDMARK_FONT_FAMILY } from '../../../constants/branding';
+
const loadingDotAnimationDelays = ['0s', '0.15s', '0.3s'];
export default function AuthLoadingScreen() {
@@ -14,7 +16,12 @@ export default function AuthLoadingScreen() {
-
CloudCLI
+
+ CloudCLI
+
Loading authentication state…
{loadingDotAnimationDelays.map((delay) => (
diff --git a/src/components/settings/view/tabs/AboutTab.tsx b/src/components/settings/view/tabs/AboutTab.tsx
index 027af75eb..0216f17d8 100644
--- a/src/components/settings/view/tabs/AboutTab.tsx
+++ b/src/components/settings/view/tabs/AboutTab.tsx
@@ -1,9 +1,10 @@
-import { ExternalLink, MessageSquare, Star } from 'lucide-react';
+import { Cloud, ExternalLink, MessageSquare, Star, Users } from 'lucide-react';
import { useTranslation } from 'react-i18next';
+
+import { CLOUDCLI_WORDMARK_FONT_FAMILY } from '../../../../constants/branding';
import { IS_PLATFORM } from '../../../../constants/config';
import { useVersionCheck } from '../../../../hooks/useVersionCheck';
import PremiumFeatureCard from '../PremiumFeatureCard';
-import { Cloud, Users } from 'lucide-react';
const GITHUB_REPO_URL = 'https://github.com/siteboon/claudecodeui';
const DISCORD_URL = 'https://discord.gg/buxwujPNRE';
@@ -40,7 +41,12 @@ export default function AboutTab() {