chat

A basic chat component that can be used to display a simple chat conversation.

🙂
What's up? Got any plans?
🙃
Got nothing special going on, you?

Installation

npx shadcn add "https://registry.niels.foo/chat.json"

Source

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 import { SendHorizonal } from "lucide-react"; import { createContext, forwardRef, useContext } from "react"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { cn } from "@/lib/utils"; const AlignmentContext = createContext<"start" | "end">("start"); type ChatAvatarProps = React.HTMLAttributes<HTMLDivElement>; export function ChatAvatar({ className, children, ...props }: ChatAvatarProps) { const align = useContext(AlignmentContext); return ( <div className={cn( "flex aspect-square h-10 w-10 shrink-0 items-center justify-center overflow-hidden rounded-full p-2", align === "start" ? "rounded-br-none bg-neutral-100 dark:bg-neutral-800" : "rounded-bl-none bg-chat", className )} {...props} > {children} </div> ); } type ChatBubbleProps = React.HTMLAttributes<HTMLDivElement>; export function ChatBubble({ className, children, ...props }: ChatBubbleProps) { const align = useContext(AlignmentContext); return ( <div className={cn( "min-h-10 overflow-hidden rounded-xl px-3 py-2", align === "start" ? "rounded-bl-none bg-neutral-100 text-neutral-800 dark:bg-neutral-800 dark:text-neutral-100" : "rounded-br-none bg-chat text-chat-foreground", className )} {...props} > {children} </div> ); } type ChatMessageProps = React.HTMLAttributes<HTMLDivElement> & { align: "start" | "end"; }; export function ChatMessage({ children, className, align, ...props }: ChatMessageProps) { return ( <AlignmentContext.Provider value={align}> <div className={cn( "flex space-x-2", align === "end" && "flex-row-reverse space-x-reverse", className )} {...props} > {children} </div> </AlignmentContext.Provider> ); } type ChatProps = React.HTMLAttributes<HTMLDivElement>; export const Chat = forwardRef<HTMLDivElement, ChatProps>( ({ children, className, ...props }, ref) => { return ( <div ref={ref} className={cn( "flex w-full flex-1 flex-col space-y-4 overflow-y-auto sm:flex-none", className )} {...props} > {children} </div> ); } ); Chat.displayName = "Chat"; type ChatInputProps = React.InputHTMLAttributes<HTMLInputElement>; export const ChatInput = forwardRef<HTMLInputElement, ChatInputProps>( ({ className, ...props }, ref) => { return ( <Input ref={ref} type="text" className={cn("h-10 flex-grow rounded-xl", className)} {...props} /> ); } ); ChatInput.displayName = "ChatInput"; export function ChatSubmit({ className, children, ...props }: React.ButtonHTMLAttributes<HTMLButtonElement>) { return ( <Button type="submit" className={cn( "h-10 rounded-xl bg-chat hover:bg-chat/90 text-chat-foreground", className )} {...props} > {children || <SendHorizonal className="h-4 w-4" />} </Button> ); } type ChatPromptProps = React.HTMLAttributes<HTMLFormElement>; export const ChatForm = forwardRef<HTMLFormElement, ChatPromptProps>( ({ className, children, ...props }, ref) => { return ( <form ref={ref} className={cn("flex items-center space-x-2", className)} {...props} > {children} </form> ); } ); ChatForm.displayName = "ChatForm";