|
| 1 | +<script setup lang="ts"> |
| 2 | +import { Action, Actions } from '@repo/elements/actions' |
| 3 | +import { Conversation, ConversationContent } from '@repo/elements/conversation' |
| 4 | +import { Message, MessageContent } from '@repo/elements/message' |
| 5 | +import { Copy, RefreshCcw, Share, ThumbsDown, ThumbsUp } from 'lucide-vue-next' |
| 6 | +import { nanoid } from 'nanoid' |
| 7 | +import { ref } from 'vue' |
| 8 | +
|
| 9 | +interface MsgItem { |
| 10 | + key: string |
| 11 | + from: 'user' | 'assistant' |
| 12 | + content: string |
| 13 | + avatar: string |
| 14 | + name: string |
| 15 | +} |
| 16 | +
|
| 17 | +const messages: MsgItem[] = [ |
| 18 | + { |
| 19 | + key: nanoid(), |
| 20 | + from: 'user', |
| 21 | + content: 'Hello, how are you?', |
| 22 | + avatar: 'https://github.com/haydenbleasel.png', |
| 23 | + name: 'Hayden Bleasel', |
| 24 | + }, |
| 25 | + { |
| 26 | + key: nanoid(), |
| 27 | + from: 'assistant', |
| 28 | + content: 'I am fine, thank you!', |
| 29 | + avatar: 'https://github.com/openai.png', |
| 30 | + name: 'OpenAI', |
| 31 | + }, |
| 32 | +] |
| 33 | +
|
| 34 | +const liked = ref(false) |
| 35 | +const disliked = ref(false) |
| 36 | +
|
| 37 | +function handleRetry() {} |
| 38 | +function handleCopy() {} |
| 39 | +function handleShare() {} |
| 40 | +
|
| 41 | +const actions = [ |
| 42 | + { icon: RefreshCcw, label: 'Retry', onClick: handleRetry }, |
| 43 | + { icon: ThumbsUp, label: 'Like', onClick: () => (liked.value = !liked.value) }, |
| 44 | + { icon: ThumbsDown, label: 'Dislike', onClick: () => (disliked.value = !disliked.value) }, |
| 45 | + { icon: Copy, label: 'Copy', onClick: () => handleCopy() }, |
| 46 | + { icon: Share, label: 'Share', onClick: () => handleShare() }, |
| 47 | +] |
| 48 | +</script> |
| 49 | + |
| 50 | +<template> |
| 51 | + <Conversation class="relative w-full"> |
| 52 | + <ConversationContent> |
| 53 | + <Message |
| 54 | + v-for="message in messages" |
| 55 | + :key="message.key" |
| 56 | + :from="message.from" |
| 57 | + class="flex flex-col gap-2" |
| 58 | + :class="message.from === 'assistant' ? 'items-start' : 'items-end'" |
| 59 | + > |
| 60 | + <MessageContent>{{ message.content }}</MessageContent> |
| 61 | + <Actions v-if="message.from === 'assistant'" class="mt-2"> |
| 62 | + <Action v-for="action in actions" :key="action.label" :label="action.label" @click="action.onClick"> |
| 63 | + <component :is="action.icon" class="size-4" /> |
| 64 | + </Action> |
| 65 | + </Actions> |
| 66 | + </Message> |
| 67 | + </ConversationContent> |
| 68 | + </Conversation> |
| 69 | +</template> |
0 commit comments