feat: expand assistant providers and polish experience
This commit is contained in:
1 parent
5f3d676af0
commit
c0445cdca2
12 files changed
+438
-70
No files matched your search
@@ -79,6 +79,15 @@
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.messageError {
|
||||
margin-top: 0.5rem;
|
||||
padding: 0.65rem 0.75rem;
|
||||
border-radius: var(--mantine-radius-md);
|
||||
color: var(--mantine-color-red-text);
|
||||
background: var(--mantine-color-red-light);
|
||||
font-size: var(--mantine-font-size-sm);
|
||||
}
|
||||
|
||||
.tool {
|
||||
margin-block: 0.5rem;
|
||||
padding: 0.7rem 0.8rem;
|
||||
@@ -105,10 +114,9 @@
|
||||
align-items: flex-end;
|
||||
gap: 0.5rem;
|
||||
padding: 0.45rem;
|
||||
border: 1px solid var(--mantine-color-default-border);
|
||||
border-radius: 1rem;
|
||||
background: var(--mantine-color-body);
|
||||
box-shadow: var(--mantine-shadow-lg);
|
||||
background: var(--mantine-color-default);
|
||||
box-shadow: var(--mantine-shadow-sm);
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
@@ -130,9 +138,26 @@
|
||||
min-height: 60vh;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 3rem 1rem 8rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.suggestions {
|
||||
display: grid;
|
||||
width: 100%;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 0.65rem;
|
||||
}
|
||||
|
||||
.suggestion {
|
||||
height: auto;
|
||||
min-height: 3.25rem;
|
||||
justify-content: flex-start;
|
||||
padding: 0.7rem 0.9rem;
|
||||
text-align: start;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.mobileHistoryButton,
|
||||
.historyClose {
|
||||
display: none;
|
||||
@@ -173,4 +198,18 @@
|
||||
.historyClose {
|
||||
display: inline-flex;
|
||||
}
|
||||
|
||||
.suggestions {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.history {
|
||||
transition: none;
|
||||
}
|
||||
|
||||
.viewport {
|
||||
scroll-behavior: auto;
|
||||
}
|
||||
}
|
||||
@@ -15,10 +15,13 @@ import {
|
||||
import { ActionIcon, Box, Button, Drawer, Group, ScrollArea, Stack, Text, ThemeIcon, Tooltip } from "@mantine/core";
|
||||
import { useMediaQuery } from "@mantine/hooks";
|
||||
import {
|
||||
IconActivityHeartbeat,
|
||||
IconApps,
|
||||
IconArchive,
|
||||
IconArrowUp,
|
||||
IconCheck,
|
||||
IconCopy,
|
||||
IconCommand,
|
||||
IconMenu2,
|
||||
IconHistory,
|
||||
IconPlayerStop,
|
||||
@@ -26,6 +29,7 @@ import {
|
||||
IconRefresh,
|
||||
IconRestore,
|
||||
IconRobot,
|
||||
IconSearch,
|
||||
IconTrash,
|
||||
IconX,
|
||||
} from "@tabler/icons-react";
|
||||
@@ -143,6 +147,15 @@ const UserMessage = () => (
|
||||
</MessagePrimitive.Root>
|
||||
);
|
||||
|
||||
const RuntimeError = () => {
|
||||
const t = useScopedI18n("common.assistant");
|
||||
return (
|
||||
<MessagePrimitive.Error>
|
||||
<Box className={classes.messageError}>{t("responseError")}</Box>
|
||||
</MessagePrimitive.Error>
|
||||
);
|
||||
};
|
||||
|
||||
const AssistantMessage = () => (
|
||||
<MessagePrimitive.Root className={`${classes.message} ${classes.assistantMessage}`}>
|
||||
<MessagePrimitive.Parts
|
||||
@@ -151,6 +164,7 @@ const AssistantMessage = () => (
|
||||
tools: { Fallback: ToolPart },
|
||||
}}
|
||||
/>
|
||||
<RuntimeError />
|
||||
<MessageActions />
|
||||
</MessagePrimitive.Root>
|
||||
);
|
||||
@@ -236,14 +250,14 @@ const ThreadHistory = ({ opened, onClose }: { opened: boolean; onClose: () => vo
|
||||
</Group>
|
||||
<Group gap="xs" px="xs" mt="xs">
|
||||
<IconHistory size={14} />
|
||||
<Text size="xs" fw={700} c="dimmed" tt="uppercase">
|
||||
<Text size="sm" fw={600} c="dimmed">
|
||||
{t("conversations")}
|
||||
</Text>
|
||||
</Group>
|
||||
<ScrollArea flex={1} type="auto">
|
||||
<Stack gap={3}>
|
||||
<ThreadListPrimitive.Items components={{ ThreadListItem }} />
|
||||
<Text size="xs" fw={700} c="dimmed" tt="uppercase" px="xs" mt="sm">
|
||||
<Text size="sm" fw={600} c="dimmed" px="xs" mt="sm">
|
||||
{t("archived")}
|
||||
</Text>
|
||||
<ThreadListPrimitive.Items archived components={{ ThreadListItem: ArchivedThreadListItem }} />
|
||||
@@ -258,16 +272,44 @@ const EmptyThread = () => {
|
||||
return (
|
||||
<ThreadPrimitive.Empty>
|
||||
<Box className={classes.empty}>
|
||||
<Stack align="center" gap="sm" maw={340}>
|
||||
<ThemeIcon size={52} radius="xl" variant="light" color="red">
|
||||
<IconRobot size={27} />
|
||||
</ThemeIcon>
|
||||
<Text size="xl" fw={700}>
|
||||
{t("emptyTitle")}
|
||||
</Text>
|
||||
<Text size="sm" c="dimmed">
|
||||
{t("emptyDescription")}
|
||||
</Text>
|
||||
<Stack align="center" gap="lg" maw={560} w="100%">
|
||||
<Stack align="center" gap="xs" maw={430}>
|
||||
<ThemeIcon size={52} radius="xl" variant="light" color="red">
|
||||
<IconRobot size={27} />
|
||||
</ThemeIcon>
|
||||
<Text size="xl" fw={700}>
|
||||
{t("emptyTitle")}
|
||||
</Text>
|
||||
<Text size="sm" c="dimmed">
|
||||
{t("emptyDescription")}
|
||||
</Text>
|
||||
</Stack>
|
||||
<Box className={classes.suggestions}>
|
||||
<ThreadPrimitive.Suggestion prompt={t("suggestions.health.prompt")} send asChild>
|
||||
<Button
|
||||
variant="default"
|
||||
className={classes.suggestion}
|
||||
leftSection={<IconActivityHeartbeat size={18} />}
|
||||
>
|
||||
{t("suggestions.health.label")}
|
||||
</Button>
|
||||
</ThreadPrimitive.Suggestion>
|
||||
<ThreadPrimitive.Suggestion prompt={t("suggestions.explore.prompt")} send asChild>
|
||||
<Button variant="default" className={classes.suggestion} leftSection={<IconApps size={18} />}>
|
||||
{t("suggestions.explore.label")}
|
||||
</Button>
|
||||
</ThreadPrimitive.Suggestion>
|
||||
<ThreadPrimitive.Suggestion prompt={t("suggestions.media.prompt")} send asChild>
|
||||
<Button variant="default" className={classes.suggestion} leftSection={<IconSearch size={18} />}>
|
||||
{t("suggestions.media.label")}
|
||||
</Button>
|
||||
</ThreadPrimitive.Suggestion>
|
||||
<ThreadPrimitive.Suggestion prompt={t("suggestions.command.prompt")} send asChild>
|
||||
<Button variant="default" className={classes.suggestion} leftSection={<IconCommand size={18} />}>
|
||||
{t("suggestions.command.label")}
|
||||
</Button>
|
||||
</ThreadPrimitive.Suggestion>
|
||||
</Box>
|
||||
</Stack>
|
||||
</Box>
|
||||
</ThreadPrimitive.Empty>
|
||||
|
||||
Reference in new issue
Block a user