diff --git a/.sandcastle/CODING_STANDARDS.md b/.sandcastle/CODING_STANDARDS.md index d0d8345..04026cf 100644 --- a/.sandcastle/CODING_STANDARDS.md +++ b/.sandcastle/CODING_STANDARDS.md @@ -13,6 +13,7 @@ - No `any` — ever (`noExplicitAny` is an error) - kebab-case filenames for components; camelCase for utilities - 2-space indent, 100-char line width, single quotes, trailing commas (Biome enforced) +- **Never** suppress lint rules with `biome-ignore` (or `@ts-ignore`/`eslint-disable`). If a rule fires, fix the underlying code — restructure the effect, derive a value, lift state, or pick a different approach. A suppression silences the linter but leaves the smell; future readers can't tell whether it's still warranted. The same applies to `as any` and other type escape hatches. ## Architecture diff --git a/apps/desktop/src/renderer/src/components/chat/ChatPanel.tsx b/apps/desktop/src/renderer/src/components/chat/ChatPanel.tsx index 05708d3..c36ab7d 100644 --- a/apps/desktop/src/renderer/src/components/chat/ChatPanel.tsx +++ b/apps/desktop/src/renderer/src/components/chat/ChatPanel.tsx @@ -73,7 +73,6 @@ export function ChatPanel({ chat }: ChatPanelProps): React.JSX.Element { const history = useChatThreads(); const [input, setInput] = useState(''); - const textareaRef = useRef(null); const messagesEndRef = useRef(null); // Track previous filePath so file-change and initial-mount paths @@ -161,19 +160,11 @@ export function ChatPanel({ chat }: ChatPanelProps): React.JSX.Element { }); }, [history.activeThreadId, history.updateThreadSessionId]); - // biome-ignore lint/correctness/useExhaustiveDependencies: scroll whenever the message list changes; biome can't see `messages` is the intended trigger + const messageCount = messages.length; useEffect(() => { + if (messageCount === 0) return; messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' }); - }, [messages]); - - // Auto-grow the textarea up to a cap so prompts with a few lines - // don't force the user to scroll a single-line input. - useEffect(() => { - const el = textareaRef.current; - if (!el) return; - el.style.height = 'auto'; - el.style.height = `${Math.min(el.scrollHeight, 160)}px`; - }, []); + }, [messageCount]); const fileThreads = useMemo( () => history.threadsForFile(filePath), @@ -367,7 +358,6 @@ export function ChatPanel({ chat }: ChatPanelProps): React.JSX.Element { )} >