fix(ai-chat): improve error banner layout

The AI chat error Alert stranded the warning icon in the top-left while
the detail text hung indented under the heading, wrapping to 3 narrow
lines with empty space below. Switch to a "full-width detail" layout
(icon + bold heading on the first row, detail spanning full width below)
and extract the markup, previously duplicated in ChatThread and
MessageItem, into a single shared ChatErrorAlert component.

- add apps/client/src/features/ai-chat/components/chat-error-alert.tsx
- use it for the live stream error in chat-thread.tsx (mb="xs")
- use it for the persisted history error in message-item.tsx (mt={4})
- heading/icon use the adaptive --mantine-color-red-light-color so the
  banner stays correct in dark mode

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
claude_code
2026-06-22 19:54:17 +03:00
parent f6a4df1b08
commit 11d5a75c79
3 changed files with 51 additions and 20 deletions

View File

@@ -1,13 +1,14 @@
import { useCallback, useMemo, useRef, useState } from "react";
import { generateId } from "ai";
import { ActionIcon, Alert, Box, Group, Stack, Text } from "@mantine/core";
import { IconAlertTriangle, IconClockHour4, IconX } from "@tabler/icons-react";
import { ActionIcon, Box, Group, Stack, Text } from "@mantine/core";
import { IconClockHour4, IconX } from "@tabler/icons-react";
import { useTranslation } from "react-i18next";
import { useChat, type UIMessage } from "@ai-sdk/react";
import { DefaultChatTransport } from "ai";
import MessageList from "@/features/ai-chat/components/message-list.tsx";
import ChatInput from "@/features/ai-chat/components/chat-input.tsx";
import RoleCards from "@/features/ai-chat/components/role-cards.tsx";
import ChatErrorAlert from "@/features/ai-chat/components/chat-error-alert.tsx";
import {
IAiChatMessageRow,
IAiRole,
@@ -277,15 +278,11 @@ export default function ChatThread({
/>
{errorView && (
<Alert
variant="light"
color="red"
icon={<IconAlertTriangle size={16} />}
mb="xs"
<ChatErrorAlert
title={errorView.title}
>
{errorView.detail}
</Alert>
detail={errorView.detail}
mb="xs"
/>
)}
<Stack gap={0} className={classes.inputWrapper}>