Skip to content

Commit

Permalink
feat: Chat bubble design (#250)
Browse files Browse the repository at this point in the history
* feat: Chat bubble design

* automatically break words

* update minimal thread template

* add changeset
  • Loading branch information
Yonom authored Jun 20, 2024
1 parent dd38913 commit 52236ab
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 85 deletions.
5 changes: 5 additions & 0 deletions .changeset/plenty-ants-exercise.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@assistant-ui/react": patch
---

feat: new default chat bubble design
2 changes: 1 addition & 1 deletion apps/www/components/shadcn/Shadcn.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import icon from "@/public/favicon/favicon.svg";
import type { TooltipContentProps } from "@radix-ui/react-tooltip";
import Image from "next/image";
import { type FC, forwardRef } from "react";
import { Thread } from "assistant-ui/registry/assistant-ui/full/thread";
import { Thread } from "@/components/ui/assistant-ui/thread";
import { Sheet, SheetContent, SheetTrigger } from "../ui/sheet";
import { Tooltip, TooltipContent, TooltipTrigger } from "../ui/tooltip";
import { ModelPicker } from "./ModelPicker";
Expand Down
87 changes: 34 additions & 53 deletions packages/cli/registry/assistant-ui/full/thread.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -105,78 +105,59 @@ const Composer: FC = () => {

const UserMessage: FC = () => {
return (
<MessagePrimitive.Root className="relative flex w-full max-w-2xl gap-3 pb-12">
<Avatar>
<AvatarFallback>Y</AvatarFallback>
</Avatar>

<div className="flex-grow">
<p className="font-semibold">You</p>

<p className="whitespace-pre-line text-foreground">
<MessagePrimitive.Root className="relative mb-6 flex w-full max-w-2xl flex-col items-end gap-2 pl-24">
<div className="relative mr-1 flex items-start gap-3">
<ActionBarPrimitive.Root
hideWhenRunning
autohide="not-last"
className="mt-2"
>
<ActionBarPrimitive.Edit asChild>
<IconButton tooltip="Edit">
<PencilIcon className="size-4" />
</IconButton>
</ActionBarPrimitive.Edit>
</ActionBarPrimitive.Root>

<p className="max-w-xl break-words whitespace-pre-line rounded-3xl bg-foreground/5 px-5 py-2.5 text-foreground">
<MessagePrimitive.Content />
</p>

<div className="flex pt-2">
<BranchPicker />

<ActionBarPrimitive.Root
hideWhenRunning
autohide="not-last"
autohideFloat="single-branch"
className="flex items-center gap-1 rounded-lg data-[floating]:absolute data-[floating]:border data-[floating]:p-1"
>
<ActionBarPrimitive.Edit asChild>
<IconButton tooltip="Edit">
<PencilIcon className="size-4" />
</IconButton>
</ActionBarPrimitive.Edit>
</ActionBarPrimitive.Root>
</div>
</div>

<BranchPicker />
</MessagePrimitive.Root>
);
};

const EditComposer: FC = () => {
return (
<MessagePrimitive.Root className="flex w-full max-w-2xl gap-3 pb-4">
<Avatar>
<AvatarFallback>Y</AvatarFallback>
</Avatar>

<div className="flex-grow">
<p className="font-semibold">You</p>

<ComposerPrimitive.Root>
<ComposerPrimitive.Input className="flex h-8 w-full resize-none bg-transparent outline-none" />

<div className="mt-1 flex justify-center gap-3">
<ComposerPrimitive.Send asChild>
<Button>Save & Submit</Button>
</ComposerPrimitive.Send>
<ComposerPrimitive.Cancel asChild>
<Button variant="outline">Cancel</Button>
</ComposerPrimitive.Cancel>
</div>
</ComposerPrimitive.Root>
<ComposerPrimitive.Root className="mb-4 flex w-full max-w-2xl flex-col gap-2 rounded-xl bg-foreground/5">
<ComposerPrimitive.Input className="flex h-8 w-full resize-none bg-transparent p-5 pb-0 text-foreground outline-none" />

<div className="mx-3 mb-3 flex items-center justify-center gap-2 self-end">
<ComposerPrimitive.Cancel asChild>
<Button variant="secondary" className="bg-transparent">
Cancel
</Button>
</ComposerPrimitive.Cancel>
<ComposerPrimitive.Send>
<Button>Send</Button>
</ComposerPrimitive.Send>
</div>
</MessagePrimitive.Root>
</ComposerPrimitive.Root>
);
};

const AssistantMessage: FC = () => {
return (
<MessagePrimitive.Root className="relative flex w-full max-w-2xl gap-3 pb-12">
<MessagePrimitive.Root className="relative mb-6 flex w-full max-w-2xl gap-3">
<Avatar>
<AvatarFallback>A</AvatarFallback>
</Avatar>

<div className="flex-grow">
<p className="font-semibold">Assistant</p>

<div className="mt-2 flex-grow">
<MessagePrimitive.InProgress className="inline-block size-3 animate-pulse rounded-full bg-foreground" />
<p className="whitespace-pre-line text-foreground">
<p className="max-w-xl break-words whitespace-pre-line text-foreground">
<MessagePrimitive.Content />
</p>

Expand All @@ -187,7 +168,7 @@ const AssistantMessage: FC = () => {
hideWhenRunning
autohide="not-last"
autohideFloat="single-branch"
className="flex items-center gap-1 rounded-lg data-[floating]:absolute data-[floating]:border data-[floating]:p-1"
className="flex items-center gap-1 rounded-lg data-[floating]:absolute data-[floating]:border data-[floating]:bg-background data-[floating]:p-1"
>
<ActionBarPrimitive.Copy asChild>
<IconButton tooltip="Copy">
Expand Down
65 changes: 34 additions & 31 deletions packages/cli/registry/assistant-ui/thread.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,29 @@ import {
import type { FC } from "react";

import { Avatar, AvatarFallback } from "@/components/ui/avatar";
import { TooltipProvider } from "@radix-ui/react-tooltip";
import { SendHorizonalIcon } from "lucide-react";

export const Thread: FC = () => {
return (
<ThreadPrimitive.Root className="flex h-full flex-col items-center pb-3">
<ThreadPrimitive.Viewport className="flex w-full flex-grow flex-col items-center overflow-y-scroll scroll-smooth px-4 pt-12">
<ThreadPrimitive.Empty>
<ThreadEmpty />
</ThreadPrimitive.Empty>
<TooltipProvider>
<ThreadPrimitive.Root className="flex h-full flex-col items-center pb-3">
<ThreadPrimitive.Viewport className="flex w-full flex-grow flex-col items-center overflow-y-scroll scroll-smooth px-4 pt-12">
<ThreadPrimitive.Empty>
<ThreadEmpty />
</ThreadPrimitive.Empty>

<ThreadPrimitive.Messages
components={{
UserMessage,
AssistantMessage,
}}
/>
</ThreadPrimitive.Viewport>
<ThreadPrimitive.Messages
components={{
UserMessage,
AssistantMessage,
}}
/>
</ThreadPrimitive.Viewport>

<Composer />
</ThreadPrimitive.Root>
<Composer />
</ThreadPrimitive.Root>
</TooltipProvider>
);
};

Expand All @@ -49,24 +52,25 @@ const Composer: FC = () => {
placeholder="Write a message..."
className="h-12 max-h-40 flex-grow resize-none bg-transparent p-3.5 text-sm outline-none placeholder:text-foreground/50"
/>
<ComposerPrimitive.Send className="m-2 flex h-8 w-8 items-center justify-center rounded-md bg-foreground font-bold text-2xl shadow transition-opacity disabled:opacity-10">
<SendHorizonalIcon className="size-4 text-background" />
</ComposerPrimitive.Send>
<ThreadPrimitive.If running={false}>
<ComposerPrimitive.Send className="m-2 flex h-8 w-8 items-center justify-center rounded-md bg-foreground font-bold text-2xl shadow transition-opacity disabled:opacity-10">
<SendHorizonalIcon className="size-4 text-background" />
</ComposerPrimitive.Send>
</ThreadPrimitive.If>
<ThreadPrimitive.If running>
<ComposerPrimitive.Cancel className="m-3.5 flex size-5 items-center justify-center rounded-full border-2 border-foreground">
<div className="size-2 rounded-[1px] bg-foreground" />
</ComposerPrimitive.Cancel>
</ThreadPrimitive.If>
</ComposerPrimitive.Root>
);
};

const UserMessage: FC = () => {
return (
<MessagePrimitive.Root className="relative flex w-full max-w-2xl gap-3 pb-12">
<Avatar>
<AvatarFallback>Y</AvatarFallback>
</Avatar>

<div className="flex-grow">
<p className="font-semibold">You</p>

<p className="whitespace-pre-line text-foreground">
<MessagePrimitive.Root className="relative mb-6 flex w-full max-w-2xl flex-col items-end gap-2 pl-24">
<div className="relative mr-1 flex items-start gap-3">
<p className="max-w-xl break-words whitespace-pre-line rounded-3xl bg-foreground/5 px-5 py-2.5 text-foreground">
<MessagePrimitive.Content />
</p>
</div>
Expand All @@ -76,15 +80,14 @@ const UserMessage: FC = () => {

const AssistantMessage: FC = () => {
return (
<MessagePrimitive.Root className="relative flex w-full max-w-2xl gap-3 pb-12">
<MessagePrimitive.Root className="relative mb-6 flex w-full max-w-2xl gap-3">
<Avatar>
<AvatarFallback>A</AvatarFallback>
</Avatar>

<div className="flex-grow">
<p className="font-semibold">Assistant</p>

<p className="whitespace-pre-line text-foreground">
<div className="mt-2 flex-grow">
<MessagePrimitive.InProgress className="inline-block size-3 animate-pulse rounded-full bg-foreground" />
<p className="max-w-xl break-words whitespace-pre-line text-foreground">
<MessagePrimitive.Content />
</p>
</div>
Expand Down

0 comments on commit 52236ab

Please sign in to comment.