This commit is contained in:
Zacharias-Brohn
2026-01-14 22:08:19 +01:00
parent 95d07eb00b
commit 7663a917da
+64 -68
View File
@@ -22,6 +22,7 @@ import {
Container,
Group,
Menu,
NavLink,
Paper,
ScrollArea,
Select,
@@ -31,7 +32,6 @@ import {
TextInputProps,
Title,
Tooltip,
UnstyledButton,
useMantineTheme,
} from '@mantine/core';
import { useDisclosure } from '@mantine/hooks';
@@ -619,29 +619,23 @@ export default function ChatLayout() {
</Group>
<ScrollArea style={{ flex: 1, margin: '0 -10px' }} p="xs">
<Stack gap="xs">
<Stack gap={2}>
{chats.length > 0 ? (
chats.map((chat) => (
chats.map((chat) =>
editingChatId === chat.id ? (
// Inline editing mode
<Group
key={chat.id}
gap={0}
wrap="nowrap"
style={{
borderRadius: 'var(--mantine-radius-md)',
backgroundColor:
activeChatId === chat.id
? 'var(--mantine-color-default-hover)'
: 'transparent',
transition: 'background-color 0.2s',
}}
gap="xs"
px="sm"
py={6}
style={{ minWidth: 0 }}
>
{editingChatId === chat.id ? (
// Inline editing mode
<Group wrap="nowrap" gap="xs" p="sm" style={{ flex: 1, minWidth: 0 }}>
{chat.pinned ? (
<IconPin size={18} color="gray" style={{ minWidth: 18 }} />
<IconPin size={16} stroke={1.5} style={{ minWidth: 16 }} />
) : (
<IconMessage size={18} color="gray" style={{ minWidth: 18 }} />
<IconMessage size={16} stroke={1.5} style={{ minWidth: 16 }} />
)}
<TextInput
ref={editInputRef}
@@ -650,48 +644,49 @@ export default function ChatLayout() {
onBlur={saveRenamedChat}
onKeyDown={handleRenameKeyDown}
size="xs"
variant="unstyled"
styles={{
input: {
padding: 0,
height: 'auto',
minHeight: 'unset',
fontSize: 'var(--mantine-font-size-sm)',
},
}}
style={{ flex: 1 }}
/>
</Group>
) : (
// Normal display mode
<UnstyledButton
onClick={() => handleSelectChat(chat)}
p="sm"
style={{ flex: 1, minWidth: 0 }}
>
<Group wrap="nowrap" gap="xs">
{chat.pinned ? (
<IconPin size={18} color="gray" style={{ minWidth: 18 }} />
// Normal display mode with NavLink
<Group key={chat.id} gap={0} wrap="nowrap">
<NavLink
component="button"
active={activeChatId === chat.id}
color={primaryColor}
variant="subtle"
label={chat.title}
leftSection={
chat.pinned ? (
<IconPin size={16} stroke={1.5} />
) : (
<IconMessage size={18} color="gray" style={{ minWidth: 18 }} />
)}
<Text size="sm" truncate style={{ flex: 1 }}>
{chat.title}
</Text>
</Group>
</UnstyledButton>
)}
<IconMessage size={16} stroke={1.5} />
)
}
onClick={() => handleSelectChat(chat)}
noWrap
styles={{
root: {
flex: 1,
minWidth: 0,
borderRadius: 'var(--mantine-radius-sm)',
padding: '6px 10px',
},
label: {
overflow: 'hidden',
textOverflow: 'ellipsis',
},
}}
/>
<Menu position="bottom-end" withArrow>
<Menu.Target>
<ActionIcon
variant="subtle"
color="gray"
size="sm"
mr="xs"
onClick={(e) => e.stopPropagation()}
>
<IconDotsVertical size={16} />
<IconDotsVertical size={14} />
</ActionIcon>
</Menu.Target>
<Menu.Dropdown>
@@ -718,7 +713,8 @@ export default function ChatLayout() {
</Menu.Dropdown>
</Menu>
</Group>
))
)
)
) : (
<Text size="sm" c="dimmed" ta="center" mt="xl">
{isLoadingChats ? 'Loading...' : 'No saved chats'}
@@ -744,49 +740,49 @@ export default function ChatLayout() {
onScrollPositionChange={handleScroll}
classNames={{ viewport: classes.chatScrollViewport }}
>
<Stack gap="xl" px="md" py="lg">
<Stack gap="md" px="md" py="lg">
{messages.map((message) => (
<Group
key={message.id}
justify={message.role === 'user' ? 'flex-end' : 'flex-start'}
align="flex-start"
wrap="nowrap"
gap="sm"
>
{message.role === 'assistant' && (
<Avatar radius="xl" color={primaryColor} variant="light">
<IconRobot size={20} />
<Avatar radius="xl" color={primaryColor} variant="light" size="sm">
<IconRobot size={16} />
</Avatar>
)}
<Paper
p="md"
radius="lg"
bg={
message.role === 'user'
? 'var(--mantine-color-default-hover)'
: 'transparent'
}
style={{
maxWidth: '80%',
borderTopLeftRadius: message.role === 'assistant' ? 0 : undefined,
borderTopRightRadius: message.role === 'user' ? 0 : undefined,
}}
>
{message.role === 'assistant' ? (
// Assistant message - no bubble, just text aligned with avatar
<div style={{ maxWidth: '85%', paddingTop: 2 }}>
<MarkdownMessage
content={message.content}
isStreaming={message.id === streamingMessageId}
/>
</div>
) : (
<Text size="sm" style={{ lineHeight: 1.6 }}>
// User message - colored bubble
<Paper
py="xs"
px="md"
radius="lg"
bg={`var(--mantine-color-${primaryColor}-light)`}
style={{
maxWidth: '75%',
}}
>
<Text size="sm" style={{ lineHeight: 1.5 }}>
{message.content}
</Text>
)}
</Paper>
)}
{message.role === 'user' && (
<Avatar radius="xl" color="gray" variant="light">
<IconUser size={20} />
<Avatar radius="xl" color={primaryColor} variant="light" size="sm">
<IconUser size={16} />
</Avatar>
)}
</Group>