message.tsx 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. import { cn } from '../../utils'
  2. import type { UIMessage } from 'ai'
  3. import { cva, type VariantProps } from 'class-variance-authority'
  4. import type { HTMLAttributes } from 'react'
  5. export type MessageProps = HTMLAttributes<HTMLDivElement> & {
  6. from: UIMessage['role']
  7. }
  8. export const Message = ({ className, from, ...props }: MessageProps) => (
  9. <div
  10. className={cn(
  11. 'group flex w-full items-end justify-end gap-2 py-4',
  12. from === 'user' ? 'is-user' : 'is-assistant flex-row-reverse justify-end',
  13. className
  14. )}
  15. {...props}
  16. />
  17. )
  18. const messageContentVariants = cva(
  19. 'is-user:dark flex flex-col gap-2 overflow-hidden rounded-lg text-sm',
  20. {
  21. variants: {
  22. variant: {
  23. contained: [
  24. 'max-w-[80%] px-4 py-3',
  25. 'group-[.is-user]:bg-primary group-[.is-user]:text-primary-foreground',
  26. 'group-[.is-assistant]:bg-secondary group-[.is-assistant]:text-foreground',
  27. ],
  28. flat: [
  29. 'group-[.is-user]:max-w-[80%] group-[.is-user]:bg-secondary group-[.is-user]:px-4 group-[.is-user]:py-3 group-[.is-user]:text-foreground',
  30. 'group-[.is-assistant]:text-foreground',
  31. ],
  32. },
  33. },
  34. defaultVariants: {
  35. variant: 'contained',
  36. },
  37. }
  38. )
  39. export type MessageContentProps = HTMLAttributes<HTMLDivElement> &
  40. VariantProps<typeof messageContentVariants>
  41. export const MessageContent = ({
  42. children,
  43. className,
  44. variant,
  45. ...props
  46. }: MessageContentProps) => (
  47. <div
  48. className={cn(messageContentVariants({ variant, className }))}
  49. {...props}
  50. >
  51. {children}
  52. </div>
  53. )