Message 会话消息
用于会话消息场景的 MoriUI 组件。
导入
import { Message, MessageAvatar, MessageContent, MessageFooter, MessageGroup, MessageHeader } from 'moriui'
示例
概览
展示聊天消息结构。
<script setup lang="ts">
import {
Avatar,
AvatarFallback,
AvatarImage,
Bubble,
BubbleContent,
Message,
MessageAvatar,
MessageContent,
MessageFooter
} from 'moriui'
</script>
<template>
<div class="flex w-full max-w-sm flex-col gap-6 py-12">
<Message align="end">
<MessageAvatar>
<Avatar>
<AvatarImage src="/avatars/10.png" alt="@me" />
<AvatarFallback>ME</AvatarFallback>
</Avatar>
</MessageAvatar>
<MessageContent>
<Bubble>
<BubbleContent>我快速部署到生产环境。</BubbleContent>
</Bubble>
</MessageContent>
</Message>
<Message>
<MessageAvatar>
<Avatar>
<AvatarImage src="/avatars/02.png" alt="@rabbit" />
<AvatarFallback>R</AvatarFallback>
</Avatar>
</MessageAvatar>
<MessageContent>
<Bubble variant="muted">
<BubbleContent>现在是周五下午 4:55。</BubbleContent>
</Bubble>
</MessageContent>
</Message>
<Message align="end">
<MessageAvatar>
<Avatar>
<AvatarImage src="/avatars/10.png" alt="@me" />
<AvatarFallback>ME</AvatarFallback>
</Avatar>
</MessageAvatar>
<MessageContent>
<Bubble>
<BubbleContent>只是一行代码改动。</BubbleContent>
</Bubble>
<MessageFooter>已送达</MessageFooter>
</MessageContent>
</Message>
<Message>
<MessageAvatar>
<Avatar>
<AvatarImage src="/avatars/02.png" alt="@rabbit" />
<AvatarFallback>R</AvatarFallback>
</Avatar>
</MessageAvatar>
<MessageContent>
<Bubble variant="muted">
<BubbleContent>每次都说只是一行改动 😭。</BubbleContent>
</Bubble>
<Bubble variant="muted">
<BubbleContent>好吧,让我看一下。</BubbleContent>
</Bubble>
</MessageContent>
</Message>
</div>
</template>
头像
消息发送者头像。
<script setup lang="ts">
import {
Avatar,
AvatarFallback,
AvatarImage,
Bubble,
BubbleContent,
Message,
MessageAvatar,
MessageContent
} from 'moriui'
</script>
<template>
<div class="flex w-full max-w-sm flex-col gap-6 py-12">
<Message>
<MessageAvatar>
<Avatar>
<AvatarImage src="/avatars/03.png" alt="@avatar" />
<AvatarFallback>R</AvatarFallback>
</Avatar>
</MessageAvatar>
<MessageContent>
<Bubble variant="muted">
<BubbleContent>构建在依赖安装阶段失败了。</BubbleContent>
</Bubble>
</MessageContent>
</Message>
<Message align="end">
<MessageAvatar>
<Avatar>
<AvatarImage src="/avatars/10.png" alt="@avatar" />
<AvatarFallback>R</AvatarFallback>
</Avatar>
</MessageAvatar>
<MessageContent>
<Bubble>
<BubbleContent>可以分享具体的错误信息吗?</BubbleContent>
</Bubble>
</MessageContent>
</Message>
<Message>
<MessageAvatar>
<Avatar>
<AvatarImage src="/avatars/03.png" alt="@avatar" />
<AvatarFallback>R</AvatarFallback>
</Avatar>
</MessageAvatar>
<MessageContent>
<Bubble variant="muted">
<BubbleContent>这是日志中的错误信息。</BubbleContent>
</Bubble>
<Bubble variant="muted">
<BubbleContent>构建出现问题,依赖库未正确安装,请尝试重新构建。</BubbleContent>
</Bubble>
</MessageContent>
</Message>
</div>
</template>
消息组
连续消息分组排列。
<script setup lang="ts">
import {
Avatar,
AvatarFallback,
AvatarImage,
Bubble,
BubbleContent,
Message,
MessageAvatar,
MessageContent,
MessageGroup
} from 'moriui'
</script>
<template>
<div class="flex w-full max-w-sm flex-col gap-6 py-12">
<MessageGroup>
<Message>
<MessageAvatar />
<MessageContent>
<Bubble variant="muted">
<BubbleContent>我已经检查过注册表地址了。</BubbleContent>
</Bubble>
</MessageContent>
</Message>
<Message>
<MessageAvatar>
<Avatar>
<AvatarImage src="/avatars/02.png" alt="@avatar" />
<AvatarFallback>CN</AvatarFallback>
</Avatar>
</MessageAvatar>
<MessageContent>
<Bubble variant="muted">
<BubbleContent>组件和示例 JSON 已经部署到 UI 注册表中。</BubbleContent>
</Bubble>
</MessageContent>
</Message>
</MessageGroup>
</div>
</template>
头部与底部
消息的头部和底部信息。
<script setup lang="ts">
import {
Bubble,
BubbleContent,
Message,
MessageContent,
MessageFooter,
MessageHeader
} from 'moriui'
</script>
<template>
<div class="flex w-full max-w-sm flex-col gap-8 py-12">
<Message>
<MessageContent>
<MessageHeader>Olivia</MessageHeader>
<Bubble variant="muted">
<BubbleContent>我已经检查过日志了。</BubbleContent>
</Bubble>
</MessageContent>
</Message>
<Message align="end">
<MessageContent>
<Bubble>
<BubbleContent>把报告发送给团队。需要帮助的话联系 @shadcn。</BubbleContent>
</Bubble>
<MessageFooter>
<div>
已读 · <span class="font-normal">昨天</span>
</div>
</MessageFooter>
</MessageContent>
</Message>
</div>
</template>
操作
消息上的交互操作。
<script setup lang="ts">
import { Copy, RefreshCcw, ThumbsDown, ThumbsUp } from '@lucide/vue'
import {
Bubble,
BubbleContent,
Button,
Message,
MessageContent,
MessageFooter
} from 'moriui'
</script>
<template>
<div class="flex w-full max-w-sm flex-col gap-8 py-12">
<Message>
<MessageContent>
<Bubble variant="muted">
<BubbleContent>安装失败的原因在于工作区依赖。</BubbleContent>
</Bubble>
<MessageFooter>
<Button
variant="ghost"
size="icon"
aria-label="复制"
title="复制"
>
<Copy />
</Button>
<Button
variant="ghost"
size="icon"
aria-label="赞同"
title="赞同"
>
<ThumbsUp />
</Button>
<Button
variant="ghost"
size="icon"
aria-label="反对"
title="反对"
>
<ThumbsDown />
</Button>
</MessageFooter>
</MessageContent>
</Message>
<Message align="end">
<MessageContent>
<Bubble>
<BubbleContent>好的,把链接发给我,我看一下……</BubbleContent>
</Bubble>
<MessageFooter class="gap-2">
<span class="font-normal text-destructive">发送失败</span>
<Button
variant="ghost"
size="icon-xs"
title="重试"
aria-label="重试"
>
<RefreshCcw />
</Button>
</MessageFooter>
</MessageContent>
</Message>
</div>
</template>
附件
消息中的文件附件。
<script setup lang="ts">
import { Download, FileText } from '@lucide/vue'
import {
Attachment,
AttachmentAction,
AttachmentActions,
AttachmentContent,
AttachmentDescription,
AttachmentMedia,
AttachmentTitle,
Bubble,
BubbleContent,
Message,
MessageContent
} from 'moriui'
</script>
<template>
<div class="flex w-full max-w-sm flex-col gap-8 py-12">
<Message align="end">
<MessageContent>
<Attachment orientation="vertical">
<AttachmentMedia variant="image">
<img
src="https://images.unsplash.com/photo-1497366754035-f200968a6e72?w=900&auto=format&fit=crop&q=80"
alt="办公空间"
>
</AttachmentMedia>
</Attachment>
<Bubble>
<BubbleContent>
这是图片,可以把它加进 PDF 作为封面页吗?
</BubbleContent>
</Bubble>
</MessageContent>
</Message>
<Message>
<MessageContent>
<Bubble variant="muted">
<BubbleContent>
已完成,这是添加了封面图片的 PDF。
</BubbleContent>
</Bubble>
<Attachment>
<AttachmentMedia>
<FileText />
</AttachmentMedia>
<AttachmentContent>
<AttachmentTitle>数据看板.pdf</AttachmentTitle>
<AttachmentDescription>PDF · 2.4 MB</AttachmentDescription>
</AttachmentContent>
<AttachmentActions>
<AttachmentAction
type="button"
title="下载"
aria-label="下载"
size="icon-sm"
variant="secondary"
>
<Download />
</AttachmentAction>
</AttachmentActions>
</Attachment>
</MessageContent>
</Message>
<Message align="end">
<MessageContent>
<Bubble>
<BubbleContent>谢谢,看起来不错。</BubbleContent>
</Bubble>
</MessageContent>
</Message>
</div>
</template>
Markdown
渲染 Markdown 内容。
<script setup lang="ts">
import {
Bubble,
BubbleContent,
Message,
MessageContent
} from 'moriui'
const response = `以下是在消息中渲染 Markdown 的方法:
1. 将助手的文本通过 **Markdown** 组件渲染。
2. 用户消息保持纯文本形式。
3. 使用 \`ghost\` 气泡使回复无边框显示。`
</script>
<template>
<div class="flex w-full max-w-sm flex-col gap-8 py-12">
<Message align="end">
<MessageContent>
<Bubble>
<BubbleContent>
如何在消息中渲染 Markdown?
</BubbleContent>
</Bubble>
</MessageContent>
</Message>
<Message>
<MessageContent>
<Bubble variant="ghost">
<BubbleContent>
<!-- 实际项目中使用 Markdown 组件渲染,此处为静态演示 -->
{{ response }}
</BubbleContent>
</Bubble>
</MessageContent>
</Message>
</div>
</template>
使用说明
组合方式
Message 组合 Header、Avatar、Content 与 Footer 组成完整聊天消息;MessageGroup 组织连续消息。
对齐
通过 align 控制消息在流中的位置(start/end)。
RTL
消息内容沿 dir 排列。
变体
Message 的 variant 支持 default/secondary/tinted,align 支持 start/end。
可访问性
消息列表应由页面提供 log/list 等上下文。消息时间戳和发送者信息应可被辅助技术理解。可交互的消息元素应使用 button 或 a。
API 参考
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
Message variant | 'default' | 'secondary' | 'tinted' | 'default' | 消息视觉层级。 |
Message align | 'start' | 'end' | 'start' | 消息对齐方向。 |
MessageHeader class | HTMLAttributes["class"] | undefined | 合并到消息头部的调用方类。 |
MessageAvatar class | HTMLAttributes["class"] | undefined | 合并到头像区域的调用方类。 |
MessageContent class | HTMLAttributes["class"] | undefined | 合并到消息内容的调用方类。 |
MessageFooter class | HTMLAttributes["class"] | undefined | 合并到消息底部的调用方类。 |
MessageGroup class | HTMLAttributes["class"] | undefined | 合并到消息分组的调用方类。 |