@assistant-ui/mcp-docs-server 0.1.15 → 0.1.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/.docs/organized/code-examples/store-example.md +112 -38
  2. package/.docs/organized/code-examples/with-ag-ui.md +248 -184
  3. package/.docs/organized/code-examples/with-ai-sdk-v5.md +247 -196
  4. package/.docs/organized/code-examples/with-assistant-transport.md +192 -240
  5. package/.docs/organized/code-examples/with-cloud.md +275 -224
  6. package/.docs/organized/code-examples/with-custom-thread-list.md +1855 -0
  7. package/.docs/organized/code-examples/with-external-store.md +244 -178
  8. package/.docs/organized/code-examples/with-ffmpeg.md +253 -187
  9. package/.docs/organized/code-examples/with-langgraph.md +291 -240
  10. package/.docs/organized/code-examples/with-parent-id-grouping.md +241 -261
  11. package/.docs/organized/code-examples/with-react-hook-form.md +260 -194
  12. package/.docs/organized/code-examples/with-tanstack.md +1574 -0
  13. package/.docs/raw/blog/2024-07-29-hello/index.mdx +2 -2
  14. package/.docs/raw/docs/api-reference/overview.mdx +6 -6
  15. package/.docs/raw/docs/api-reference/primitives/ActionBar.mdx +85 -4
  16. package/.docs/raw/docs/api-reference/primitives/AssistantIf.mdx +200 -0
  17. package/.docs/raw/docs/api-reference/primitives/Composer.mdx +0 -20
  18. package/.docs/raw/docs/api-reference/primitives/Message.mdx +0 -45
  19. package/.docs/raw/docs/api-reference/primitives/Thread.mdx +0 -50
  20. package/.docs/raw/docs/cloud/persistence/ai-sdk.mdx +2 -3
  21. package/.docs/raw/docs/cloud/persistence/langgraph.mdx +2 -3
  22. package/.docs/raw/docs/devtools.mdx +2 -3
  23. package/.docs/raw/docs/getting-started.mdx +36 -1102
  24. package/.docs/raw/docs/guides/Attachments.mdx +3 -25
  25. package/.docs/raw/docs/guides/Branching.mdx +1 -1
  26. package/.docs/raw/docs/guides/Speech.mdx +1 -1
  27. package/.docs/raw/docs/guides/ToolUI.mdx +1 -1
  28. package/.docs/raw/docs/legacy/styled/AssistantModal.mdx +2 -3
  29. package/.docs/raw/docs/legacy/styled/Decomposition.mdx +6 -5
  30. package/.docs/raw/docs/legacy/styled/Markdown.mdx +2 -3
  31. package/.docs/raw/docs/legacy/styled/Thread.mdx +2 -3
  32. package/.docs/raw/docs/react-compatibility.mdx +2 -5
  33. package/.docs/raw/docs/runtimes/ai-sdk/use-chat.mdx +3 -4
  34. package/.docs/raw/docs/runtimes/ai-sdk/v4-legacy.mdx +3 -6
  35. package/.docs/raw/docs/runtimes/custom/external-store.mdx +2 -3
  36. package/.docs/raw/docs/runtimes/custom/local.mdx +11 -41
  37. package/.docs/raw/docs/runtimes/data-stream.mdx +15 -11
  38. package/.docs/raw/docs/runtimes/langgraph/index.mdx +3 -3
  39. package/.docs/raw/docs/runtimes/langgraph/tutorial/part-2.mdx +1 -1
  40. package/.docs/raw/docs/runtimes/langgraph/tutorial/part-3.mdx +2 -3
  41. package/.docs/raw/docs/runtimes/langserve.mdx +2 -3
  42. package/.docs/raw/docs/runtimes/mastra/full-stack-integration.mdx +2 -3
  43. package/.docs/raw/docs/runtimes/mastra/separate-server-integration.mdx +2 -3
  44. package/.docs/raw/docs/ui/AssistantModal.mdx +3 -25
  45. package/.docs/raw/docs/ui/AssistantSidebar.mdx +2 -24
  46. package/.docs/raw/docs/ui/Attachment.mdx +3 -25
  47. package/.docs/raw/docs/ui/Markdown.mdx +2 -24
  48. package/.docs/raw/docs/ui/Mermaid.mdx +2 -24
  49. package/.docs/raw/docs/ui/Reasoning.mdx +2 -24
  50. package/.docs/raw/docs/ui/Scrollbar.mdx +4 -6
  51. package/.docs/raw/docs/ui/SyntaxHighlighting.mdx +3 -47
  52. package/.docs/raw/docs/ui/Thread.mdx +38 -53
  53. package/.docs/raw/docs/ui/ThreadList.mdx +4 -47
  54. package/.docs/raw/docs/ui/ToolFallback.mdx +2 -24
  55. package/package.json +5 -6
@@ -238,7 +238,7 @@ import { ThreadList } from "@/components/assistant-ui/thread-list";
238
238
 
