Skip to content

Commit 5e35f3f

Browse files
authored
Merge pull request #495 from Mng-dev-ai/fix/frontend-claude-md-compliance
Fix frontend CLAUDE.md rule violations
2 parents e472f0b + 0f54c26 commit 5e35f3f

7 files changed

Lines changed: 54 additions & 33 deletions

File tree

frontend/src/App.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ import { useResolvedTheme } from '@/hooks/useResolvedTheme';
99
import { useCurrentUserQuery } from '@/hooks/queries/useAuthQueries';
1010
import { useInfiniteChatsQuery } from '@/hooks/queries/useChatQueries';
1111
import { LoadingScreen } from '@/components/ui/LoadingScreen';
12-
import { useGlobalStream, useStreamRestoration } from '@/hooks/useChatStreaming';
12+
import { useGlobalStream } from '@/hooks/useGlobalStream';
13+
import { useStreamRestoration } from '@/hooks/useStreamRestoration';
1314
import { authService } from '@/services/authService';
1415
import { toasterConfig } from '@/config/toaster';
1516
import { AuthRoute } from '@/components/routes/AuthRoute';

frontend/src/components/chat/sub-threads/CreateSubThreadDialog.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useState, useEffect, useCallback, useRef } from 'react';
1+
import { useState, useCallback, useRef } from 'react';
22
import { useNavigate } from 'react-router-dom';
33
import { GitBranch, Brain, Shield } from 'lucide-react';
44
import toast from 'react-hot-toast';
@@ -90,11 +90,14 @@ export function CreateSubThreadDialog({ parentChat, onClose }: CreateSubThreadDi
9090
agentKind,
9191
});
9292

93-
useEffect(() => {
93+
// Select first model when models load — ref-based check avoids extra render cycle
94+
const prevModelsRef = useRef(models);
95+
if (prevModelsRef.current !== models) {
96+
prevModelsRef.current = models;
9497
if (!selectedModelId && models.length > 0) {
9598
setSelectedModelId(models[0].model_id);
9699
}
97-
}, [models, selectedModelId]);
100+
}
98101

99102
const createSubThread = useCreateSubThreadMutation(parentChat.id);
100103

