Skip to content

Commit 40011e8

Browse files
committed
Update docs
1 parent 1ff28c7 commit 40011e8

9 files changed

Lines changed: 2080 additions & 1385 deletions

File tree

components/ai-elements/attachments.tsx

Lines changed: 421 additions & 0 deletions
Large diffs are not rendered by default.

components/ai-elements/code-block.tsx

Lines changed: 441 additions & 90 deletions
Large diffs are not rendered by default.

components/ai-elements/conversation.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export type ConversationProps = ComponentProps<typeof StickToBottom>;
1111

1212
export const Conversation = ({ className, ...props }: ConversationProps) => (
1313
<StickToBottom
14-
className={cn("relative flex-1 overflow-y-auto", className)}
14+
className={cn("relative flex-1 overflow-y-hidden", className)}
1515
initial="smooth"
1616
resize="smooth"
1717
role="log"
@@ -84,7 +84,7 @@ export const ConversationScrollButton = ({
8484
!isAtBottom && (
8585
<Button
8686
className={cn(
87-
"absolute bottom-4 left-[50%] translate-x-[-50%] rounded-full",
87+
"absolute bottom-4 left-[50%] translate-x-[-50%] rounded-full dark:bg-background dark:hover:bg-muted",
8888
className
8989
)}
9090
onClick={handleScrollToBottom}

components/ai-elements/message.tsx

Lines changed: 11 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,12 @@ import {
1212
TooltipTrigger,
1313
} from "@/components/ui/tooltip";
1414
import { cn } from "@/lib/utils";
15-
import type { FileUIPart, UIMessage } from "ai";
16-
import {
17-
ChevronLeftIcon,
18-
ChevronRightIcon,
19-
PaperclipIcon,
20-
XIcon,
21-
} from "lucide-react";
15+
import { cjk } from "@streamdown/cjk";
16+
import { code } from "@streamdown/code";
17+
import { math } from "@streamdown/math";
18+
import { mermaid } from "@streamdown/mermaid";
19+
import type { UIMessage } from "ai";
20+
import { ChevronLeftIcon, ChevronRightIcon } from "lucide-react";
2221
import type { ComponentProps, HTMLAttributes, ReactElement } from "react";
2322
import { createContext, memo, useContext, useEffect, useState } from "react";
2423
import { Streamdown } from "streamdown";
@@ -30,7 +29,7 @@ export type MessageProps = HTMLAttributes<HTMLDivElement> & {
3029
export const Message = ({ className, from, ...props }: MessageProps) => (
3130
<div
3231
className={cn(
33-
"group flex flex-col w-full max-w-[80%] gap-2",
32+
"group flex w-full max-w-[95%] flex-col gap-2",
3433
from === "user" ? "is-user ml-auto justify-end" : "is-assistant",
3534
className
3635
)}
@@ -47,7 +46,7 @@ export const MessageContent = ({
4746
}: MessageContentProps) => (
4847
<div
4948
className={cn(
50-
"is-user:dark flex w-fit flex-col gap-2 overflow-hidden text-sm",
49+
"is-user:dark flex w-fit min-w-0 max-w-full flex-col gap-2 overflow-hidden text-sm",
5150
"group-[.is-user]:ml-auto group-[.is-user]:rounded-lg group-[.is-user]:bg-secondary group-[.is-user]:px-4 group-[.is-user]:py-3 group-[.is-user]:text-foreground",
5251
"group-[.is-assistant]:text-foreground",
5352
className
@@ -106,14 +105,14 @@ export const MessageAction = ({
106105
return button;
107106
};
108107

109-
type MessageBranchContextType = {
108+
interface MessageBranchContextType {
110109
currentBranch: number;
111110
totalBranches: number;
112111
goToPrevious: () => void;
113112
goToNext: () => void;
114113
branches: ReactElement[];
115114
setBranches: (branches: ReactElement[]) => void;
116-
};
115+
}
117116

118117
const MessageBranchContext = createContext<MessageBranchContextType | null>(
119118
null
@@ -263,7 +262,6 @@ export type MessageBranchNextProps = ComponentProps<typeof Button>;
263262

264263
export const MessageBranchNext = ({
265264
children,
266-
className,
267265
...props
268266
}: MessageBranchNextProps) => {
269267
const { goToNext, totalBranches } = useMessageBranch();
@@ -313,6 +311,7 @@ export const MessageResponse = memo(
313311
"size-full [&>*:first-child]:mt-0 [&>*:last-child]:mb-0",
314312
className
315313
)}
314+
plugins={{ code, mermaid, math, cjk }}
316315
{...props}
317316
/>
318317
),
@@ -321,114 +320,6 @@ export const MessageResponse = memo(
321320

322321
MessageResponse.displayName = "MessageResponse";
323322

324-
export type MessageAttachmentProps = HTMLAttributes<HTMLDivElement> & {
325-
data: FileUIPart;
326-
className?: string;
327-
onRemove?: () => void;
328-
};
329-
330-
export function MessageAttachment({
331-
data,
332-
className,
333-
onRemove,
334-
...props
335-
}: MessageAttachmentProps) {
336-
const filename = data.filename || "";
337-
const mediaType =
338-
data.mediaType?.startsWith("image/") && data.url ? "image" : "file";
339-
const isImage = mediaType === "image";
340-
const attachmentLabel = filename || (isImage ? "Image" : "Attachment");
341-
342-
return (
343-
<div
344-
className={cn(
345-
"group relative size-24 overflow-hidden rounded-lg",
346-
className
347-
)}
348-
{...props}
349-
>
350-
{isImage ? (
351-
<>
352-
<img
353-
alt={filename || "attachment"}
354-
className="size-full object-cover"
355-
height={100}
356-
src={data.url}
357-
width={100}
358-
/>
359-
{onRemove && (
360-
<Button
361-
aria-label="Remove attachment"
362-
className="absolute top-2 right-2 size-6 rounded-full bg-background/80 p-0 opacity-0 backdrop-blur-sm transition-opacity hover:bg-background group-hover:opacity-100 [&>svg]:size-3"
363-
onClick={(e) => {
364-
e.stopPropagation();
365-
onRemove();
366-
}}
367-
type="button"
368-
variant="ghost"
369-
>
370-
<XIcon />
371-
<span className="sr-only">Remove</span>
372-
</Button>
373-
)}
374-
</>
375-
) : (
376-
<>
377-
<Tooltip>
378-
<TooltipTrigger asChild>
379-
<div className="flex size-full shrink-0 items-center justify-center rounded-lg bg-muted text-muted-foreground">
380-
<PaperclipIcon className="size-4" />
381-
</div>
382-
</TooltipTrigger>
383-
<TooltipContent>
384-
<p>{attachmentLabel}</p>
385-
</TooltipContent>
386-
</Tooltip>
387-
{onRemove && (
388-
<Button
389-
aria-label="Remove attachment"
390-
className="size-6 shrink-0 rounded-full p-0 opacity-0 transition-opacity hover:bg-accent group-hover:opacity-100 [&>svg]:size-3"
391-
onClick={(e) => {
392-
e.stopPropagation();
393-
onRemove();
394-
}}
395-
type="button"
396-
variant="ghost"
397-
>
398-
<XIcon />
399-
<span className="sr-only">Remove</span>
400-
</Button>
401-
)}
402-
</>
403-
)}
404-
</div>
405-
);
406-
}
407-
408-
export type MessageAttachmentsProps = ComponentProps<"div">;
409-
410-
export function MessageAttachments({
411-
children,
412-
className,
413-
...props
414-
}: MessageAttachmentsProps) {
415-
if (!children) {
416-
return null;
417-
}
418-
419-
return (
420-
<div
421-
className={cn(
422-
"ml-auto flex w-fit flex-wrap items-start gap-2",
423-
className
424-
)}
425-
{...props}
426-
>
427-
{children}
428-
</div>
429-
);
430-
}
431-
432323
export type MessageToolbarProps = ComponentProps<"div">;
433324

434325
export const MessageToolbar = ({

0 commit comments

Comments
 (0)