239
239
  export default function Home() {
240
240
  return (
241
- <main className="grid h-dvh grid-cols-[200px,1fr] gap-4 p-4">
241
+ <main className="grid h-dvh grid-cols-[200px_1fr] gap-4 p-4">
242
242
  <ThreadList />
243
243
  <Thread />
244
244
  </main>
@@ -371,16 +371,16 @@ const AttachmentPreviewDialog: FC<PropsWithChildren> = ({ children }) => {
371
371
  return (
372
372
  <Dialog>
373
373
  <DialogTrigger
374
- className="aui-attachment-preview-trigger hover:bg-accent/50 cursor-pointer transition-colors"
374
+ className="aui-attachment-preview-trigger cursor-pointer transition-colors hover:bg-accent/50"
375
375
  asChild
376
376
  >
377
377
  {children}
378
378
  </DialogTrigger>
379
- <DialogContent className="aui-attachment-preview-dialog-content [&_svg]:text-background [&>button]:bg-foreground/60 [&>button]:hover:[&_svg]:text-destructive p-2 sm:max-w-3xl [&>button]:rounded-full [&>button]:p-1 [&>button]:opacity-100 [&>button]:!ring-0">
379
+ <DialogContent className="aui-attachment-preview-dialog-content p-2 sm:max-w-3xl [&>button]:rounded-full [&>button]:bg-foreground/60 [&>button]:p-1 [&>button]:opacity-100 [&>button]:ring-0! [&_svg]:text-background [&>button]:hover:[&_svg]:text-destructive">
380
380
  <DialogTitle className="aui-sr-only sr-only">
381
381
  Image Attachment Preview
382
382
  </DialogTitle>
383
- <div className="aui-attachment-preview bg-background relative mx-auto flex max-h-[80dvh] w-full items-center justify-center overflow-hidden">
383
+ <div className="aui-attachment-preview relative mx-auto flex max-h-[80dvh] w-full items-center justify-center overflow-hidden bg-background">
384
384
  <AttachmentPreview src={src} />
385
385
  </div>
386
386
  </DialogContent>
@@ -402,7 +402,7 @@ const AttachmentThumb: FC = () => {
402
402
  className="aui-attachment-tile-image object-cover"
403
403
  />
404
404
  <AvatarFallback delayMs={isImage ? 200 : 0}>
405
- <FileText className="aui-attachment-tile-fallback-icon text-muted-foreground size-8" />
405
+ <FileText className="aui-attachment-tile-fallback-icon size-8 text-muted-foreground" />
406
406
  </AvatarFallback>
407
407
  </Avatar>
408
408
  );
@@ -443,7 +443,7 @@ const AttachmentUI: FC = () => {
443
443
  <TooltipTrigger asChild>
444
444
  <div
445
445
  className={cn(
446
- "aui-attachment-tile bg-muted size-14 cursor-pointer overflow-hidden rounded-[14px] border transition-opacity hover:opacity-75",
446
+ "aui-attachment-tile size-14 cursor-pointer overflow-hidden rounded-[14px] border bg-muted transition-opacity hover:opacity-75",
447
447
  isComposer &&
448
448
  "aui-attachment-tile-composer border-foreground/20",
449
449
  )}
@@ -469,7 +469,7 @@ const AttachmentRemove: FC = () => {
469
469
  <AttachmentPrimitive.Remove asChild>
470
470
  <TooltipIconButton
471
471
  tooltip="Remove file"
472
- className="aui-attachment-tile-remove text-muted-foreground hover:[&_svg]:text-destructive absolute top-1.5 right-1.5 size-3.5 rounded-full bg-white opacity-100 shadow-sm hover:!bg-white [&_svg]:text-black"
472
+ className="aui-attachment-tile-remove absolute top-1.5 right-1.5 size-3.5 rounded-full bg-white text-muted-foreground opacity-100 shadow-sm hover:bg-white! [&_svg]:text-black hover:[&_svg]:text-destructive"
473
473
  side="top"
474
474
  >
475
475
  <XIcon className="aui-attachment-remove-icon size-3 dark:stroke-[2.5px]" />
@@ -504,7 +504,7 @@ export const ComposerAddAttachment: FC = () => {
504
504
  side="bottom"
505
505
  variant="ghost"
506
506
  size="icon"
507
- className="aui-composer-add-attachment hover:bg-muted-foreground/15 dark:border-muted-foreground/15 dark:hover:bg-muted-foreground/30 size-[34px] rounded-full p-1 text-xs font-semibold"
507
+ className="aui-composer-add-attachment size-[34px] rounded-full p-1 font-semibold text-xs hover:bg-muted-foreground/15 dark:border-muted-foreground/15 dark:hover:bg-muted-foreground/30"
508
508
  aria-label="Add Attachment"
509
509
  >
510
510
  <PlusIcon className="aui-attachment-add-icon size-5 stroke-[1.5px]" />
@@ -555,7 +555,7 @@ const CodeHeader: FC<CodeHeaderProps> = ({ language, code }) => {
555
555
  };
556
556
 
557
557
  return (
558
- <div className="aui-code-header-root bg-muted-foreground/15 text-foreground dark:bg-muted-foreground/20 mt-4 flex items-center justify-between gap-4 rounded-t-lg px-4 py-2 text-sm font-semibold">
558
+ <div className="aui-code-header-root mt-4 flex items-center justify-between gap-4 rounded-t-lg bg-muted-foreground/15 px-4 py-2 font-semibold text-foreground text-sm dark:bg-muted-foreground/20">
559
559
  <span className="aui-code-header-language lowercase [&>span]:text-xs">
560
560
  {language}
561
561
  </span>
@@ -590,7 +590,7 @@ const defaultComponents = memoizeMarkdownComponents({
590
590
  h1: ({ className, ...props }) => (
591
591
  <h1
592
592
  className={cn(
593
- "aui-md-h1 mb-8 scroll-m-20 text-4xl font-extrabold tracking-tight last:mb-0",
593
+ "aui-md-h1 mb-8 scroll-m-20 font-extrabold text-4xl tracking-tight last:mb-0",
594
594
  className,
595
595
  )}
596
596
  {...props}
@@ -599,7 +599,7 @@ const defaultComponents = memoizeMarkdownComponents({
599
599
  h2: ({ className, ...props }) => (
600
600
  <h2
601
601
  className={cn(
602
- "aui-md-h2 mt-8 mb-4 scroll-m-20 text-3xl font-semibold tracking-tight first:mt-0 last:mb-0",
602
+ "aui-md-h2 mt-8 mb-4 scroll-m-20 font-semibold text-3xl tracking-tight first:mt-0 last:mb-0",
603
603
  className,
604
604
  )}
605
605
  {...props}
@@ -608,7 +608,7 @@ const defaultComponents = memoizeMarkdownComponents({
608
608
  h3: ({ className, ...props }) => (
609
609
  <h3
610
610
  className={cn(
611
- "aui-md-h3 mt-6 mb-4 scroll-m-20 text-2xl font-semibold tracking-tight first:mt-0 last:mb-0",
611
+ "aui-md-h3 mt-6 mb-4 scroll-m-20 font-semibold text-2xl tracking-tight first:mt-0 last:mb-0",
612
612
  className,
613
613
  )}
614
614
  {...props}
@@ -617,7 +617,7 @@ const defaultComponents = memoizeMarkdownComponents({
617
617
  h4: ({ className, ...props }) => (
618
618
  <h4
619
619
  className={cn(
620
- "aui-md-h4 mt-6 mb-4 scroll-m-20 text-xl font-semibold tracking-tight first:mt-0 last:mb-0",
620
+ "aui-md-h4 mt-6 mb-4 scroll-m-20 font-semibold text-xl tracking-tight first:mt-0 last:mb-0",
621
621
  className,
622
622
  )}
623
623
  {...props}
@@ -626,7 +626,7 @@ const defaultComponents = memoizeMarkdownComponents({
626
626
  h5: ({ className, ...props }) => (
627
627
  <h5
628
628
  className={cn(
629
- "aui-md-h5 my-4 text-lg font-semibold first:mt-0 last:mb-0",
629
+ "aui-md-h5 my-4 font-semibold text-lg first:mt-0 last:mb-0",
630
630
  className,
631
631
  )}
632
632
  {...props}
@@ -653,7 +653,7 @@ const defaultComponents = memoizeMarkdownComponents({
653
653
  a: ({ className, ...props }) => (
654
654
  <a
655
655
  className={cn(
656
- "aui-md-a text-primary font-medium underline underline-offset-4",
656
+ "aui-md-a font-medium text-primary underline underline-offset-4",
657
657
  className,
658
658
  )}
659
659
  {...props}
@@ -692,7 +692,7 @@ const defaultComponents = memoizeMarkdownComponents({
692
692
  th: ({ className, ...props }) => (
693
693
  <th
694
694
  className={cn(
695
- "aui-md-th bg-muted px-4 py-2 text-left font-bold first:rounded-tl-lg last:rounded-tr-lg [&[align=center]]:text-center [&[align=right]]:text-right",
695
+ "aui-md-th bg-muted px-4 py-2 text-left font-bold first:rounded-tl-lg last:rounded-tr-lg [[align=center]]:text-center [[align=right]]:text-right",
696
696
  className,
697
697
  )}
698
698
  {...props}
@@ -701,7 +701,7 @@ const defaultComponents = memoizeMarkdownComponents({
701
701
  td: ({ className, ...props }) => (
702
702
  <td
703
703
  className={cn(
704
- "aui-md-td border-b border-l px-4 py-2 text-left last:border-r [&[align=center]]:text-center [&[align=right]]:text-right",
704
+ "aui-md-td border-b border-l px-4 py-2 text-left last:border-r [[align=center]]:text-center [[align=right]]:text-right",
705
705
  className,
706
706
  )}
707
707
  {...props}
@@ -725,7 +725,7 @@ const defaultComponents = memoizeMarkdownComponents({
725
725
  pre: ({ className, ...props }) => (
726
726
  <pre
727
727
  className={cn(
728
- "aui-md-pre overflow-x-auto !rounded-t-none rounded-b-lg bg-black p-4 text-white",
728
+ "aui-md-pre overflow-x-auto rounded-t-none! rounded-b-lg bg-black p-4 text-white",
729
729
  className,
730
730
  )}
731
731
  {...props}
@@ -737,7 +737,7 @@ const defaultComponents = memoizeMarkdownComponents({
737
737
  <code
738
738
  className={cn(
739
739
  !isCodeBlock &&
740
- "aui-md-inline-code bg-muted rounded border font-semibold",
740
+ "aui-md-inline-code rounded border bg-muted font-semibold",
741
741
  className,
742
742
  )}
743
743
  {...props}
@@ -752,23 +752,27 @@ const defaultComponents = memoizeMarkdownComponents({
752
752
  ## components/assistant-ui/thread-list.tsx
753
753
 
754
754
  ```tsx
755
- import type { FC } from "react";
755
+ import { TooltipIconButton } from "@/components/assistant-ui/tooltip-icon-button";
756
+ import { Button } from "@/components/ui/button";
757
+ import { Skeleton } from "@/components/ui/skeleton";
756
758
  import {
759
+ AssistantIf,
757
760
  ThreadListItemPrimitive,
758
761
  ThreadListPrimitive,
759
- useAssistantState,
760
762
  } from "@assistant-ui/react";
761
763
  import { ArchiveIcon, PlusIcon } from "lucide-react";
762
-
763
- import { Button } from "@/components/ui/button";
764
- import { TooltipIconButton } from "@/components/assistant-ui/tooltip-icon-button";
765
- import { Skeleton } from "@/components/ui/skeleton";
764
+ import type { FC } from "react";
766
765
 
767
766
  export const ThreadList: FC = () => {
768
767
  return (
769
- <ThreadListPrimitive.Root className="aui-root aui-thread-list-root flex flex-col items-stretch gap-1.5">
768
+ <ThreadListPrimitive.Root className="aui-root aui-thread-list-root flex flex-col gap-1">
770
769
  <ThreadListNew />
771
- <ThreadListItems />
770
+ <AssistantIf condition={({ threads }) => threads.isLoading}>
771
+ <ThreadListSkeleton />
772
+ </AssistantIf>
773
+ <AssistantIf condition={({ threads }) => !threads.isLoading}>
774
+ <ThreadListPrimitive.Items components={{ ThreadListItem }} />
775
+ </AssistantIf>
772
776
  </ThreadListPrimitive.Root>
773
777
  );
774
778
  };
@@ -777,72 +781,53 @@ const ThreadListNew: FC = () => {
777
781
  return (
778
782
  <ThreadListPrimitive.New asChild>
779
783
  <Button
780
- className="aui-thread-list-new hover:bg-muted data-active:bg-muted flex items-center justify-start gap-1 rounded-lg px-2.5 py-2 text-start"
781
- variant="ghost"
784
+ variant="outline"
785
+ className="aui-thread-list-new h-9 justify-start gap-2 rounded-lg px-3 text-sm hover:bg-muted data-active:bg-muted"
782
786
  >
783
- <PlusIcon />
787
+ <PlusIcon className="size-4" />
784
788
  New Thread
785
789
  </Button>
786
790
  </ThreadListPrimitive.New>
787
791
  );
788
792
  };
789
793
 
790
- const ThreadListItems: FC = () => {
791
- const isLoading = useAssistantState(({ threads }) => threads.isLoading);
792
-
793
- if (isLoading) {
794
- return <ThreadListSkeleton />;
795
- }
796
-
797
- return <ThreadListPrimitive.Items components={{ ThreadListItem }} />;
798
- };
799
-
800
794
  const ThreadListSkeleton: FC = () => {
801
795
  return (
802
- <>
796
+ <div className="flex flex-col gap-1">
803
797
  {Array.from({ length: 5 }, (_, i) => (
804
798
  <div
805
799
  key={i}
806
800
  role="status"
807
801
  aria-label="Loading threads"
808
- aria-live="polite"
809
- className="aui-thread-list-skeleton-wrapper flex items-center gap-2 rounded-md px-3 py-2"
802
+ className="aui-thread-list-skeleton-wrapper flex h-9 items-center px-3"
810
803
  >
811
- <Skeleton className="aui-thread-list-skeleton h-[22px] flex-grow" />
804
+ <Skeleton className="aui-thread-list-skeleton h-4 w-full" />
812
805
  </div>
813
806
  ))}
814
- </>
807
+ </div>
815
808
  );
816
809
  };
817
810
 
818
811
  const ThreadListItem: FC = () => {
819
812
  return (
820
- <ThreadListItemPrimitive.Root className="aui-thread-list-item hover:bg-muted focus-visible:bg-muted focus-visible:ring-ring data-active:bg-muted flex items-center gap-2 rounded-lg transition-all focus-visible:ring-2 focus-visible:outline-none">
821
- <ThreadListItemPrimitive.Trigger className="aui-thread-list-item-trigger flex-grow px-3 py-2 text-start">
822
- <ThreadListItemTitle />
813
+ <ThreadListItemPrimitive.Root className="aui-thread-list-item group flex h-9 items-center rounded-lg transition-colors hover:bg-muted focus-visible:bg-muted focus-visible:outline-none data-active:bg-muted">
814
+ <ThreadListItemPrimitive.Trigger className="aui-thread-list-item-trigger flex h-full flex-1 items-center truncate px-3 text-start text-sm">
815
+ <ThreadListItemPrimitive.Title fallback="New Chat" />
823
816
  </ThreadListItemPrimitive.Trigger>
824
817
  <ThreadListItemArchive />
825
818
  </ThreadListItemPrimitive.Root>
826
819
  );
827
820
  };
828
821
 
829
- const ThreadListItemTitle: FC = () => {
830
- return (
831
- <span className="aui-thread-list-item-title text-sm">
832
- <ThreadListItemPrimitive.Title fallback="New Chat" />
833
- </span>
834
- );
835
- };
836
-
837
822
  const ThreadListItemArchive: FC = () => {
838
823
  return (
839
824
  <ThreadListItemPrimitive.Archive asChild>
840
825
  <TooltipIconButton
841
- className="aui-thread-list-item-archive text-foreground hover:text-primary mr-3 ml-auto size-4 p-0"
842
826
  variant="ghost"
843
827
  tooltip="Archive thread"
828
+ className="aui-thread-list-item-archive mr-2 size-7 p-0 opacity-0 transition-opacity group-hover:opacity-100"
844
829
  >
845
- <ArchiveIcon />
830
+ <ArchiveIcon className="size-4" />
846
831
  </TooltipIconButton>
847
832
  </ThreadListItemPrimitive.Archive>
848
833
  );
@@ -853,57 +838,67 @@ const ThreadListItemArchive: FC = () => {
853
838
  ## components/assistant-ui/thread.tsx
854
839
 
855
840
  ```tsx
841
+ import {
842
+ ComposerAddAttachment,
843
+ ComposerAttachments,
844
+ UserMessageAttachments,
845
+ } from "@/components/assistant-ui/attachment";
846
+ import { MarkdownText } from "@/components/assistant-ui/markdown-text";
847
+ import { ToolFallback } from "@/components/assistant-ui/tool-fallback";
848
+ import { TooltipIconButton } from "@/components/assistant-ui/tooltip-icon-button";
849
+ import { Button } from "@/components/ui/button";
850
+ import { cn } from "@/lib/utils";
856
851
  import {
857
852
  ActionBarPrimitive,
853
+ AssistantIf,
858
854
  BranchPickerPrimitive,
859
855
  ComposerPrimitive,
856
+ ErrorPrimitive,
860
857
  MessagePrimitive,
861
858
  ThreadPrimitive,
862
859
  } from "@assistant-ui/react";
863
- import type { FC } from "react";
864
860
  import {
865
861
  ArrowDownIcon,
862
+ ArrowUpIcon,
866
863
  CheckIcon,
867
864
  ChevronLeftIcon,
868
865
  ChevronRightIcon,
869
866
  CopyIcon,
867
+ DownloadIcon,
870
868
  PencilIcon,
871
869
  RefreshCwIcon,
872
- SendHorizontalIcon,
870
+ SquareIcon,
873
871
  } from "lucide-react";
874
- import { cn } from "@/lib/utils";
875
-
876
- import { Button } from "@/components/ui/button";
877
- import { MarkdownText } from "@/components/assistant-ui/markdown-text";
878
- import { TooltipIconButton } from "@/components/assistant-ui/tooltip-icon-button";
872
+ import type { FC } from "react";
879
873
 
880
874
  export const Thread: FC = () => {
881
875
  return (
882
876
  <ThreadPrimitive.Root
883
- className="bg-background box-border flex h-full flex-col overflow-hidden"
877
+ className="aui-root aui-thread-root @container flex h-full flex-col bg-background"
884
878
  style={{
885
- ["--thread-max-width" as string]: "42rem",
879
+ ["--thread-max-width" as string]: "44rem",
886
880
  }}
887
881
  >
888
- <ThreadPrimitive.Viewport className="flex h-full flex-col items-center overflow-y-scroll scroll-smooth bg-inherit px-4 pt-8">
889
- <ThreadWelcome />
882
+ <ThreadPrimitive.Viewport
883
+ turnAnchor="top"
884
+ className="aui-thread-viewport relative flex flex-1 flex-col overflow-x-auto overflow-y-scroll scroll-smooth px-4 pt-4"
885
+ >
886
+ <AssistantIf condition={({ thread }) => thread.isEmpty}>
887
+ <ThreadWelcome />
888
+ </AssistantIf>
890
889
 
891
890
  <ThreadPrimitive.Messages
892
891
  components={{
893
- UserMessage: UserMessage,
894
- EditComposer: EditComposer,
895
- AssistantMessage: AssistantMessage,
892
+ UserMessage,
893
+ EditComposer,
894
+ AssistantMessage,
896
895
  }}
897
896
  />
898
897
 
899
- <ThreadPrimitive.If empty={false}>
900
- <div className="min-h-8 flex-grow" />
901
- </ThreadPrimitive.If>
902
-
903
- <div className="sticky bottom-0 mt-3 flex w-full max-w-[var(--thread-max-width)] flex-col items-center justify-end rounded-t-lg bg-inherit pb-4">
898
+ <ThreadPrimitive.ViewportFooter className="aui-thread-viewport-footer sticky bottom-0 mx-auto mt-auto flex w-full max-w-(--thread-max-width) flex-col gap-4 overflow-visible rounded-t-3xl bg-background pb-4 md:pb-6">
904
899
  <ThreadScrollToBottom />
905
900
  <Composer />
906
- </div>
901
+ </ThreadPrimitive.ViewportFooter>
907
902
  </ThreadPrimitive.Viewport>
908
903
  </ThreadPrimitive.Root>
909
904
  );
@@ -915,7 +910,7 @@ const ThreadScrollToBottom: FC = () => {
915
910
  <TooltipIconButton
916
911
  tooltip="Scroll to bottom"
917
912
  variant="outline"
918
- className="absolute -top-8 rounded-full disabled:invisible"
913
+ className="aui-thread-scroll-to-bottom -top-12 absolute z-10 self-center rounded-full p-4 disabled:invisible dark:bg-background dark:hover:bg-accent"
919
914
  >
920
915
  <ArrowDownIcon />
921
916
  </TooltipIconButton>
@@ -925,175 +920,247 @@ const ThreadScrollToBottom: FC = () => {
925
920
 
926
921
  const ThreadWelcome: FC = () => {
927
922
  return (
928
- <ThreadPrimitive.Empty>
929
- <div className="flex w-full max-w-[var(--thread-max-width)] flex-grow flex-col">
930
- <div className="flex w-full flex-grow flex-col items-center justify-center">
931
- <p className="mt-4 font-medium">How can I help you today?</p>
923
+ <div className="aui-thread-welcome-root mx-auto my-auto flex w-full max-w-(--thread-max-width) grow flex-col">
924
+ <div className="aui-thread-welcome-center flex w-full grow flex-col items-center justify-center">
925
+ <div className="aui-thread-welcome-message flex size-full flex-col justify-center px-4">
926
+ <h1 className="aui-thread-welcome-message-inner fade-in slide-in-from-bottom-1 animate-in font-semibold text-2xl duration-200">
927
+ Hello there!
928
+ </h1>
929
+ <p className="aui-thread-welcome-message-inner fade-in slide-in-from-bottom-1 animate-in text-muted-foreground text-xl delay-75 duration-200">
930
+ How can I help you today?
931
+ </p>
932
932
  </div>
933
- <ThreadWelcomeSuggestions />
934
933
  </div>
935
- </ThreadPrimitive.Empty>
934
+ <ThreadSuggestions />
935
+ </div>
936
936
  );
937
937
  };
938
938
 
939
- const ThreadWelcomeSuggestions: FC = () => {
939
+ const SUGGESTIONS = [
940
+ {
941
+ title: "What's the weather",
942
+ label: "in San Francisco?",
943
+ prompt: "What's the weather in San Francisco?",
944
+ },
945
+ {
946
+ title: "Explain React hooks",
947
+ label: "like useState and useEffect",
948
+ prompt: "Explain React hooks like useState and useEffect",
949
+ },
950
+ ] as const;
951
+
952
+ const ThreadSuggestions: FC = () => {
940
953
  return (
941
- <div className="mt-3 flex w-full items-stretch justify-center gap-4">
942
- <ThreadPrimitive.Suggestion
943
- className="hover:bg-muted/80 flex max-w-sm grow basis-0 flex-col items-center justify-center rounded-lg border p-3 transition-colors ease-in"
944
- prompt="What is the weather in Tokyo?"
945
- method="replace"
946
- autoSend
947
- >
948
- <span className="line-clamp-2 text-sm font-semibold text-ellipsis">
949
- What is the weather in Tokyo?
950
- </span>
951
- </ThreadPrimitive.Suggestion>
952
- <ThreadPrimitive.Suggestion
953
- className="hover:bg-muted/80 flex max-w-sm grow basis-0 flex-col items-center justify-center rounded-lg border p-3 transition-colors ease-in"
954
- prompt="What is assistant-ui?"
955
- method="replace"
956
- autoSend
957
- >
958
- <span className="line-clamp-2 text-sm font-semibold text-ellipsis">
959
- What is assistant-ui?
960
- </span>
961
- </ThreadPrimitive.Suggestion>
954
+ <div className="aui-thread-welcome-suggestions grid w-full @md:grid-cols-2 gap-2 pb-4">
955
+ {SUGGESTIONS.map((suggestion, index) => (
956
+ <div
957
+ key={suggestion.prompt}
958
+ className="aui-thread-welcome-suggestion-display fade-in slide-in-from-bottom-2 @md:nth-[n+3]:block nth-[n+3]:hidden animate-in fill-mode-both duration-200"
959
+ style={{ animationDelay: `${100 + index * 50}ms` }}
960
+ >
961
+ <ThreadPrimitive.Suggestion prompt={suggestion.prompt} send asChild>
962
+ <Button
963
+ variant="ghost"
964
+ className="aui-thread-welcome-suggestion h-auto w-full @md:flex-col flex-wrap items-start justify-start gap-1 rounded-2xl border px-4 py-3 text-left text-sm transition-colors hover:bg-muted"
965
+ aria-label={suggestion.prompt}
966
+ >
967
+ <span className="aui-thread-welcome-suggestion-text-1 font-medium">
968
+ {suggestion.title}
969
+ </span>
970
+ <span className="aui-thread-welcome-suggestion-text-2 text-muted-foreground">
971
+ {suggestion.label}
972
+ </span>
973
+ </Button>
974
+ </ThreadPrimitive.Suggestion>
975
+ </div>
976
+ ))}
962
977
  </div>
963
978
  );
964
979
  };
965
980
 
966
981
  const Composer: FC = () => {
967
982
  return (
968
- <ComposerPrimitive.Root className="focus-within:border-ring/20 flex w-full flex-wrap items-end rounded-lg border bg-inherit px-2.5 shadow-sm transition-colors ease-in">
969
- <ComposerPrimitive.Input
970
- rows={1}
971
- autoFocus
972
- placeholder="Write a message..."
973
- className="placeholder:text-muted-foreground max-h-40 flex-grow resize-none border-none bg-transparent px-2 py-4 text-sm outline-none focus:ring-0 disabled:cursor-not-allowed"
974
- />
975
- <ComposerAction />
983
+ <ComposerPrimitive.Root className="aui-composer-root relative flex w-full flex-col">
984
+ <ComposerPrimitive.AttachmentDropzone className="aui-composer-attachment-dropzone flex w-full flex-col rounded-2xl border border-input bg-background px-1 pt-2 outline-none transition-shadow has-[textarea:focus-visible]:border-ring has-[textarea:focus-visible]:ring-2 has-[textarea:focus-visible]:ring-ring/20 data-[dragging=true]:border-ring data-[dragging=true]:border-dashed data-[dragging=true]:bg-accent/50">
985
+ <ComposerAttachments />
986
+ <ComposerPrimitive.Input
987
+ placeholder="Send a message..."
988
+ className="aui-composer-input mb-1 max-h-32 min-h-14 w-full resize-none bg-transparent px-4 pt-2 pb-3 text-sm outline-none placeholder:text-muted-foreground focus-visible:ring-0"
989
+ rows={1}
990
+ autoFocus
991
+ aria-label="Message input"
992
+ />
993
+ <ComposerAction />
994
+ </ComposerPrimitive.AttachmentDropzone>
976
995
  </ComposerPrimitive.Root>
977
996
  );
978
997
  };
979
998
 
980
999
  const ComposerAction: FC = () => {
981
1000
  return (
982
- <>
983
- <ThreadPrimitive.If running={false}>
1001
+ <div className="aui-composer-action-wrapper relative mx-2 mb-2 flex items-center justify-between">
1002
+ <ComposerAddAttachment />
1003
+
1004
+ <AssistantIf condition={({ thread }) => !thread.isRunning}>
984
1005
  <ComposerPrimitive.Send asChild>
985
1006
  <TooltipIconButton
986
- tooltip="Send"
1007
+ tooltip="Send message"
1008
+ side="bottom"
1009
+ type="submit"
987
1010
  variant="default"
988
- className="my-2.5 size-8 p-2 transition-opacity ease-in"
1011
+ size="icon"
1012
+ className="aui-composer-send size-8 rounded-full"
1013
+ aria-label="Send message"
989
1014
  >
990
- <SendHorizontalIcon />
1015
+ <ArrowUpIcon className="aui-composer-send-icon size-4" />
991
1016
  </TooltipIconButton>
992
1017
  </ComposerPrimitive.Send>
993
- </ThreadPrimitive.If>
994
- <ThreadPrimitive.If running>
1018
+ </AssistantIf>
1019
+
1020
+ <AssistantIf condition={({ thread }) => thread.isRunning}>
995
1021
  <ComposerPrimitive.Cancel asChild>
996
- <TooltipIconButton
997
- tooltip="Cancel"
1022
+ <Button
1023
+ type="button"
998
1024
  variant="default"
999
- className="my-2.5 size-8 p-2 transition-opacity ease-in"
1025
+ size="icon"
1026
+ className="aui-composer-cancel size-8 rounded-full"
1027
+ aria-label="Stop generating"
1000
1028
  >
1001
- <CircleStopIcon />
1002
- </TooltipIconButton>
1029
+ <SquareIcon className="aui-composer-cancel-icon size-3 fill-current" />
1030
+ </Button>
1003
1031
  </ComposerPrimitive.Cancel>
1004
- </ThreadPrimitive.If>
1005
- </>
1032
+ </AssistantIf>
1033
+ </div>
1006
1034
  );
1007
1035
  };
1008
1036
 
1009
- const UserMessage: FC = () => {
1037
+ const MessageError: FC = () => {
1010
1038
  return (
1011
- <MessagePrimitive.Root className="grid w-full max-w-[var(--thread-max-width)] auto-rows-auto grid-cols-[minmax(72px,1fr)_auto] gap-y-2 py-4 [&:where(>*)]:col-start-2">
1012
- <UserActionBar />
1039
+ <MessagePrimitive.Error>
1040
+ <ErrorPrimitive.Root className="aui-message-error-root mt-2 rounded-md border border-destructive bg-destructive/10 p-3 text-destructive text-sm dark:bg-destructive/5 dark:text-red-200">
1041
+ <ErrorPrimitive.Message className="aui-message-error-message line-clamp-2" />
1042
+ </ErrorPrimitive.Root>
1043
+ </MessagePrimitive.Error>
1044
+ );
1045
+ };
1013
1046
 
1014
- <div className="bg-muted text-foreground col-start-2 row-start-2 max-w-[calc(var(--thread-max-width)*0.8)] rounded-3xl px-5 py-2.5 break-words">
1015
- <MessagePrimitive.Parts />
1047
+ const AssistantMessage: FC = () => {
1048
+ return (
1049
+ <MessagePrimitive.Root
1050
+ className="aui-assistant-message-root fade-in slide-in-from-bottom-1 relative mx-auto w-full max-w-(--thread-max-width) animate-in py-3 duration-150"
1051
+ data-role="assistant"
1052
+ >
1053
+ <div className="aui-assistant-message-content wrap-break-word px-2 text-foreground leading-relaxed">
1054
+ <MessagePrimitive.Parts
1055
+ components={{
1056
+ Text: MarkdownText,
1057
+ tools: { Fallback: ToolFallback },
1058
+ }}
1059
+ />
1060
+ <MessageError />
1016
1061
  </div>
1017
1062
 
1018
- <BranchPicker className="col-span-full col-start-1 row-start-3 -mr-1 justify-end" />
1063
+ <div className="aui-assistant-message-footer mt-1 ml-2 flex">
1064
+ <BranchPicker />
1065
+ <AssistantActionBar />
1066
+ </div>
1019
1067
  </MessagePrimitive.Root>
1020
1068
  );
1021
1069
  };
1022
1070
 
1023
- const UserActionBar: FC = () => {
1071
+ const AssistantActionBar: FC = () => {
1024
1072
  return (
1025
1073
  <ActionBarPrimitive.Root
1026
1074
  hideWhenRunning
1027
1075
  autohide="not-last"
1028
- className="col-start-1 row-start-2 mt-2.5 mr-3 flex flex-col items-end"
1076
+ autohideFloat="single-branch"
1077
+ className="aui-assistant-action-bar-root -ml-1 col-start-3 row-start-2 flex gap-1 text-muted-foreground data-floating:absolute data-floating:rounded-md data-floating:border data-floating:bg-background data-floating:p-1 data-floating:shadow-sm"
1029
1078
  >
1030
- <ActionBarPrimitive.Edit asChild>
1031
- <TooltipIconButton tooltip="Edit">
1032
- <PencilIcon />
1079
+ <ActionBarPrimitive.Copy asChild>
1080
+ <TooltipIconButton tooltip="Copy">
1081
+ <AssistantIf condition={({ message }) => message.isCopied}>
1082
+ <CheckIcon />
1083
+ </AssistantIf>
1084
+ <AssistantIf condition={({ message }) => !message.isCopied}>
1085
+ <CopyIcon />
1086
+ </AssistantIf>
1033
1087
  </TooltipIconButton>
1034
- </ActionBarPrimitive.Edit>
1088
+ </ActionBarPrimitive.Copy>
1089
+ <ActionBarPrimitive.ExportMarkdown asChild>
1090
+ <TooltipIconButton tooltip="Export as Markdown">
1091
+ <DownloadIcon />
1092
+ </TooltipIconButton>
1093
+ </ActionBarPrimitive.ExportMarkdown>
1094
+ <ActionBarPrimitive.Reload asChild>
1095
+ <TooltipIconButton tooltip="Refresh">
1096
+ <RefreshCwIcon />
1097
+ </TooltipIconButton>
1098
+ </ActionBarPrimitive.Reload>
1035
1099
  </ActionBarPrimitive.Root>
1036
1100
  );
1037
1101
  };
1038
1102
 
1039
- const EditComposer: FC = () => {
1103
+ const UserMessage: FC = () => {
1040
1104
  return (
1041
- <ComposerPrimitive.Root className="bg-muted my-4 flex w-full max-w-[var(--thread-max-width)] flex-col gap-2 rounded-xl">
1042
- <ComposerPrimitive.Input className="text-foreground flex h-8 w-full resize-none bg-transparent p-4 pb-0 outline-none" />
1043
-
1044
- <div className="mx-3 mb-3 flex items-center justify-center gap-2 self-end">
1045
- <ComposerPrimitive.Cancel asChild>
1046
- <Button variant="ghost">Cancel</Button>
1047
- </ComposerPrimitive.Cancel>
1048
- <ComposerPrimitive.Send asChild>
1049
- <Button>Send</Button>
1050
- </ComposerPrimitive.Send>
1051
- </div>
1052
- </ComposerPrimitive.Root>
1053
- );
1054
- };
1105
+ <MessagePrimitive.Root
1106
+ className="aui-user-message-root fade-in slide-in-from-bottom-1 mx-auto grid w-full max-w-(--thread-max-width) animate-in auto-rows-auto grid-cols-[minmax(72px,1fr)_auto] content-start gap-y-2 px-2 py-3 duration-150 [&:where(>*)]:col-start-2"
1107
+ data-role="user"
1108
+ >
1109
+ <UserMessageAttachments />
1055
1110
 
1056
- const AssistantMessage: FC = () => {
1057
- return (
1058
- <MessagePrimitive.Root className="relative grid w-full max-w-[var(--thread-max-width)] grid-cols-[auto_auto_1fr] grid-rows-[auto_1fr] py-4">
1059
- <div className="text-foreground col-span-2 col-start-2 row-start-1 my-1.5 max-w-[calc(var(--thread-max-width)*0.8)] leading-7 break-words">
1060
- <MessagePrimitive.Parts components={{ Text: MarkdownText }} />
1111
+ <div className="aui-user-message-content-wrapper relative col-start-2 min-w-0">
1112
+ <div className="aui-user-message-content wrap-break-word rounded-2xl bg-muted px-4 py-2.5 text-foreground">
1113
+ <MessagePrimitive.Parts />
1114
+ </div>
1115
+ <div className="aui-user-action-bar-wrapper -translate-x-full -translate-y-1/2 absolute top-1/2 left-0 pr-2">
1116
+ <UserActionBar />
1117
+ </div>
1061
1118
  </div>
1062
1119
 
1063
- <AssistantActionBar />
1064
-
1065
- <BranchPicker className="col-start-2 row-start-2 mr-2 -ml-2" />
1120
+ <BranchPicker className="aui-user-branch-picker -mr-1 col-span-full col-start-1 row-start-3 justify-end" />
1066
1121
  </MessagePrimitive.Root>
1067
1122
  );
1068
1123
  };
1069
1124
 
1070
- const AssistantActionBar: FC = () => {
1125
+ const UserActionBar: FC = () => {
1071
1126
  return (
1072
1127
  <ActionBarPrimitive.Root
1073
1128
  hideWhenRunning
1074
1129
  autohide="not-last"
1075
- autohideFloat="single-branch"
1076
- className="text-muted-foreground data-[floating]:bg-background col-start-3 row-start-2 -ml-1 flex gap-1 data-[floating]:absolute data-[floating]:rounded-md data-[floating]:border data-[floating]:p-1 data-[floating]:shadow-sm"
1130
+ className="aui-user-action-bar-root flex flex-col items-end"
1077
1131
  >
1078
- <ActionBarPrimitive.Copy asChild>
1079
- <TooltipIconButton tooltip="Copy">
1080
- <MessagePrimitive.If copied>
1081
- <CheckIcon />
1082
- </MessagePrimitive.If>
1083
- <MessagePrimitive.If copied={false}>
1084
- <CopyIcon />
1085
- </MessagePrimitive.If>
1086
- </TooltipIconButton>
1087
- </ActionBarPrimitive.Copy>
1088
- <ActionBarPrimitive.Reload asChild>
1089
- <TooltipIconButton tooltip="Refresh">
1090
- <RefreshCwIcon />
1132
+ <ActionBarPrimitive.Edit asChild>
1133
+ <TooltipIconButton tooltip="Edit" className="aui-user-action-edit p-4">
1134
+ <PencilIcon />
1091
1135
  </TooltipIconButton>
1092
- </ActionBarPrimitive.Reload>
1136
+ </ActionBarPrimitive.Edit>
1093
1137
  </ActionBarPrimitive.Root>
1094
1138
  );
1095
1139
  };
1096
1140
 
1141
+ const EditComposer: FC = () => {
1142
+ return (
1143
+ <MessagePrimitive.Root className="aui-edit-composer-wrapper mx-auto flex w-full max-w-(--thread-max-width) flex-col px-2 py-3">
1144
+ <ComposerPrimitive.Root className="aui-edit-composer-root ml-auto flex w-full max-w-[85%] flex-col rounded-2xl bg-muted">
1145
+ <ComposerPrimitive.Input
1146
+ className="aui-edit-composer-input min-h-14 w-full resize-none bg-transparent p-4 text-foreground text-sm outline-none"
1147
+ autoFocus
1148
+ />
1149
+ <div className="aui-edit-composer-footer mx-3 mb-3 flex items-center gap-2 self-end">
1150
+ <ComposerPrimitive.Cancel asChild>
1151
+ <Button variant="ghost" size="sm">
1152
+ Cancel
1153
+ </Button>
1154
+ </ComposerPrimitive.Cancel>
1155
+ <ComposerPrimitive.Send asChild>
1156
+ <Button size="sm">Update</Button>
1157
+ </ComposerPrimitive.Send>
1158
+ </div>
1159
+ </ComposerPrimitive.Root>
1160
+ </MessagePrimitive.Root>
1161
+ );
1162
+ };
1163
+
1097
1164
  const BranchPicker: FC<BranchPickerPrimitive.Root.Props> = ({
1098
1165
  className,
1099
1166
  ...rest
@@ -1102,7 +1169,7 @@ const BranchPicker: FC<BranchPickerPrimitive.Root.Props> = ({
1102
1169
  <BranchPickerPrimitive.Root
1103
1170
  hideWhenSingleBranch
1104
1171
  className={cn(
1105
- "text-muted-foreground inline-flex items-center text-xs",
1172
+ "aui-branch-picker-root -ml-2 mr-2 inline-flex items-center text-muted-foreground text-xs",
1106
1173
  className,
1107
1174
  )}
1108
1175
  {...rest}
@@ -1112,7 +1179,7 @@ const BranchPicker: FC<BranchPickerPrimitive.Root.Props> = ({
1112
1179
  <ChevronLeftIcon />
1113
1180
  </TooltipIconButton>
1114
1181
  </BranchPickerPrimitive.Previous>
1115
- <span className="font-medium">
1182
+ <span className="aui-branch-picker-state font-medium">
1116
1183
  <BranchPickerPrimitive.Number /> / <BranchPickerPrimitive.Count />
1117
1184
  </span>
1118
1185
  <BranchPickerPrimitive.Next asChild>
@@ -1124,20 +1191,6 @@ const BranchPicker: FC<BranchPickerPrimitive.Root.Props> = ({
1124
1191
  );
1125
1192
  };
1126
1193
 
1127
- const CircleStopIcon = () => {
1128
- return (
1129
- <svg
1130
- xmlns="http://www.w3.org/2000/svg"
1131
- viewBox="0 0 16 16"
1132
- fill="currentColor"
1133
- width="16"
1134
- height="16"
1135
- >
1136
- <rect width="10" height="10" x="3" y="3" rx="2" />
1137
- </svg>
1138
- );
1139
- };
1140
-
1141
1194
  ```
1142
1195
 
1143
1196
  ## components/assistant-ui/tool-fallback.tsx
@@ -1180,7 +1233,7 @@ export const ToolFallback: ToolCallMessagePartComponent = ({
1180
1233
  >
1181
1234
  <div className="aui-tool-fallback-header flex items-center gap-2 px-4">
1182
1235
  {isCancelled ? (
1183
- <XCircleIcon className="aui-tool-fallback-icon text-muted-foreground size-4" />
1236
+ <XCircleIcon className="aui-tool-fallback-icon size-4 text-muted-foreground" />
1184
1237
  ) : (
1185
1238
  <CheckIcon className="aui-tool-fallback-icon size-4" />
1186
1239
  )}
@@ -1201,7 +1254,7 @@ export const ToolFallback: ToolCallMessagePartComponent = ({
1201
1254
  <div className="aui-tool-fallback-content flex flex-col gap-2 border-t pt-2">
1202
1255
  {cancelledReason && (
1203
1256
  <div className="aui-tool-fallback-cancelled-root px-4">
1204
- <p className="aui-tool-fallback-cancelled-header text-muted-foreground font-semibold">
1257
+ <p className="aui-tool-fallback-cancelled-header font-semibold text-muted-foreground">
1205
1258
  Cancelled reason:
1206
1259
  </p>
1207
1260
  <p className="aui-tool-fallback-cancelled-reason text-muted-foreground">
@@ -1331,7 +1384,7 @@ const AvatarFallback = React.forwardRef<
1331
1384
  <AvatarPrimitive.Fallback
1332
1385
  ref={ref}
1333
1386
  className={cn(
1334
- "bg-muted flex h-full w-full items-center justify-center rounded-full",
1387
+ "flex h-full w-full items-center justify-center rounded-full bg-muted",
1335
1388
  className,
1336
1389
  )}
1337
1390
  {...props}
@@ -1353,16 +1406,16 @@ import { cva, type VariantProps } from "class-variance-authority";
1353
1406
  import { cn } from "@/lib/utils";
1354
1407
 
1355
1408
  const buttonVariants = cva(
1356
- "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
1409
+ "inline-flex shrink-0 items-center justify-center gap-2 whitespace-nowrap rounded-md font-medium text-sm outline-none transition-all focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0",
1357
1410
  {
1358
1411
  variants: {
1359
1412
  variant: {
1360
1413
  default:
1361
1414
  "bg-primary text-primary-foreground shadow-xs hover:bg-primary/90",
1362
1415
  destructive:
1363
- "bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
1416
+ "bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:bg-destructive/60 dark:focus-visible:ring-destructive/40",
1364
1417
  outline:
1365
- "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50",
1418
+ "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50",
1366
1419
  secondary:
1367
1420
  "bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80",
1368
1421
  ghost:
@@ -1371,7 +1424,7 @@ const buttonVariants = cva(
1371
1424
  },
1372
1425
  size: {
1373
1426
  default: "h-9 px-4 py-2 has-[>svg]:px-3",
1374
- sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
1427
+ sm: "h-8 gap-1.5 rounded-md px-3 has-[>svg]:px-2.5",
1375
1428
  lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
1376
1429
  icon: "size-9",
1377
1430
  },
@@ -1451,7 +1504,7 @@ function DialogOverlay({
1451
1504
  <DialogPrimitive.Overlay
1452
1505
  data-slot="dialog-overlay"
1453
1506
  className={cn(
1454
- "data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:animate-in data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/80",
1507
+ "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/80 data-[state=closed]:animate-out data-[state=open]:animate-in",
1455
1508
  className,
1456
1509
  )}
1457
1510
  {...props}
@@ -1470,13 +1523,13 @@ function DialogContent({
1470
1523
  <DialogPrimitive.Content
1471
1524
  data-slot="dialog-content"
1472
1525
  className={cn(
1473
- "bg-background data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 sm:max-w-lg",
1526
+ "data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border bg-background p-6 shadow-lg duration-200 data-[state=closed]:animate-out data-[state=open]:animate-in sm:max-w-lg",
1474
1527
  className,
1475
1528
  )}
1476
1529
  {...props}
1477
1530
  >
1478
1531
  {children}
1479
- <DialogPrimitive.Close className="ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4">
1532
+ <DialogPrimitive.Close className="absolute top-4 right-4 rounded-xs opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-hidden focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0">
1480
1533
  <XIcon />
1481
1534
  <span className="sr-only">Close</span>
1482
1535
  </DialogPrimitive.Close>
@@ -1515,7 +1568,7 @@ function DialogTitle({
1515
1568
  return (
1516
1569
  <DialogPrimitive.Title
1517
1570
  data-slot="dialog-title"
1518
- className={cn("text-lg leading-none font-semibold", className)}
1571
+ className={cn("font-semibold text-lg leading-none", className)}
1519
1572
  {...props}
1520
1573
  />
1521
1574
  );
@@ -1558,7 +1611,7 @@ function Skeleton({ className, ...props }: React.ComponentProps<"div">) {
1558
1611
  return (
1559
1612
  <div
1560
1613
  data-slot="skeleton"
1561
- className={cn("bg-accent animate-pulse rounded-md", className)}
1614
+ className={cn("animate-pulse rounded-md bg-accent", className)}
1562
1615
  {...props}
1563
1616
  />
1564
1617
  );
@@ -1619,13 +1672,13 @@ function TooltipContent({
1619
1672
  data-slot="tooltip-content"
1620
1673
  sideOffset={sideOffset}
1621
1674
  className={cn(
1622
- "bg-primary text-primary-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-fit origin-[--radix-tooltip-content-transform-origin] rounded-md px-3 py-1.5 text-xs text-balance",
1675
+ "fade-in-0 zoom-in-95 data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-fit origin-[--radix-tooltip-content-transform-origin] animate-in text-balance rounded-md bg-primary px-3 py-1.5 text-primary-foreground text-xs data-[state=closed]:animate-out",
1623
1676
  className,
1624
1677
  )}
1625
1678
  {...props}
1626
1679
  >
1627
1680
  {children}
1628
- <TooltipPrimitive.Arrow className="bg-primary fill-primary z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px]" />
1681
+ <TooltipPrimitive.Arrow className="z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px] bg-primary fill-primary" />
1629
1682
  </TooltipPrimitive.Content>
1630
1683
  </TooltipPrimitive.Portal>
1631
1684
  );
@@ -1670,32 +1723,30 @@ export default nextConfig;
1670
1723
  "scripts": {
1671
1724
  "dev": "next dev --turbo",
1672
1725
  "build": "next build",
1673
- "start": "next start",
1674
- "lint": "eslint ."
1726
+ "start": "next start"
1675
1727
  },
1676
1728
  "dependencies": {
1677
- "@ai-sdk/openai": "^2.0.73",
1729
+ "@ai-sdk/openai": "^2.0.77",
1678
1730
  "@assistant-ui/react": "workspace:*",
1679
1731
  "@assistant-ui/react-ai-sdk": "workspace:*",
1680
1732
  "@assistant-ui/react-markdown": "workspace:*",
1681
- "@radix-ui/react-avatar": "^1.1.4",
1682
- "@radix-ui/react-dialog": "^1.1.7",
1733
+ "@radix-ui/react-avatar": "^1.1.11",
1734
+ "@radix-ui/react-dialog": "^1.1.15",
1683
1735
  "@radix-ui/react-slot": "^1.2.4",
1684
1736
  "@radix-ui/react-tooltip": "^1.2.8",
1685
- "ai": "^5.0.102",
1737
+ "ai": "^5.0.107",
1686
1738
  "class-variance-authority": "^0.7.1",
1687
1739
  "clsx": "^2.1.1",
1688
- "jsonwebtoken": "^9.0.2",
1689
- "lucide-react": "^0.555.0",
1690
- "motion": "^11.18.2",
1740
+ "jsonwebtoken": "^9.0.3",
1741
+ "lucide-react": "^0.556.0",
1691
1742
  "nanoid": "5.1.6",
1692
- "next": "16.0.4",
1693
- "react": "19.2.0",
1694
- "react-dom": "19.2.0",
1743
+ "next": "16.0.7",
1744
+ "react": "19.2.1",
1745
+ "react-dom": "19.2.1",
1695
1746
  "remark-gfm": "^4.0.1",
1696
1747
  "tailwind-merge": "^3.4.0",
1697
1748
  "tw-animate-css": "^1.4.0",
1698
- "zustand": "^5.0.8"
1749
+ "zustand": "^5.0.9"
1699
1750
  },
1700
1751
  "devDependencies": {
1701
1752
  "@assistant-ui/x-buildutils": "workspace:*",