frontend/src/components/chat/workspace-selector/WorkspaceSelector.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,8 @@ export function WorkspaceSelector({
370370
const [repoSearchQuery, setRepoSearchQuery] = useState('');
371371
const [debouncedRepoQuery, setDebouncedRepoQuery] = useState('');
372372
const [showUrlInput, setShowUrlInput] = useState(false);
373+
// Form state initialization from server settings — useEffect is correct here
374+
// because sandboxProvider is user-editable form state that diverges from the source
373375
useEffect(() => {
374376
if (defaultProvider) {
375377
setSandboxProvider(defaultProvider);

frontend/src/components/editor/editor-view/Content.tsx

Lines changed: 36 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
import { memo } from 'react';
2-
import Editor from '@monaco-editor/react';
1+
import { memo, lazy, Suspense } from 'react';
32
import type * as monaco from 'monaco-editor';
43
import { MONACO_FONT_FAMILY } from '@/config/constants';
54

5+
const Editor = lazy(() => import('@monaco-editor/react'));
6+
67
const EDITOR_OPTIONS = {
78
minimap: { enabled: false },
89
scrollBeyondLastLine: false,
@@ -59,29 +60,41 @@ export const Content = memo(function Content({
5960
onMount,
6061
theme,
6162
}: ContentProps) {
63+
const loadingFallback = (
64+
<div
65+
className={`flex h-full items-center justify-center text-xs text-text-quaternary ${theme === 'custom-light' ? 'bg-surface-secondary' : 'bg-surface-dark-secondary'}`}
66+
>
67+
<div className="animate-pulse">Loading editor...</div>
68+
</div>
69+
);
70+
6271
return (
6372
<div className="h-full">
64-
<Editor
65-
height="100%"
66-
language={language}
67-
path={`file://${language}`}
68-
value={content}
69-
onChange={onChange}
70-
theme={theme}
71-
options={{
72-
...EDITOR_OPTIONS,
73-
readOnly: isReadOnly,
74-
}}
75-
onMount={onMount}
76-
loading={
77-
<div
78-
className={`flex h-full items-center justify-center text-xs text-text-quaternary ${theme === 'custom-light' ? 'bg-surface-secondary' : 'bg-surface-dark-secondary'}`}
79-
>
80-
<div className="animate-pulse">Loading editor...</div>
81-
</div>
82-
}
83-
className={theme === 'custom-light' ? 'bg-surface-secondary' : 'bg-surface-dark-secondary'}
84-
/>
73+
<Suspense fallback={loadingFallback}>
74+
<Editor
75+
height="100%"
76+
language={language}
77+
path={`file://${language}`}
78+
value={content}
79+
onChange={onChange}
80+
theme={theme}
81+
options={{
82+
...EDITOR_OPTIONS,
83+
readOnly: isReadOnly,
84+
}}
85+
onMount={onMount}
86+
loading={
87+
<div
88+
className={`flex h-full items-center justify-center text-xs text-text-quaternary ${theme === 'custom-light' ? 'bg-surface-secondary' : 'bg-surface-dark-secondary'}`}
89+
>
90+
<div className="animate-pulse">Loading editor...</div>
91+
</div>
92+
}
93+
className={
94+
theme === 'custom-light' ? 'bg-surface-secondary' : 'bg-surface-dark-secondary'
95+
}
96+
/>
97+
</Suspense>
8598
</div>
8699
);
87100
});

frontend/src/components/layout/TitleBar.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ export function TrafficLights() {
3838
type="button"
3939
variant="unstyled"
4040
onClick={handleClose}
41-
className="group flex h-3 w-3 items-center justify-center rounded-full bg-[#ff5f57] transition-opacity hover:opacity-90"
41+
className="group flex h-3 w-3 items-center justify-center rounded-full bg-traffic-close transition-opacity hover:opacity-90"
4242
aria-label="Close window"
4343
>
4444
{isHovered && (
@@ -56,7 +56,7 @@ export function TrafficLights() {
5656
type="button"
5757
variant="unstyled"
5858
onClick={handleMinimize}
59-
className="group flex h-3 w-3 items-center justify-center rounded-full bg-[#febc2e] transition-opacity hover:opacity-90"
59+
className="group flex h-3 w-3 items-center justify-center rounded-full bg-traffic-minimize transition-opacity hover:opacity-90"
6060
aria-label="Minimize window"
6161
>
6262
{isHovered && (
@@ -69,7 +69,7 @@ export function TrafficLights() {
6969
type="button"
7070
variant="unstyled"
7171
onClick={handleMaximize}
72-
className="group flex h-3 w-3 items-center justify-center rounded-full bg-[#28c840] transition-opacity hover:opacity-90"
72+
className="group flex h-3 w-3 items-center justify-center rounded-full bg-traffic-maximize transition-opacity hover:opacity-90"
7373
aria-label="Maximize window"
7474
>
7575
{isHovered && (

frontend/src/hooks/useChatStreaming.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,6 @@ import { useClipboard } from '@/hooks/useClipboard';
1515
import { useStreamCallbacks } from '@/hooks/useStreamCallbacks';
1616
import { useStreamReconnect } from '@/hooks/useStreamReconnect';
1717

18-
export { useStreamRestoration } from './useStreamRestoration';
19-
export { useGlobalStream } from './useGlobalStream';
20-
2118
interface UseChatStreamingParams {
2219
chatId: string | undefined;
2320
currentChat: Chat | undefined;

frontend/tailwind.config.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,11 @@ export default {
107107
},
108108
},
109109

110+
// macOS traffic light colors
111+
'traffic-close': '#ff5f57',
112+
'traffic-minimize': '#febc2e',
113+
'traffic-maximize': '#28c840',
114+
110115
// Text colors
111116
text: {
112117
primary: '#0f172a',

0 commit comments

Comments
 (0)